From nobody at rubyforge.org Fri Dec 1 07:30:57 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 1 Dec 2006 07:30:57 -0500 (EST)
Subject: [Archipelago-submits] [88] trunk/archipelago/TODO: more TODO
Message-ID: <20061201123057.54BC95240E36@rubyforge.org>
Revision: 88
Author: zond
Date: 2006-12-01 07:30:56 -0500 (Fri, 01 Dec 2006)
Log Message:
-----------
more TODO
Modified Paths:
--------------
trunk/archipelago/TODO
Modified: trunk/archipelago/TODO
===================================================================
--- trunk/archipelago/TODO 2006-11-30 22:06:57 UTC (rev 87)
+++ trunk/archipelago/TODO 2006-12-01 12:30:56 UTC (rev 88)
@@ -1,16 +1,23 @@
- * Create a new HashishProvider with built in redundancy,
- for example using the Chord project: http://pdos.csail.mit.edu/chord/
+ * Create a failover/redundancy framework
+ * For example: Create a new HashishProvider with built in redundancy,
+ for example using the Chord project: http://pdos.csail.mit.edu/chord/
+ * Or: Create migration methods that move objects between Chests opon
+ startup and shutdown, and make them keep backups at each others
+ persistence backends.
* Make Chest aware about whether transactions have affected it 'for real' ie
check whether the instance before the call differs from the instance after
the call. Preferably without incurring performance lossage.
+ * For example: Make Dubloon proxy targets able to provide a dirty_state
+ method that decide whether they are to be considered dirty, clean or auto-select.
- * Make Dubloon proxy targets able to provide a dirty_state method that decides
- whether they are to be considered dirty, clean or auto-select.
-
* Test the transaction recovery mechanism of Chest.
- * Make Archipelago::Treasure::Dubloons work after an Archipelago::Treasure::Chest
- has rebooted. For example: demand that the chest always run the same host+port
- or make Dubloons able to lookup their home Chest by service_id.
+ * Create a memcached-starter that publishes the address to the started memcached
+ instance on the Disco network.
+
+ * Create a memcached-client that uses Disco instance to find all memcached instances
+ in the network and distribute requests among them.
+
+ * Create a validation framework for Hyperactive::Record::Bass
From nobody at rubyforge.org Fri Dec 1 10:10:35 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 1 Dec 2006 10:10:35 -0500 (EST)
Subject: [Archipelago-submits] [89] trunk/hyperactive: stage one in cleaning
up Hyperactive::Record::Bass
Message-ID: <20061201151035.D2F605241319@rubyforge.org>
Revision: 89
Author: zond
Date: 2006-12-01 10:10:35 -0500 (Fri, 01 Dec 2006)
Log Message:
-----------
stage one in cleaning up Hyperactive::Record::Bass
Modified Paths:
--------------
trunk/hyperactive/README
trunk/hyperactive/lib/hyperactive/hash.rb
trunk/hyperactive/lib/hyperactive/hooker.rb
trunk/hyperactive/lib/hyperactive/index.rb
trunk/hyperactive/lib/hyperactive/list.rb
trunk/hyperactive/lib/hyperactive/record.rb
trunk/hyperactive/lib/hyperactive/transactions.rb
trunk/hyperactive/tests/record_test.rb
Modified: trunk/hyperactive/README
===================================================================
--- trunk/hyperactive/README 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/README 2006-12-01 15:10:35 UTC (rev 89)
@@ -7,15 +7,21 @@
Hyperactive::Record:: The base class package itself, providing you with cached selectors and rejectors, along with cached finders for any number of attributes.
Hyperactive::Hash:: A collection class that contains any number of Hyperactive::Records in a hash like structure.
Hyperactive::List:: A collection class that contains any number of Hyperactive::Records in a list like structure.
+Hyperactive::Index:: A module included into Hyperactive::Record that adds simple indexing capabilities of the find_by_... type.
+Hyperactive::Transactions:: A module included into Hyperactive::Record that adds a few simplifications in handling transactions properly.
== Usage:
To use Hyperactive in the simplest way, just run the script/services.rb script from the Archipelago
distribution to get a few services running, then subclass Hyperactive::Record::Bass and create
-objects with MyBassSubclass.get_instance (not new!). They will be automagically
-stored in the network, and fetchable via their instance.record_id.
+objects with MyBassSubclass.get_instance. They will be automagically stored in the network,
+and fetchable via their instance.record_id.
-By loading Hyperactive::Record you will automatically define Hyperactive::Record::CAPTAIN which will
+You can also use new of course, but beware that this will not store the object persistently
+or give you a proxy. Both of these things are good for you, so use get_instance unless you know
+what you are doing.
+
+By loading Hyperactive::Record you will automatically define Hyperactive::CAPTAIN which will
be an Archipelago::Pirate::Captain that is your interface to the distributed database.
== Examples:
Modified: trunk/hyperactive/lib/hyperactive/hash.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-01 15:10:35 UTC (rev 89)
@@ -62,6 +62,7 @@
# NB: Remember to call create on the new instance or use Head.get_instance to get that done automatically.
#
def initialize
+ super
self.list = nil
end
@@ -73,6 +74,13 @@
end
#
+ # Return whether this Hash is empty.
+ #
+ def empty?
+ self.list.empty?
+ end
+
+ #
# Return the value for +key+.
#
def [](key)
Modified: trunk/hyperactive/lib/hyperactive/hooker.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/hooker.rb 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/lib/hyperactive/hooker.rb 2006-12-01 15:10:35 UTC (rev 89)
@@ -19,62 +19,172 @@
module Hyperactive
#
- # A utility method to simplify using around-hooks for any block.
+ # A container of utility hook methods.
#
module Hooker
#
- # Will call each hook in +hooks+ with a block that
- # calls the rest of the +hooks+ with +argument+ as argument
- # and after that yields to the given +block+.
+ # Something that uses hooks a lot, include if you want support for various types of hooks.
#
- # This will allow you wrap any method call in a dynamic set
- # of other methods.
- #
- # For more examples, see Hyperactive::Record.
- #
- # Example:
- # class ImportantStuff
- # attr_accessor :timestamp
- # def is_valid?
- # # do nifty stuff
- # end
- # def notify_someone_that_i_am_changed!(message)
- # # do even more nifty stuff
- # end
- # def validate_and_notify(message)
- # raise "i am invalid!" unless is_valid?
- # yield
- # notify_someone_that_i_am_changed!(message)
- # end
- # def do_save
- # # save me in persistent storage
- # end
- # end
- # class ImportantHandler
- # def update_timestamp(important_stuff_instance)
- # important_stuff_instance.timestamp = Time.now
- # Hyperactive::Hooker.call_with_hooks("changed at #{Time.now}",
- # important_stuff_instance.method(:validate_and_notify)) do
- # important_stuff_instance.do_save
- # end
- # end
- # end
- #
- def call_with_hooks(argument, *hooks, &block)
- if hooks.empty?
- yield
- else
- first = hooks.first
- rest = hooks[1..-1]
- first.call(argument) do
- call_with_hooks(argument, *rest, &block)
+ module Pimp
+
+ #
+ # Upon inclusion, our +base+ class will be given a set of hook
+ # arrays, and then get extended by ClassMethods.
+ #
+ def self.append_features(base)
+ super
+ base.instance_variable_set(:@create_hooks, [])
+ base.instance_variable_set(:@destroy_hooks, [])
+ base.instance_variable_set(:@save_hooks, [])
+ base.instance_variable_set(:@load_hooks, [])
+ base.extend(ClassMethods)
+ end
+
+ #
+ # This will allow us to wrap any write of us to persistent storage
+ # in the @save_hooks as long as the Archipelago::Hashish provider
+ # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
+ # of Hashish providers that do this.
+ #
+ def save_hook(old_value, &block)
+ self.class.with_hooks(:instance => self, :arguments => [old_value], :hooks => self.class.save_hooks) do
+ yield
end
end
+
+ #
+ # This will allow us to wrap any load of us from persistent storage
+ # in the @@load_hooks as long as the Archipelago::Hashish provider
+ # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
+ # of Hashish providers that do this.
+ #
+ def load_hook(&block)
+ self.class.with_hooks(:instance => self, :hooks => self.class.load_hooks) do
+ yield
+ end
+ end
+
+
+ #
+ # The class methods of a Pimp.
+ #
+ module ClassMethods
+
+ #
+ # Will wrap a block within nested calls to given hooks.
+ #
+ # Parameters:
+ # * :instance: An instance to send methods to, defaults to self
+ # * :arguments: Extra arguments to send to whatever we call, defaults to self
+ # * :hooks: An Array of hook objects. They can be either Strings or Symbols, or
+ # whatever else can be given to respond_to?, or they can be anything
+ # that respond_to?(:call). If the hook is something that
+ # respond_to?(:call) it will be called and given
+ # the the :instance and *:arguments and the provided +block+.
+ # Else the :instance.respond_to?(the given hook)
+ # must be true, and that :instance will be sent the given hook along with the :arguments and
+ # a block that does the rest of the hooks.
+ #
+ def with_hooks(options = {}, &block)
+ instance = options[:instance] || self
+ arguments = options[:arguments] || []
+ hooks = options[:hooks] || []
+
+ if hooks.empty?
+ yield
+ else
+ first = hooks.first
+ rest = hooks[1..-1]
+ if first.respond_to?(:call)
+ first.call(instance, *arguments) do
+ with_hooks(:instance => instance, :hooks => rest, :arguments => arguments, &block)
+ end
+ elsif instance.respond_to?(first)
+ instance.send(first, *arguments) do
+ with_hooks(:instance => instance, :hooks => rest, :arguments => arguments, &block)
+ end
+ else
+ raise "You can only send in hooks that are Symbols in the given instance or call'able objects"
+ end
+ end
+ end
+
+ #
+ # Upon inheritance, our +subclass+ will be given copies of our hooks.
+ #
+ def inherited(subclass)
+ subclass.instance_variable_set(:@create_hooks, @create_hooks.clone)
+ subclass.instance_variable_set(:@destroy_hooks, @destroy_hooks.clone)
+ subclass.instance_variable_set(:@save_hooks, @save_hooks.clone)
+ subclass.instance_variable_set(:@load_hooks, @load_hooks.clone)
+ end
+
+ #
+ # Return our create_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent the instance about to be created (initial
+ # insertion into the database system) that take a block argument.
+ #
+ # The block argument will be a Proc that actually injects the
+ # instance into the database system.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon creation.
+ #
+ attr_reader :create_hooks
+
+ #
+ # Return our destroy_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent the instance about to be destroyed (removal
+ # from the database system) that take a block argument.
+ #
+ # The block argument will be a Proc that actually removes the
+ # instance from the database system.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon destruction.
+ #
+ attr_reader :destroy_hooks
+
+ #
+ # Return our load_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent the instance about to be loaded (insertion
+ # into the live hash of the database in question) that take a block argument.
+ #
+ # The block argument will be a Proc that actually puts the
+ # instance into the live hash.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon loading.
+ #
+ attr_reader :load_hooks
+
+ #
+ # Return our save_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent [the old version, the new version] of the
+ # instance about to be saved (storage into the database system)
+ # along with a block argument.
+ #
+ # The block argument will be a Proc that actually saves the
+ # instance into the database system.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon saving.
+ #
+ attr_reader :save_hooks
+
+ end
+
end
- module_function :call_with_hooks
-
end
end
Modified: trunk/hyperactive/lib/hyperactive/index.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/index.rb 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/lib/hyperactive/index.rb 2006-12-01 15:10:35 UTC (rev 89)
@@ -41,16 +41,16 @@
# If the +argument+ is an Array then we know we are a save hook,
# otherwise we are a destroy hook.
#
- def call(argument, &block)
+ def call(*arguments, &block)
yield
#
# If the argument is an Array (of old value, new value)
# then we are a save hook, otherwise a destroy hook.
#
- if Array === argument
- record = argument.last
- old_record = argument.first
+ if arguments.size > 1
+ record = arguments.first
+ old_record = arguments.last
old_key = get_key_for(old_record)
new_key = get_key_for(record)
if old_key != new_key
@@ -58,7 +58,7 @@
(CAPTAIN[new_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction))[record.record_id] = record
end
else
- record = argument
+ record = arguments.first
(CAPTAIN[get_key_for(record)] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
end
end
@@ -83,11 +83,10 @@
# may save record in the Hash-like container named @key in
# the main database after having yielded to +block+.
#
- def call(argument, &block)
+ def call(*arguments, &block)
yield
- record = argument
- record = argument.last if Array === argument
+ record = arguments.first
case @mode
when :select
@@ -147,19 +146,15 @@
# is defined.
#
def select(name, &block) #:yields: instance
- key = self.collection_key(name)
+ key = collection_key(name)
CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
self.class.class_eval do
define_method(name) do
CAPTAIN[key]
end
end
- self.save_hooks << MatchSaver.new(key, Proc.new do |arg|
- yield(arg)
- end, :select)
- self.destroy_hooks << MatchSaver.new(key, Proc.new do |arg|
- yield(arg)
- end, :delete_if_match)
+ self.save_hooks << MatchSaver.new(key, block, :select)
+ self.destroy_hooks << MatchSaver.new(key, block, :delete_if_match)
end
#
@@ -169,22 +164,27 @@
# rejector is defined.
#
def reject(name, &block) #:yields: instance
- key = self.collection_key(name)
+ key = collection_key(name)
CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
self.class.class_eval do
define_method(name) do
CAPTAIN[key]
end
end
- self.save_hooks << MatchSaver.new(key, Proc.new do |arg|
- yield(arg)
- end, :reject)
- self.destroy_hooks << MatchSaver.new(key, Proc.new do |arg|
- yield(arg)
- end, :delete_unless_match)
+ self.save_hooks << MatchSaver.new(key, block, :reject)
+ self.destroy_hooks << MatchSaver.new(key, block, :delete_unless_match)
end
+
+ private
+
+ #
+ # The key used to store the collection with the given +sym+ as name.
+ #
+ def collection_key(sym)
+ "Hyperactive::Index::Indexable::collection_key::#{sym}"
+ end
+
-
end
end
Modified: trunk/hyperactive/lib/hyperactive/list.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/list.rb 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/lib/hyperactive/list.rb 2006-12-01 15:10:35 UTC (rev 89)
@@ -70,6 +70,7 @@
# NB: Remember to call create on the new instance or use Head.get_instance to get that done automatically.
#
def initialize
+ super
self.size = 0
self.first_element = self.last_element = nil
end
@@ -103,6 +104,13 @@
end
#
+ # Return whether this List is empty.
+ #
+ def empty?
+ return self.size == 0
+ end
+
+ #
# Remove all elements from this List::Head.
#
def clear!
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-01 15:10:35 UTC (rev 89)
@@ -51,87 +51,15 @@
include Hyperactive::Index::Indexable
include Hyperactive::Transactions::Accessors
+ include Hyperactive::Transactions::Participant
+ include Hyperactive::Hooker::Pimp
- @@create_hooks_by_class = {}
- @@destroy_hooks_by_class = {}
- @@save_hooks_by_class = {}
- @@load_hooks_by_class = {}
-
#
# The host we are running on.
#
HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
#
- # Return our create_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent the instance about to be created (initial
- # insertion into the database system) that take a block argument.
- #
- # The block argument will be a Proc that actually injects the
- # instance into the database system.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon creation.
- #
- def self.create_hooks
- self.get_hook_array_by_class(@@create_hooks_by_class)
- end
-
- #
- # Return our destroy_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent the instance about to be destroyed (removal
- # from the database system) that take a block argument.
- #
- # The block argument will be a Proc that actually removes the
- # instance from the database system.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon destruction.
- #
- def self.destroy_hooks
- self.get_hook_array_by_class(@@destroy_hooks_by_class)
- end
-
- #
- # Return our load_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent the instance about to be loaded (insertion
- # into the live hash of the database in question) that take a block argument.
- #
- # The block argument will be a Proc that actually puts the
- # instance into the live hash.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon loading.
- #
- def self.load_hooks
- self.get_hook_array_by_class(@@load_hooks_by_class)
- end
-
- #
- # Return our save_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent [the old version, the new version] of the
- # instance about to be saved (storage into the database system)
- # along with a block argument.
- #
- # The block argument will be a Proc that actually saves the
- # instance into the database system.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon saving.
- #
- def self.save_hooks
- self.get_hook_array_by_class(@@save_hooks_by_class)
- end
-
- #
# Return the record with +record_id+, optionally within a +transaction+.
#
def self.find(record_id, transaction = nil)
@@ -147,21 +75,14 @@
end
#
- # Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
+ # Our semi-unique id.
#
- def self.get_instance_with_transaction(transaction, *args)
- instance = self.new(*args)
- return_value = nil
- instance.with_transaction(transaction) do
- return_value = instance.create
- end
- return return_value
- end
-
+ attr_reader :record_id
+
#
- # Our semi-unique id.
+ # The transaction we are currently in.
#
- attr_reader :record_id, :transaction
+ attr_reader :transaction
#
# Utility compare method. Override as you please.
@@ -173,6 +94,11 @@
0
end
end
+
+ def initialize
+ @record_id = nil
+ @transaction = nil
+ end
#
# Save this Record instance into the distributed database and return a proxy to the saved object.
@@ -182,8 +108,8 @@
def create
@record_id ||= Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}").to_s
@transaction ||= nil
-
- Hyperactive::Hooker.call_with_hooks(self, *self.class.create_hooks) do
+
+ self.class.with_hooks(:instance => self, :hooks => self.class.create_hooks) do
CAPTAIN[self.record_id, @transaction] = self
end
@@ -193,92 +119,17 @@
end
#
- # Will execute +block+ within a transaction.
- #
- # What it does is just set the @transaction instance variable
- # before calling the block, and unsetting it after.
- #
- # This means that any classes that want to be transaction sensitive
- # need to take heed regarding the @transaction instance variable.
- #
- # For example, when creating new Record instances you may want to use
- # get_instance_with_transaction(@transaction, *args) to ensure that the
- # new instance exists within the same transaction as yourself.
- #
- # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
- #
- def with_transaction(transaction, &block)
- @transaction = transaction
- begin
- yield
- ensure
- @transaction = nil
- end
- end
-
- #
- # This will allow us to wrap any write of us to persistent storage
- # in the @@save_hooks as long as the Archipelago::Hashish provider
- # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
- # of Hashish providers that do this.
- #
- def save_hook(old_value, &block)
- Hyperactive::Hooker.call_with_hooks([old_value, self], *self.class.save_hooks) do
- yield
- end
- end
-
- #
- # This will allow us to wrap any load of us from persistent storage
- # in the @@load_hooks as long as the Archipelago::Hashish provider
- # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
- # of Hashish providers that do this.
- #
- def load_hook(&block)
- Hyperactive::Hooker.call_with_hooks(self, *self.class.load_hooks) do
- yield
- end
- end
-
- #
# Remove this instance from the database wrapped in our destroy_hooks.
#
# Freezes this instance after having deleted it.
#
def destroy!
- Hyperactive::Hooker.call_with_hooks(self, *self.class.destroy_hooks) do
+ self.class.with_hooks(:instance => self, :hooks => self.class.destroy_hooks) do
CAPTAIN.delete(@record_id, @transaction)
self.freeze
end
end
- private
-
- #
- # The key used to store the collection with the given +sym+ as name.
- #
- def self.collection_key(sym)
- "Hyperactive::Record::Bass::collection_key::#{sym}"
- end
-
- #
- # Get an Array from +hash+ using self as
- # key. If self doesnt exist in the +hash+
- # it will recurse by calling the same method in the
- # superclass until it has been called in Hyperactive::Record::Base.
- #
- def self.get_hook_array_by_class(hash)
- return hash[self] if hash.include?(self)
-
- if self == Bass
- hash[self] = []
- return self.get_hook_array_by_class(hash)
- else
- hash[self] = self.superclass.get_hook_array_by_class(hash).clone
- return self.get_hook_array_by_class(hash)
- end
- end
-
end
end
end
Modified: trunk/hyperactive/lib/hyperactive/transactions.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-01 15:10:35 UTC (rev 89)
@@ -1,15 +1,58 @@
module Hyperactive
+ #
+ # A utility package of transaction handling methods.
+ #
module Transactions
+
+ #
+ # Include this to get methods to do with participating in a transaction.
+ #
+ module Participant
+
+ #
+ # Will execute +block+ within a transaction.
+ #
+ # What it does is just set the @transaction instance variable
+ # before calling the block, and unsetting it after.
+ #
+ # This means that any classes that want to be transaction sensitive
+ # need to take heed regarding the @transaction instance variable.
+ #
+ # For example, when creating new Record instances you may want to use
+ # get_instance_with_transaction(@transaction, *args) to ensure that the
+ # new instance exists within the same transaction as yourself.
+ #
+ # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
+ #
+ def with_transaction(transaction, &block)
+ @transaction = transaction
+ begin
+ yield
+ ensure
+ @transaction = nil
+ end
+ end
+
+ end
+ #
+ # Include this to get the default attr_reader at al redefined to be transactionally aware.
+ #
module Accessors
-
+
+ #
+ # The +base+ class including this will get a our ClassMethods as well.
+ #
def self.append_features(base)
super
base.extend(ClassMethods)
end
+ #
+ # The class methods that help us set/get instance variables in a transactionally aware way.
+ #
module ClassMethods
#
# Works like normal attr_reader but with transactional awareness.
Modified: trunk/hyperactive/tests/record_test.rb
===================================================================
--- trunk/hyperactive/tests/record_test.rb 2006-12-01 12:30:56 UTC (rev 88)
+++ trunk/hyperactive/tests/record_test.rb 2006-12-01 15:10:35 UTC (rev 89)
@@ -6,7 +6,7 @@
def initialize
@bajs = nil
end
- def self.save_hook(instance, &block)
+ def self.save_hook(instance, old_value, &block)
$BEFORE_SAVE += 1
yield
$AFTER_SAVE += 1
From nobody at rubyforge.org Fri Dec 1 10:20:50 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 1 Dec 2006 10:20:50 -0500 (EST)
Subject: [Archipelago-submits] [90] trunk/hyperactive/lib/hyperactive: added
GPL-2 licenses.
Message-ID: <20061201152050.E0B7952410A8@rubyforge.org>
Revision: 90
Author: zond
Date: 2006-12-01 10:20:50 -0500 (Fri, 01 Dec 2006)
Log Message:
-----------
added GPL-2 licenses. moved more stuff to modules
Modified Paths:
--------------
trunk/hyperactive/lib/hyperactive/index.rb
trunk/hyperactive/lib/hyperactive/record.rb
trunk/hyperactive/lib/hyperactive/transactions.rb
Modified: trunk/hyperactive/lib/hyperactive/index.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/index.rb 2006-12-01 15:10:35 UTC (rev 89)
+++ trunk/hyperactive/lib/hyperactive/index.rb 2006-12-01 15:20:50 UTC (rev 90)
@@ -1,3 +1,19 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module Hyperactive
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-01 15:10:35 UTC (rev 89)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-01 15:20:50 UTC (rev 90)
@@ -80,11 +80,6 @@
attr_reader :record_id
#
- # The transaction we are currently in.
- #
- attr_reader :transaction
-
- #
# Utility compare method. Override as you please.
#
def <=>(o)
Modified: trunk/hyperactive/lib/hyperactive/transactions.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-01 15:10:35 UTC (rev 89)
+++ trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-01 15:20:50 UTC (rev 90)
@@ -1,3 +1,19 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module Hyperactive
@@ -12,6 +28,11 @@
module Participant
#
+ # The transaction we are currently in.
+ #
+ attr_reader :transaction
+
+ #
# Will execute +block+ within a transaction.
#
# What it does is just set the @transaction instance variable
@@ -35,6 +56,32 @@
end
end
+ #
+ # Add our ClassMethods to anyone that includes us.
+ #
+ def self.append_features(base)
+ super
+ base.extend(ClassMethods)
+ end
+
+ #
+ # Class methods for transaction participants.
+ #
+ module ClassMethods
+ #
+ # Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
+ #
+ def get_instance_with_transaction(transaction, *args)
+ instance = self.new(*args)
+ return_value = nil
+ instance.with_transaction(transaction) do
+ return_value = instance.create
+ end
+ return return_value
+ end
+
+ end
+
end
#
From nobody at rubyforge.org Fri Dec 1 10:24:29 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 1 Dec 2006 10:24:29 -0500 (EST)
Subject: [Archipelago-submits] [91] trunk/archipelago/TODO: TODO change
Message-ID: <20061201152429.37C7D5240FFD@rubyforge.org>
Revision: 91
Author: zond
Date: 2006-12-01 10:24:29 -0500 (Fri, 01 Dec 2006)
Log Message:
-----------
TODO change
Modified Paths:
--------------
trunk/archipelago/TODO
Modified: trunk/archipelago/TODO
===================================================================
--- trunk/archipelago/TODO 2006-12-01 15:20:50 UTC (rev 90)
+++ trunk/archipelago/TODO 2006-12-01 15:24:29 UTC (rev 91)
@@ -20,4 +20,3 @@
* Create a memcached-client that uses Disco instance to find all memcached instances
in the network and distribute requests among them.
- * Create a validation framework for Hyperactive::Record::Bass
From nobody at rubyforge.org Fri Dec 1 10:24:42 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 1 Dec 2006 10:24:42 -0500 (EST)
Subject: [Archipelago-submits] [92] trunk/hyperactive: added TODO
Message-ID: <20061201152442.2487A5240FFD@rubyforge.org>
Revision: 92
Author: zond
Date: 2006-12-01 10:24:41 -0500 (Fri, 01 Dec 2006)
Log Message:
-----------
added TODO
Modified Paths:
--------------
trunk/hyperactive/Rakefile
Added Paths:
-----------
trunk/hyperactive/TODO
Modified: trunk/hyperactive/Rakefile
===================================================================
--- trunk/hyperactive/Rakefile 2006-12-01 15:24:29 UTC (rev 91)
+++ trunk/hyperactive/Rakefile 2006-12-01 15:24:41 UTC (rev 92)
@@ -13,7 +13,7 @@
s.author = "Martin Kihlgren"
s.email = "zond at troja dot ath dot cx"
s.summary = "A base class for persistent objects that uses archipelago for persistence. Useful for Ruby on Rails models for example."
- s.files = FileList['lib/hyperactive.rb', 'lib/hyperactive/*.rb', 'tests/*', 'GPL-2'].to_a
+ s.files = FileList['lib/hyperactive.rb', 'lib/hyperactive/*.rb', 'tests/*', 'GPL-2', 'TODO'].to_a
s.require_path = "lib"
s.autorequire = "hyperactive"
s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
Added: trunk/hyperactive/TODO
===================================================================
--- trunk/hyperactive/TODO (rev 0)
+++ trunk/hyperactive/TODO 2006-12-01 15:24:41 UTC (rev 92)
@@ -0,0 +1,2 @@
+
+ * Create a validation framework for Hyperactive::Record::Bass
From nobody at rubyforge.org Sat Dec 2 06:45:24 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 2 Dec 2006 06:45:24 -0500 (EST)
Subject: [Archipelago-submits] [93] trunk/hyperactive/TODO: more todo
Message-ID: <20061202114524.968D95240CF1@rubyforge.org>
Revision: 93
Author: zond
Date: 2006-12-02 06:45:24 -0500 (Sat, 02 Dec 2006)
Log Message:
-----------
more todo
Modified Paths:
--------------
trunk/hyperactive/TODO
Modified: trunk/hyperactive/TODO
===================================================================
--- trunk/hyperactive/TODO 2006-12-01 15:24:41 UTC (rev 92)
+++ trunk/hyperactive/TODO 2006-12-02 11:45:24 UTC (rev 93)
@@ -1,2 +1,4 @@
* Create a validation framework for Hyperactive::Record::Bass
+
+ * Create a sorted data structure, for example AA trees: http://www.eternallyconfuzzled.com/tuts/andersson.html
\ No newline at end of file
From nobody at rubyforge.org Sat Dec 2 07:48:40 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 2 Dec 2006 07:48:40 -0500 (EST)
Subject: [Archipelago-submits] [94] trunk: added debug option to Disco.
Message-ID: <20061202124840.74ED75240D74@rubyforge.org>
Revision: 94
Author: zond
Date: 2006-12-02 07:48:40 -0500 (Sat, 02 Dec 2006)
Log Message:
-----------
added debug option to Disco. increased version. added more failsafety to Disco
Modified Paths:
--------------
trunk/archipelago/Rakefile
trunk/archipelago/lib/archipelago/disco.rb
trunk/hyperactive/Rakefile
Modified: trunk/archipelago/Rakefile
===================================================================
--- trunk/archipelago/Rakefile 2006-12-02 11:45:24 UTC (rev 93)
+++ trunk/archipelago/Rakefile 2006-12-02 12:48:40 UTC (rev 94)
@@ -9,7 +9,7 @@
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "archipelago"
- s.version = "0.2.3"
+ s.version = "0.2.4"
s.author = "Martin Kihlgren"
s.email = "zond at troja dot ath dot cx"
s.summary = "A set of tools for distributed computing in ruby."
Modified: trunk/archipelago/lib/archipelago/disco.rb
===================================================================
--- trunk/archipelago/lib/archipelago/disco.rb 2006-12-02 11:45:24 UTC (rev 93)
+++ trunk/archipelago/lib/archipelago/disco.rb 2006-12-02 12:48:40 UTC (rev 94)
@@ -409,7 +409,9 @@
@unicast_address = "#{HOST}:#{this_port}"
@sender = UDPSocket.new
- @sender.connect(options[:address] || ADDRESS, options[:port] || PORT)
+ @multiaddress = options[:address] || ADDRESS
+ @multiport = options[:port] || PORT
+ @sender.connect(@multiaddress, @multiport)
@unisender = UDPSocket.new
end
@@ -530,9 +532,17 @@
recipient, data = @outgoing.pop
if recipient
address, port = recipient.split(/:/)
+ if $DEBUG
+ puts "sending to #{address}:#{port}:"
+ puts Marshal.dump(data)
+ end
@unisender.send(Marshal.dump(data), 0, address, port.to_i)
else
begin
+ if $DEBUG
+ puts "broadcasting to #{@multiaddress}:#{@multiport}:"
+ puts Marshal.dump(data)
+ end
@sender.write(Marshal.dump(data))
rescue Errno::ECONNREFUSED => e
retry
@@ -554,6 +564,9 @@
loop do
begin
@incoming << Marshal.load(@listener.recv(1024))
+ rescue ArgumentError => e
+ # An ArgumentError here means that the data describes a class we dont know anything
+ # about, which we just have to ignore.
rescue Exception => e
puts e
pp e.backtrace
Modified: trunk/hyperactive/Rakefile
===================================================================
--- trunk/hyperactive/Rakefile 2006-12-02 11:45:24 UTC (rev 93)
+++ trunk/hyperactive/Rakefile 2006-12-02 12:48:40 UTC (rev 94)
@@ -9,7 +9,7 @@
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "hyperactive"
- s.version = "0.2.3"
+ s.version = "0.2.4"
s.author = "Martin Kihlgren"
s.email = "zond at troja dot ath dot cx"
s.summary = "A base class for persistent objects that uses archipelago for persistence. Useful for Ruby on Rails models for example."
From nobody at rubyforge.org Sat Dec 2 07:49:10 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 2 Dec 2006 07:49:10 -0500 (EST)
Subject: [Archipelago-submits] [95] tags: created release_0_2_4
Message-ID: <20061202124910.90B9E5240D74@rubyforge.org>
Revision: 95
Author: zond
Date: 2006-12-02 07:49:10 -0500 (Sat, 02 Dec 2006)
Log Message:
-----------
created release_0_2_4
Added Paths:
-----------
tags/release_0_2_4/
tags/release_0_2_4/archipelago/Rakefile
tags/release_0_2_4/archipelago/TODO
tags/release_0_2_4/archipelago/lib/archipelago/disco.rb
tags/release_0_2_4/hyperactive/README
tags/release_0_2_4/hyperactive/Rakefile
tags/release_0_2_4/hyperactive/TODO
tags/release_0_2_4/hyperactive/lib/hyperactive/hash.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/hooker.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/index.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/list.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/record.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/transactions.rb
tags/release_0_2_4/hyperactive/lib/hyperactive.rb
tags/release_0_2_4/hyperactive/tests/hash_benchmark.rb
tags/release_0_2_4/hyperactive/tests/hash_test.rb
tags/release_0_2_4/hyperactive/tests/list_benchmark.rb
tags/release_0_2_4/hyperactive/tests/list_test.rb
tags/release_0_2_4/hyperactive/tests/record_test.rb
Removed Paths:
-------------
tags/release_0_2_4/archipelago/Rakefile
tags/release_0_2_4/archipelago/TODO
tags/release_0_2_4/archipelago/lib/archipelago/disco.rb
tags/release_0_2_4/hyperactive/README
tags/release_0_2_4/hyperactive/Rakefile
tags/release_0_2_4/hyperactive/lib/hyperactive/hash.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/hooker.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/list.rb
tags/release_0_2_4/hyperactive/lib/hyperactive/record.rb
tags/release_0_2_4/hyperactive/lib/hyperactive.rb
tags/release_0_2_4/hyperactive/tests/hash_benchmark.rb
tags/release_0_2_4/hyperactive/tests/hash_test.rb
tags/release_0_2_4/hyperactive/tests/list_benchmark.rb
tags/release_0_2_4/hyperactive/tests/list_test.rb
tags/release_0_2_4/hyperactive/tests/record_test.rb
Copied: tags/release_0_2_4 (from rev 85, trunk)
Deleted: tags/release_0_2_4/archipelago/Rakefile
===================================================================
--- trunk/archipelago/Rakefile 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/archipelago/Rakefile 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,59 +0,0 @@
-
-require 'rake'
-require 'rake/testtask'
-require 'rubygems'
-Gem::manage_gems
-require 'rake/gempackagetask'
-
-
-spec = Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = "archipelago"
- s.version = "0.2.3"
- s.author = "Martin Kihlgren"
- s.email = "zond at troja dot ath dot cx"
- s.summary = "A set of tools for distributed computing in ruby."
- s.files = FileList['lib/**/*.rb', 'tests/*', 'script/*', 'GPL-2', 'TODO'].to_a
- s.require_path = "lib"
- s.autorequire = "archipelago"
- s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
- s.has_rdoc = true
- s.rdoc_options << '--line-numbers'
- s.rdoc_options << '--inline-source'
- s.extra_rdoc_files = ["README"]
-end
-
-
-SOURCE_FILES = FileList.new do |fl|
- [ "lib", "tests" ].each do |dir|
- fl.include "#{dir}/**/*"
- end
- fl.include "Rakefile"
-end
-
-Rake::GemPackageTask.new(spec) do |pkg|
- pkg.need_tar = true
-end
-
-task :default => [:units] do
-end
-
-desc "Run all tests"
-Rake::TestTask.new(:units) do |t|
- t.pattern = 'tests/*_test.rb'
- t.verbose = true
- t.warning = true
-end
-
-desc "Run all benchmarks"
-Rake::TestTask.new(:bench) do |t|
- t.pattern = 'tests/*_benchmark.rb'
- t.verbose = true
- t.warning = true
-end
-
-desc "Package a gem from the source"
-task :gem => "pkg/#{spec.name}-#{spec.version}.gem" do
- puts "generated latest version"
-end
-
Copied: tags/release_0_2_4/archipelago/Rakefile (from rev 94, trunk/archipelago/Rakefile)
===================================================================
--- tags/release_0_2_4/archipelago/Rakefile (rev 0)
+++ tags/release_0_2_4/archipelago/Rakefile 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,59 @@
+
+require 'rake'
+require 'rake/testtask'
+require 'rubygems'
+Gem::manage_gems
+require 'rake/gempackagetask'
+
+
+spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = "archipelago"
+ s.version = "0.2.4"
+ s.author = "Martin Kihlgren"
+ s.email = "zond at troja dot ath dot cx"
+ s.summary = "A set of tools for distributed computing in ruby."
+ s.files = FileList['lib/**/*.rb', 'tests/*', 'script/*', 'GPL-2', 'TODO'].to_a
+ s.require_path = "lib"
+ s.autorequire = "archipelago"
+ s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
+ s.has_rdoc = true
+ s.rdoc_options << '--line-numbers'
+ s.rdoc_options << '--inline-source'
+ s.extra_rdoc_files = ["README"]
+end
+
+
+SOURCE_FILES = FileList.new do |fl|
+ [ "lib", "tests" ].each do |dir|
+ fl.include "#{dir}/**/*"
+ end
+ fl.include "Rakefile"
+end
+
+Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.need_tar = true
+end
+
+task :default => [:units] do
+end
+
+desc "Run all tests"
+Rake::TestTask.new(:units) do |t|
+ t.pattern = 'tests/*_test.rb'
+ t.verbose = true
+ t.warning = true
+end
+
+desc "Run all benchmarks"
+Rake::TestTask.new(:bench) do |t|
+ t.pattern = 'tests/*_benchmark.rb'
+ t.verbose = true
+ t.warning = true
+end
+
+desc "Package a gem from the source"
+task :gem => "pkg/#{spec.name}-#{spec.version}.gem" do
+ puts "generated latest version"
+end
+
Deleted: tags/release_0_2_4/archipelago/TODO
===================================================================
--- trunk/archipelago/TODO 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/archipelago/TODO 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,16 +0,0 @@
-
- * Create a new HashishProvider with built in redundancy,
- for example using the Chord project: http://pdos.csail.mit.edu/chord/
-
- * Make Chest aware about whether transactions have affected it 'for real' ie
- check whether the instance before the call differs from the instance after
- the call. Preferably without incurring performance lossage.
-
- * Make Dubloon proxy targets able to provide a dirty_state method that decides
- whether they are to be considered dirty, clean or auto-select.
-
- * Test the transaction recovery mechanism of Chest.
-
- * Make Archipelago::Treasure::Dubloons work after an Archipelago::Treasure::Chest
- has rebooted. For example: demand that the chest always run the same host+port
- or make Dubloons able to lookup their home Chest by service_id.
Copied: tags/release_0_2_4/archipelago/TODO (from rev 91, trunk/archipelago/TODO)
===================================================================
--- tags/release_0_2_4/archipelago/TODO (rev 0)
+++ tags/release_0_2_4/archipelago/TODO 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,22 @@
+
+ * Create a failover/redundancy framework
+ * For example: Create a new HashishProvider with built in redundancy,
+ for example using the Chord project: http://pdos.csail.mit.edu/chord/
+ * Or: Create migration methods that move objects between Chests opon
+ startup and shutdown, and make them keep backups at each others
+ persistence backends.
+
+ * Make Chest aware about whether transactions have affected it 'for real' ie
+ check whether the instance before the call differs from the instance after
+ the call. Preferably without incurring performance lossage.
+ * For example: Make Dubloon proxy targets able to provide a dirty_state
+ method that decide whether they are to be considered dirty, clean or auto-select.
+
+ * Test the transaction recovery mechanism of Chest.
+
+ * Create a memcached-starter that publishes the address to the started memcached
+ instance on the Disco network.
+
+ * Create a memcached-client that uses Disco instance to find all memcached instances
+ in the network and distribute requests among them.
+
Deleted: tags/release_0_2_4/archipelago/lib/archipelago/disco.rb
===================================================================
--- trunk/archipelago/lib/archipelago/disco.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/archipelago/lib/archipelago/disco.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,638 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'socket'
-require 'thread'
-require 'ipaddr'
-require 'pp'
-require 'archipelago/current'
-require 'drb'
-require 'set'
-
-module Archipelago
-
- module Disco
-
- #
- # Default address to use.
- #
- ADDRESS = "234.2.4.2"
- #
- # Default port to use.
- #
- PORT = 25242
- #
- # Default port range to use for unicast.
- #
- UNIPORTS = 25243..26243
- #
- # Default lookup timeout.
- #
- LOOKUP_TIMEOUT = 10
- #
- # Default initial pause between resending lookup queries.
- # Will be doubled for each resend.
- #
- INITIAL_LOOKUP_STANDOFF = 0.1
- #
- # Default pause between trying to validate all services we
- # know about.
- #
- VALIDATION_INTERVAL = 60
- #
- # Only save stuff that we KNOW we want.
- #
- THRIFTY_CACHING = true
- #
- # Only reply to the one actually asking about a service.
- #
- THRIFTY_REPLYING = true
- #
- # Dont send on publish, only on query.
- #
- THRIFTY_PUBLISHING = false
-
- #
- # The host we are running on.
- #
- HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
-
- #
- # A module to simplify publishing services.
- #
- # If you include it you can use the publish! method
- # at your convenience.
- #
- # If you want to customize the publishing related behaviour you can
- # call initialize_publishable with a Hash of options.
- #
- # See Archipelago::Treasure::Chest or Archipelago::Tranny::Manager for examples.
- #
- # It will store the service_id of this service in a directory beside this
- # file (publishable.rb) named as the class you include into unless you
- # define @persistence_provider before you call initialize_publishable.
- #
- module Publishable
-
- #
- # Also add the ClassMethods to +base+.
- #
- def self.append_features(base)
- super
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- #
- # Just load whatever we have in +s+.
- #
- def _load(s)
- DRbObject._load(s)
- end
- end
-
- #
- # Dump a DRbObject refering to us.
- #
- def _dump(dummy_param)
- DRbObject.new(self)._dump(dummy_param)
- end
-
- #
- # Will initialize this instance with @service_description and @jockey_options
- # and merge these with the optionally given :service_description and
- # :jockey_options.
- #
- def initialize_publishable(options = {})
- @service_description = {
- :service_id => service_id,
- :validator => self,
- :service => self,
- :class => self.class.name
- }.merge(options[:service_description] || {})
- @jockey_options = options[:jockey_options] || {}
- end
-
- #
- # Create an Archipelago::Disco::Jockey for this instance using @jockey_options
- # or optionally given :jockey_options.
- #
- # Will publish this service using @service_description or optionally given
- # :service_description.
- #
- def publish!(options = {})
- @jockey ||= defined?(Archipelago::Disco::MC) ? Archipelago::Disco::MC : Archipelago::Disco::Jockey.new(@jockey_options.merge(options[:jockey_options] || {}))
- @jockey.publish(Archipelago::Disco::Record.new(@service_description.merge(options[:service_description] || {})))
- end
-
- #
- # We are always valid if we are able to reply.
- #
- def valid?
- if defined?(@valid)
- @valid
- else
- @valid = true
- end
- end
-
- #
- # Stops the publishing of this Publishable.
- #
- def stop!
- if valid?
- @valid = false
- if defined?(Archipelago::Disco::MC) && @jockey == Archipelago::Disco::MC
- @jockey.unpublish(self.service_id)
- else
- @jockey.stop!
- end
- end
- end
-
- #
- # Returns our semi-unique id so that we can be found again.
- #
- def service_id
- #
- # The provider of happy magic persistent hashes of different kinds.
- #
- @persistence_provider ||= Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(File.expand_path(__FILE__)).parent.join(self.class.name + ".db"))
- #
- # Stuff that didnt fit in any of the other databases.
- #
- @metadata ||= @persistence_provider.get_hashish("metadata")
- return @metadata["service_id"] ||= Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}").to_s
- end
-
- end
-
- #
- # A mock validator to be used for dumb systems that dont want
- # to validate.
- #
- class MockValidator
- def valid?
- true
- end
- end
-
- #
- # A Hash-like description of a service.
- #
- class ServiceDescription
- IGNORABLE_ATTRIBUTES = Set[:unicast_reply]
- attr_reader :attributes
- #
- # Initialize this service description with a hash
- # that describes its attributes.
- #
- def initialize(hash = {})
- @attributes = hash
- end
- #
- # Forwards as much as possible to our Hash.
- #
- def method_missing(meth, *args, &block)
- if @attributes.respond_to?(meth)
- @attributes.send(meth, *args, &block)
- else
- super(*args)
- end
- end
- #
- # Returns whether this ServiceDescription matches the given +match+.
- #
- def matches?(match)
- match.each do |key, value|
- unless IGNORABLE_ATTRIBUTES.include?(key)
- return false unless @attributes.include?(key) && (value.nil? || @attributes[key] == value)
- end
- end
- true
- end
- end
-
- #
- # A class used to query the Disco network for services.
- #
- class Query < ServiceDescription
- end
-
- #
- # A class used to defined removed services.
- #
- class UnPublish
- attr_reader :service_id
- def initialize(service_id)
- @service_id = service_id
- end
- end
-
- #
- # A class used to define an existing service.
- #
- class Record < ServiceDescription
- #
- # Initialize this Record with a hash that must contain an :service_id and a :validator.
- #
- def initialize(hash)
- raise "Record must have a :service_id" unless hash.include?(:service_id)
- raise "Record must have a :validator" unless hash.include?(:validator)
- super(hash)
- end
- #
- # Returns whether this service is still valid.
- #
- def valid?
- begin
- self[:validator].valid?
- rescue DRb::DRbError => e
- false
- end
- end
- end
-
- #
- # A container of services.
- #
- class ServiceLocker
- attr_reader :hash
- include Archipelago::Current::Synchronized
- include Archipelago::Current::ThreadedCollection
- def initialize(hash = nil)
- super
- @hash = hash || {}
- end
- #
- # Merge this locker with another.
- #
- def merge(sd)
- rval = @hash.clone
- rval.merge!(sd.hash)
- ServiceLocker.new(rval)
- end
- #
- # Forwards as much as possible to our Hash.
- #
- def method_missing(meth, *args, &block)
- if @hash.respond_to?(meth)
- synchronize do
- @hash.send(meth, *args, &block)
- end
- else
- super(meth, *args, &block)
- end
- end
- #
- # Find all containing services matching +match+.
- #
- def get_services(match)
- rval = ServiceLocker.new
- self.each do |service_id, service_data|
- rval[service_id] = service_data if service_data.matches?(match) && service_data.valid?
- end
- return rval
- end
- #
- # Remove all non-valid services.
- #
- def validate!
- self.clone.each do |service_id, service_data|
- self.delete(service_id) unless service_data.valid?
- end
- end
- end
-
- #
- # The main discovery class used to both publish and lookup services.
- #
- class Jockey
-
- #
- # Will create a Jockey service running on :address and :port or
- # ADDRESS and PORT if none are given.
- #
- # Will the first available unicast port within :uniports or if not given UNIPORTS for receiving unicast messages.
- #
- # Will have a default :lookup_timeout of LOOKUP_TIMEOUT, a default
- # :initial_lookup_standoff of INITIAL_LOOKUP_STANDOFF and a default
- # :validation_interval of VALIDATION_INTERVAL.
- #
- # Will only cache (and validate, which saves network traffic) stuff
- # that has been looked up before if :thrifty_caching, or THRIFTY_CACHING if not given.
- #
- # Will only reply to the one that sent out the query (and therefore save lots of network traffic)
- # if :thrifty_replying, or THRIFTY_REPLYING if not given.
- #
- # Will send out a multicast when a new service is published unless :thrifty_publishing, or
- # THRIFTY_PUBLISHING if not given.
- #
- # Will reply to all queries to which it has matching local services with a unicast message if :thrifty_replying,
- # or if not given THRIFTY_REPLYING. Otherwise will reply with multicasts.
- #
- def initialize(options = {})
- @valid = true
- @remote_services = ServiceLocker.new
- @local_services = ServiceLocker.new
- @subscribed_services = Set.new
-
- @incoming = Queue.new
- @outgoing = Queue.new
-
- @new_service_semaphore = MonitorMixin::ConditionVariable.new(Archipelago::Current::Lock.new)
-
- setup(options)
-
- start_listener
- start_unilistener
- start_shouter
- start_picker
- start_validator(options[:validation_interval] || VALIDATION_INTERVAL)
- end
-
- #
- # Sets up this instance according to the given +options+.
- #
- def setup(options = {})
- @thrifty_caching = options.include?(:thrifty_caching) ? options[:thrifty_caching] : THRIFTY_CACHING
- @thrifty_replying = options.include?(:thrifty_replying) ? options[:thrifty_replying] : THRIFTY_REPLYING
- @thrifty_publishing = options.include?(:thrifty_publishing) ? options[:thrifty_publishing] : THRIFTY_PUBLISHING
- @lookup_timeout = options[:lookup_timeout] || LOOKUP_TIMEOUT
- @initial_lookup_standoff = options[:initial_lookup_standoff] || INITIAL_LOOKUP_STANDOFF
-
- @listener = UDPSocket.new
- @unilistener = UDPSocket.new
-
- @listener.setsockopt(Socket::IPPROTO_IP,
- Socket::IP_ADD_MEMBERSHIP,
- IPAddr.new(options[:address] || ADDRESS).hton + Socket.gethostbyname("0.0.0.0")[3])
-
- @listener.setsockopt(Socket::SOL_SOCKET,
- Socket::SO_REUSEADDR,
- true)
- begin
- @listener.setsockopt(Socket::SOL_SOCKET,
- Socket::SO_REUSEPORT,
- true)
- rescue
- # /moo
- end
- @listener.bind('', options[:port] || PORT)
-
- uniports = options[:uniports] || UNIPORTS
- this_port = uniports.min
- begin
- @unilistener.bind('', this_port)
- rescue Errno::EADDRINUSE => e
- if this_port < uniports.max
- this_port += 1
- retry
- else
- raise e
- end
- end
- @unicast_address = "#{HOST}:#{this_port}"
-
- @sender = UDPSocket.new
- @sender.connect(options[:address] || ADDRESS, options[:port] || PORT)
-
- @unisender = UDPSocket.new
- end
-
- #
- # Clears our local and remote services.
- #
- def clear!
- @local_services = ServiceLocker.new
- @remote_services = ServiceLocker.new
- end
-
- #
- # Stops all the threads in this instance.
- #
- def stop!
- if @valid
- @valid = false
- @local_services.each do |service_id, service_description|
- self.unpublish(service_id)
- end
- @listener_thread.kill
- @unilistener_thread.kill
- @validator_thread.kill
- @picker_thread.kill
- until @outgoing.empty?
- sleep(0.01)
- end
- @shouter_thread.kill
- end
- end
-
- #
- # Lookup any services matching +match+, optionally with a +timeout+.
- #
- # Will immediately return if we know of matching and valid services,
- # will otherwise send out regular Queries and return as soon as
- # matching services are found, or when the +timeout+ runs out.
- #
- def lookup(match, timeout = @lookup_timeout)
- match[:unicast_reply] = @unicast_address
- @subscribed_services << match if @thrifty_caching
- standoff = @initial_lookup_standoff
-
- @outgoing << [nil, match]
- known_services = @remote_services.get_services(match).merge(@local_services.get_services(match))
- return known_services unless known_services.empty?
-
- @new_service_semaphore.wait(standoff)
- standoff *= 2
-
- t = Time.new
- while Time.new < t + timeout
- known_services = @remote_services.get_services(match).merge(@local_services.get_services(match))
- return known_services unless known_services.empty?
-
- @new_service_semaphore.wait(standoff)
- standoff *= 2
-
- @outgoing << [nil, match]
- end
-
- ServiceLocker.new
- end
-
- #
- # Record the given +service+ and broadcast about it.
- #
- def publish(service)
- if service.valid?
- service[:published_at] = Time.now
- @local_services[service[:service_id]] = service
- @new_service_semaphore.broadcast
- unless @thrifty_publishing
- @outgoing << [nil, service]
- end
- end
- end
-
- #
- # Removes the service with given +service_id+ from the published services.
- #
- def unpublish(service_id)
- @local_services.delete(service_id)
- @new_service_semaphore.broadcast
- unless @thrifty_publishing
- @outgoing << [nil, UnPublish.new(service_id)]
- end
- end
-
- private
-
- #
- # Start the validating thread.
- #
- def start_validator(validation_interval)
- @validator_thread = Thread.new do
- loop do
- begin
- @local_services.validate!
- @remote_services.validate!
- sleep(validation_interval)
- rescue Exception => e
- puts e
- pp e.backtrace
- end
- end
- end
- end
-
- #
- # Start the thread sending Records and Queries
- #
- def start_shouter
- @shouter_thread = Thread.new do
- loop do
- begin
- recipient, data = @outgoing.pop
- if recipient
- address, port = recipient.split(/:/)
- @unisender.send(Marshal.dump(data), 0, address, port.to_i)
- else
- begin
- @sender.write(Marshal.dump(data))
- rescue Errno::ECONNREFUSED => e
- retry
- end
- end
- rescue Exception => e
- puts e
- pp e.backtrace
- end
- end
- end
- end
-
- #
- # Start the thread receiving Records and Queries
- #
- def start_listener
- @listener_thread = Thread.new do
- loop do
- begin
- @incoming << Marshal.load(@listener.recv(1024))
- rescue Exception => e
- puts e
- pp e.backtrace
- end
- end
- end
- end
-
- #
- # Start the thread receiving Records and Queries
- # on unicast.
- #
- def start_unilistener
- @unilistener_thread = Thread.new do
- loop do
- begin
- @incoming << Marshal.load(@unilistener.recv(1024))
- rescue Exception => e
- puts e
- pp e.backtrace
- end
- end
- end
- end
-
- #
- # Start the thread picking incoming Records, Queries and UnPublishes and
- # handling them properly.
- #
- def start_picker
- @picker_thread = Thread.new do
- loop do
- begin
- data = @incoming.pop
- if Archipelago::Disco::Query === data
- @local_services.get_services(data).each do |service_id, service_data|
- if @thrifty_replying
- @outgoing << [data[:unicast_reply], service_data]
- else
- @outgoing << [nil, service_data]
- end
- end
- elsif Archipelago::Disco::Record === data
- if interesting?(data) && data.valid?
- @remote_services[data[:service_id]] = data
- @new_service_semaphore.broadcast
- end
- elsif Archipelago::Disco::UnPublish === data
- @remote_services.delete(data.service_id)
- end
- rescue Exception => e
- puts e
- pp e.backtrace
- end
- end
- end
- end
-
- #
- # Are we generous in our caching, or have we been
- # asked about this type of +publish+ before?
- #
- def interesting?(publish)
- @subscribed_services.each do |subscribed|
- return true if publish.matches?(subscribed)
- end
- return !@thrifty_caching
- end
-
- end
-
- #
- # The default Archipelago::Disco::Jockey that is always available for lookups is Archipelago::Disco::MC.
- #
- # If you really need to you can customize it by defining MC_OPTIONS before loading disco.rb, and if you REALLY
- # need to you can disable it completely by setting MC_DISABLED to true.
- #
- MC = Jockey.new(defined?(MC_OPTIONS) ? MC_OPTIONS : {}) unless defined?(MC_DISABLED) && MC_DISABLED
-
- end
-
-end
Copied: tags/release_0_2_4/archipelago/lib/archipelago/disco.rb (from rev 94, trunk/archipelago/lib/archipelago/disco.rb)
===================================================================
--- tags/release_0_2_4/archipelago/lib/archipelago/disco.rb (rev 0)
+++ tags/release_0_2_4/archipelago/lib/archipelago/disco.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,651 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'socket'
+require 'thread'
+require 'ipaddr'
+require 'pp'
+require 'archipelago/current'
+require 'drb'
+require 'set'
+
+module Archipelago
+
+ module Disco
+
+ #
+ # Default address to use.
+ #
+ ADDRESS = "234.2.4.2"
+ #
+ # Default port to use.
+ #
+ PORT = 25242
+ #
+ # Default port range to use for unicast.
+ #
+ UNIPORTS = 25243..26243
+ #
+ # Default lookup timeout.
+ #
+ LOOKUP_TIMEOUT = 10
+ #
+ # Default initial pause between resending lookup queries.
+ # Will be doubled for each resend.
+ #
+ INITIAL_LOOKUP_STANDOFF = 0.1
+ #
+ # Default pause between trying to validate all services we
+ # know about.
+ #
+ VALIDATION_INTERVAL = 60
+ #
+ # Only save stuff that we KNOW we want.
+ #
+ THRIFTY_CACHING = true
+ #
+ # Only reply to the one actually asking about a service.
+ #
+ THRIFTY_REPLYING = true
+ #
+ # Dont send on publish, only on query.
+ #
+ THRIFTY_PUBLISHING = false
+
+ #
+ # The host we are running on.
+ #
+ HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
+
+ #
+ # A module to simplify publishing services.
+ #
+ # If you include it you can use the publish! method
+ # at your convenience.
+ #
+ # If you want to customize the publishing related behaviour you can
+ # call initialize_publishable with a Hash of options.
+ #
+ # See Archipelago::Treasure::Chest or Archipelago::Tranny::Manager for examples.
+ #
+ # It will store the service_id of this service in a directory beside this
+ # file (publishable.rb) named as the class you include into unless you
+ # define @persistence_provider before you call initialize_publishable.
+ #
+ module Publishable
+
+ #
+ # Also add the ClassMethods to +base+.
+ #
+ def self.append_features(base)
+ super
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ #
+ # Just load whatever we have in +s+.
+ #
+ def _load(s)
+ DRbObject._load(s)
+ end
+ end
+
+ #
+ # Dump a DRbObject refering to us.
+ #
+ def _dump(dummy_param)
+ DRbObject.new(self)._dump(dummy_param)
+ end
+
+ #
+ # Will initialize this instance with @service_description and @jockey_options
+ # and merge these with the optionally given :service_description and
+ # :jockey_options.
+ #
+ def initialize_publishable(options = {})
+ @service_description = {
+ :service_id => service_id,
+ :validator => self,
+ :service => self,
+ :class => self.class.name
+ }.merge(options[:service_description] || {})
+ @jockey_options = options[:jockey_options] || {}
+ end
+
+ #
+ # Create an Archipelago::Disco::Jockey for this instance using @jockey_options
+ # or optionally given :jockey_options.
+ #
+ # Will publish this service using @service_description or optionally given
+ # :service_description.
+ #
+ def publish!(options = {})
+ @jockey ||= defined?(Archipelago::Disco::MC) ? Archipelago::Disco::MC : Archipelago::Disco::Jockey.new(@jockey_options.merge(options[:jockey_options] || {}))
+ @jockey.publish(Archipelago::Disco::Record.new(@service_description.merge(options[:service_description] || {})))
+ end
+
+ #
+ # We are always valid if we are able to reply.
+ #
+ def valid?
+ if defined?(@valid)
+ @valid
+ else
+ @valid = true
+ end
+ end
+
+ #
+ # Stops the publishing of this Publishable.
+ #
+ def stop!
+ if valid?
+ @valid = false
+ if defined?(Archipelago::Disco::MC) && @jockey == Archipelago::Disco::MC
+ @jockey.unpublish(self.service_id)
+ else
+ @jockey.stop!
+ end
+ end
+ end
+
+ #
+ # Returns our semi-unique id so that we can be found again.
+ #
+ def service_id
+ #
+ # The provider of happy magic persistent hashes of different kinds.
+ #
+ @persistence_provider ||= Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(File.expand_path(__FILE__)).parent.join(self.class.name + ".db"))
+ #
+ # Stuff that didnt fit in any of the other databases.
+ #
+ @metadata ||= @persistence_provider.get_hashish("metadata")
+ return @metadata["service_id"] ||= Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}").to_s
+ end
+
+ end
+
+ #
+ # A mock validator to be used for dumb systems that dont want
+ # to validate.
+ #
+ class MockValidator
+ def valid?
+ true
+ end
+ end
+
+ #
+ # A Hash-like description of a service.
+ #
+ class ServiceDescription
+ IGNORABLE_ATTRIBUTES = Set[:unicast_reply]
+ attr_reader :attributes
+ #
+ # Initialize this service description with a hash
+ # that describes its attributes.
+ #
+ def initialize(hash = {})
+ @attributes = hash
+ end
+ #
+ # Forwards as much as possible to our Hash.
+ #
+ def method_missing(meth, *args, &block)
+ if @attributes.respond_to?(meth)
+ @attributes.send(meth, *args, &block)
+ else
+ super(*args)
+ end
+ end
+ #
+ # Returns whether this ServiceDescription matches the given +match+.
+ #
+ def matches?(match)
+ match.each do |key, value|
+ unless IGNORABLE_ATTRIBUTES.include?(key)
+ return false unless @attributes.include?(key) && (value.nil? || @attributes[key] == value)
+ end
+ end
+ true
+ end
+ end
+
+ #
+ # A class used to query the Disco network for services.
+ #
+ class Query < ServiceDescription
+ end
+
+ #
+ # A class used to defined removed services.
+ #
+ class UnPublish
+ attr_reader :service_id
+ def initialize(service_id)
+ @service_id = service_id
+ end
+ end
+
+ #
+ # A class used to define an existing service.
+ #
+ class Record < ServiceDescription
+ #
+ # Initialize this Record with a hash that must contain an :service_id and a :validator.
+ #
+ def initialize(hash)
+ raise "Record must have a :service_id" unless hash.include?(:service_id)
+ raise "Record must have a :validator" unless hash.include?(:validator)
+ super(hash)
+ end
+ #
+ # Returns whether this service is still valid.
+ #
+ def valid?
+ begin
+ self[:validator].valid?
+ rescue DRb::DRbError => e
+ false
+ end
+ end
+ end
+
+ #
+ # A container of services.
+ #
+ class ServiceLocker
+ attr_reader :hash
+ include Archipelago::Current::Synchronized
+ include Archipelago::Current::ThreadedCollection
+ def initialize(hash = nil)
+ super
+ @hash = hash || {}
+ end
+ #
+ # Merge this locker with another.
+ #
+ def merge(sd)
+ rval = @hash.clone
+ rval.merge!(sd.hash)
+ ServiceLocker.new(rval)
+ end
+ #
+ # Forwards as much as possible to our Hash.
+ #
+ def method_missing(meth, *args, &block)
+ if @hash.respond_to?(meth)
+ synchronize do
+ @hash.send(meth, *args, &block)
+ end
+ else
+ super(meth, *args, &block)
+ end
+ end
+ #
+ # Find all containing services matching +match+.
+ #
+ def get_services(match)
+ rval = ServiceLocker.new
+ self.each do |service_id, service_data|
+ rval[service_id] = service_data if service_data.matches?(match) && service_data.valid?
+ end
+ return rval
+ end
+ #
+ # Remove all non-valid services.
+ #
+ def validate!
+ self.clone.each do |service_id, service_data|
+ self.delete(service_id) unless service_data.valid?
+ end
+ end
+ end
+
+ #
+ # The main discovery class used to both publish and lookup services.
+ #
+ class Jockey
+
+ #
+ # Will create a Jockey service running on :address and :port or
+ # ADDRESS and PORT if none are given.
+ #
+ # Will the first available unicast port within :uniports or if not given UNIPORTS for receiving unicast messages.
+ #
+ # Will have a default :lookup_timeout of LOOKUP_TIMEOUT, a default
+ # :initial_lookup_standoff of INITIAL_LOOKUP_STANDOFF and a default
+ # :validation_interval of VALIDATION_INTERVAL.
+ #
+ # Will only cache (and validate, which saves network traffic) stuff
+ # that has been looked up before if :thrifty_caching, or THRIFTY_CACHING if not given.
+ #
+ # Will only reply to the one that sent out the query (and therefore save lots of network traffic)
+ # if :thrifty_replying, or THRIFTY_REPLYING if not given.
+ #
+ # Will send out a multicast when a new service is published unless :thrifty_publishing, or
+ # THRIFTY_PUBLISHING if not given.
+ #
+ # Will reply to all queries to which it has matching local services with a unicast message if :thrifty_replying,
+ # or if not given THRIFTY_REPLYING. Otherwise will reply with multicasts.
+ #
+ def initialize(options = {})
+ @valid = true
+ @remote_services = ServiceLocker.new
+ @local_services = ServiceLocker.new
+ @subscribed_services = Set.new
+
+ @incoming = Queue.new
+ @outgoing = Queue.new
+
+ @new_service_semaphore = MonitorMixin::ConditionVariable.new(Archipelago::Current::Lock.new)
+
+ setup(options)
+
+ start_listener
+ start_unilistener
+ start_shouter
+ start_picker
+ start_validator(options[:validation_interval] || VALIDATION_INTERVAL)
+ end
+
+ #
+ # Sets up this instance according to the given +options+.
+ #
+ def setup(options = {})
+ @thrifty_caching = options.include?(:thrifty_caching) ? options[:thrifty_caching] : THRIFTY_CACHING
+ @thrifty_replying = options.include?(:thrifty_replying) ? options[:thrifty_replying] : THRIFTY_REPLYING
+ @thrifty_publishing = options.include?(:thrifty_publishing) ? options[:thrifty_publishing] : THRIFTY_PUBLISHING
+ @lookup_timeout = options[:lookup_timeout] || LOOKUP_TIMEOUT
+ @initial_lookup_standoff = options[:initial_lookup_standoff] || INITIAL_LOOKUP_STANDOFF
+
+ @listener = UDPSocket.new
+ @unilistener = UDPSocket.new
+
+ @listener.setsockopt(Socket::IPPROTO_IP,
+ Socket::IP_ADD_MEMBERSHIP,
+ IPAddr.new(options[:address] || ADDRESS).hton + Socket.gethostbyname("0.0.0.0")[3])
+
+ @listener.setsockopt(Socket::SOL_SOCKET,
+ Socket::SO_REUSEADDR,
+ true)
+ begin
+ @listener.setsockopt(Socket::SOL_SOCKET,
+ Socket::SO_REUSEPORT,
+ true)
+ rescue
+ # /moo
+ end
+ @listener.bind('', options[:port] || PORT)
+
+ uniports = options[:uniports] || UNIPORTS
+ this_port = uniports.min
+ begin
+ @unilistener.bind('', this_port)
+ rescue Errno::EADDRINUSE => e
+ if this_port < uniports.max
+ this_port += 1
+ retry
+ else
+ raise e
+ end
+ end
+ @unicast_address = "#{HOST}:#{this_port}"
+
+ @sender = UDPSocket.new
+ @multiaddress = options[:address] || ADDRESS
+ @multiport = options[:port] || PORT
+ @sender.connect(@multiaddress, @multiport)
+
+ @unisender = UDPSocket.new
+ end
+
+ #
+ # Clears our local and remote services.
+ #
+ def clear!
+ @local_services = ServiceLocker.new
+ @remote_services = ServiceLocker.new
+ end
+
+ #
+ # Stops all the threads in this instance.
+ #
+ def stop!
+ if @valid
+ @valid = false
+ @local_services.each do |service_id, service_description|
+ self.unpublish(service_id)
+ end
+ @listener_thread.kill
+ @unilistener_thread.kill
+ @validator_thread.kill
+ @picker_thread.kill
+ until @outgoing.empty?
+ sleep(0.01)
+ end
+ @shouter_thread.kill
+ end
+ end
+
+ #
+ # Lookup any services matching +match+, optionally with a +timeout+.
+ #
+ # Will immediately return if we know of matching and valid services,
+ # will otherwise send out regular Queries and return as soon as
+ # matching services are found, or when the +timeout+ runs out.
+ #
+ def lookup(match, timeout = @lookup_timeout)
+ match[:unicast_reply] = @unicast_address
+ @subscribed_services << match if @thrifty_caching
+ standoff = @initial_lookup_standoff
+
+ @outgoing << [nil, match]
+ known_services = @remote_services.get_services(match).merge(@local_services.get_services(match))
+ return known_services unless known_services.empty?
+
+ @new_service_semaphore.wait(standoff)
+ standoff *= 2
+
+ t = Time.new
+ while Time.new < t + timeout
+ known_services = @remote_services.get_services(match).merge(@local_services.get_services(match))
+ return known_services unless known_services.empty?
+
+ @new_service_semaphore.wait(standoff)
+ standoff *= 2
+
+ @outgoing << [nil, match]
+ end
+
+ ServiceLocker.new
+ end
+
+ #
+ # Record the given +service+ and broadcast about it.
+ #
+ def publish(service)
+ if service.valid?
+ service[:published_at] = Time.now
+ @local_services[service[:service_id]] = service
+ @new_service_semaphore.broadcast
+ unless @thrifty_publishing
+ @outgoing << [nil, service]
+ end
+ end
+ end
+
+ #
+ # Removes the service with given +service_id+ from the published services.
+ #
+ def unpublish(service_id)
+ @local_services.delete(service_id)
+ @new_service_semaphore.broadcast
+ unless @thrifty_publishing
+ @outgoing << [nil, UnPublish.new(service_id)]
+ end
+ end
+
+ private
+
+ #
+ # Start the validating thread.
+ #
+ def start_validator(validation_interval)
+ @validator_thread = Thread.new do
+ loop do
+ begin
+ @local_services.validate!
+ @remote_services.validate!
+ sleep(validation_interval)
+ rescue Exception => e
+ puts e
+ pp e.backtrace
+ end
+ end
+ end
+ end
+
+ #
+ # Start the thread sending Records and Queries
+ #
+ def start_shouter
+ @shouter_thread = Thread.new do
+ loop do
+ begin
+ recipient, data = @outgoing.pop
+ if recipient
+ address, port = recipient.split(/:/)
+ if $DEBUG
+ puts "sending to #{address}:#{port}:"
+ puts Marshal.dump(data)
+ end
+ @unisender.send(Marshal.dump(data), 0, address, port.to_i)
+ else
+ begin
+ if $DEBUG
+ puts "broadcasting to #{@multiaddress}:#{@multiport}:"
+ puts Marshal.dump(data)
+ end
+ @sender.write(Marshal.dump(data))
+ rescue Errno::ECONNREFUSED => e
+ retry
+ end
+ end
+ rescue Exception => e
+ puts e
+ pp e.backtrace
+ end
+ end
+ end
+ end
+
+ #
+ # Start the thread receiving Records and Queries
+ #
+ def start_listener
+ @listener_thread = Thread.new do
+ loop do
+ begin
+ @incoming << Marshal.load(@listener.recv(1024))
+ rescue ArgumentError => e
+ # An ArgumentError here means that the data describes a class we dont know anything
+ # about, which we just have to ignore.
+ rescue Exception => e
+ puts e
+ pp e.backtrace
+ end
+ end
+ end
+ end
+
+ #
+ # Start the thread receiving Records and Queries
+ # on unicast.
+ #
+ def start_unilistener
+ @unilistener_thread = Thread.new do
+ loop do
+ begin
+ @incoming << Marshal.load(@unilistener.recv(1024))
+ rescue Exception => e
+ puts e
+ pp e.backtrace
+ end
+ end
+ end
+ end
+
+ #
+ # Start the thread picking incoming Records, Queries and UnPublishes and
+ # handling them properly.
+ #
+ def start_picker
+ @picker_thread = Thread.new do
+ loop do
+ begin
+ data = @incoming.pop
+ if Archipelago::Disco::Query === data
+ @local_services.get_services(data).each do |service_id, service_data|
+ if @thrifty_replying
+ @outgoing << [data[:unicast_reply], service_data]
+ else
+ @outgoing << [nil, service_data]
+ end
+ end
+ elsif Archipelago::Disco::Record === data
+ if interesting?(data) && data.valid?
+ @remote_services[data[:service_id]] = data
+ @new_service_semaphore.broadcast
+ end
+ elsif Archipelago::Disco::UnPublish === data
+ @remote_services.delete(data.service_id)
+ end
+ rescue Exception => e
+ puts e
+ pp e.backtrace
+ end
+ end
+ end
+ end
+
+ #
+ # Are we generous in our caching, or have we been
+ # asked about this type of +publish+ before?
+ #
+ def interesting?(publish)
+ @subscribed_services.each do |subscribed|
+ return true if publish.matches?(subscribed)
+ end
+ return !@thrifty_caching
+ end
+
+ end
+
+ #
+ # The default Archipelago::Disco::Jockey that is always available for lookups is Archipelago::Disco::MC.
+ #
+ # If you really need to you can customize it by defining MC_OPTIONS before loading disco.rb, and if you REALLY
+ # need to you can disable it completely by setting MC_DISABLED to true.
+ #
+ MC = Jockey.new(defined?(MC_OPTIONS) ? MC_OPTIONS : {}) unless defined?(MC_DISABLED) && MC_DISABLED
+
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/README
===================================================================
--- trunk/hyperactive/README 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/README 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,41 +0,0 @@
-= This is HyperactiveRecord, a not-at-all drop-in replacement for ActiveRecord::Base
-
-It uses archipelago for persistence, and is meaningful only in an environment where the server process doesnt restart at each request. This means that cgi environment is not really an option.
-
-== Sub packages:
-
-Hyperactive::Record:: The base class package itself, providing you with cached selectors and rejectors, along with cached finders for any number of attributes.
-Hyperactive::Hash:: A collection class that contains any number of Hyperactive::Records in a hash like structure.
-Hyperactive::List:: A collection class that contains any number of Hyperactive::Records in a list like structure.
-
-== Usage:
-
-To use Hyperactive in the simplest way, just run the script/services.rb script from the Archipelago
-distribution to get a few services running, then subclass Hyperactive::Record::Bass and create
-objects with MyBassSubclass.get_instance (not new!). They will be automagically
-stored in the network, and fetchable via their instance.record_id.
-
-By loading Hyperactive::Record you will automatically define Hyperactive::Record::CAPTAIN which will
-be an Archipelago::Pirate::Captain that is your interface to the distributed database.
-
-== Examples:
-
-To define a Record subclass that has the properties @active and @city that are indexed in two ways:
-
- class MyClass < Hyperactive::Record
- attr_accessor :active, :city
- select(:active_records, Proc.new do |record|
- record.active == true
- end)
- index_by(:city)
- end
-
-This will allow you to find all active MyClass instances by:
-
- MyClass.active_records
-
-Or finding all MyClass instances connected to Stockholm by:
-
- MyClass.find_by_city("Stockholm")
-
-
Copied: tags/release_0_2_4/hyperactive/README (from rev 89, trunk/hyperactive/README)
===================================================================
--- tags/release_0_2_4/hyperactive/README (rev 0)
+++ tags/release_0_2_4/hyperactive/README 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,47 @@
+= This is HyperactiveRecord, a not-at-all drop-in replacement for ActiveRecord::Base
+
+It uses archipelago for persistence, and is meaningful only in an environment where the server process doesnt restart at each request. This means that cgi environment is not really an option.
+
+== Sub packages:
+
+Hyperactive::Record:: The base class package itself, providing you with cached selectors and rejectors, along with cached finders for any number of attributes.
+Hyperactive::Hash:: A collection class that contains any number of Hyperactive::Records in a hash like structure.
+Hyperactive::List:: A collection class that contains any number of Hyperactive::Records in a list like structure.
+Hyperactive::Index:: A module included into Hyperactive::Record that adds simple indexing capabilities of the find_by_... type.
+Hyperactive::Transactions:: A module included into Hyperactive::Record that adds a few simplifications in handling transactions properly.
+
+== Usage:
+
+To use Hyperactive in the simplest way, just run the script/services.rb script from the Archipelago
+distribution to get a few services running, then subclass Hyperactive::Record::Bass and create
+objects with MyBassSubclass.get_instance. They will be automagically stored in the network,
+and fetchable via their instance.record_id.
+
+You can also use new of course, but beware that this will not store the object persistently
+or give you a proxy. Both of these things are good for you, so use get_instance unless you know
+what you are doing.
+
+By loading Hyperactive::Record you will automatically define Hyperactive::CAPTAIN which will
+be an Archipelago::Pirate::Captain that is your interface to the distributed database.
+
+== Examples:
+
+To define a Record subclass that has the properties @active and @city that are indexed in two ways:
+
+ class MyClass < Hyperactive::Record
+ attr_accessor :active, :city
+ select(:active_records, Proc.new do |record|
+ record.active == true
+ end)
+ index_by(:city)
+ end
+
+This will allow you to find all active MyClass instances by:
+
+ MyClass.active_records
+
+Or finding all MyClass instances connected to Stockholm by:
+
+ MyClass.find_by_city("Stockholm")
+
+
Deleted: tags/release_0_2_4/hyperactive/Rakefile
===================================================================
--- trunk/hyperactive/Rakefile 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/Rakefile 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,60 +0,0 @@
-
-require 'rake'
-require 'rake/testtask'
-require 'rubygems'
-Gem::manage_gems
-require 'rake/gempackagetask'
-
-
-spec = Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = "hyperactive"
- s.version = "0.2.3"
- s.author = "Martin Kihlgren"
- s.email = "zond at troja dot ath dot cx"
- s.summary = "A base class for persistent objects that uses archipelago for persistence. Useful for Ruby on Rails models for example."
- s.files = FileList['lib/hyperactive.rb', 'lib/hyperactive/*.rb', 'tests/*', 'GPL-2'].to_a
- s.require_path = "lib"
- s.autorequire = "hyperactive"
- s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
- s.has_rdoc = true
- s.rdoc_options << '--line-numbers'
- s.rdoc_options << '--inline-source'
- s.extra_rdoc_files = ["README"]
- s.add_dependency('archipelago', '>= 0.2.0')
-end
-
-
-SOURCE_FILES = FileList.new do |fl|
- [ "lib", "tests" ].each do |dir|
- fl.include "#{dir}/**/*"
- end
- fl.include "Rakefile"
-end
-
-Rake::GemPackageTask.new(spec) do |pkg|
- pkg.need_tar = true
-end
-
-task :default => [:units] do
-end
-
-desc "Run all tests"
-Rake::TestTask.new(:units) do |t|
- t.pattern = 'tests/*_test.rb'
- t.verbose = true
- t.warning = true
-end
-
-desc "Run all benchmarks"
-Rake::TestTask.new(:bench) do |t|
- t.pattern = 'tests/*_benchmark.rb'
- t.verbose = true
- t.warning = true
-end
-
-desc "Package a gem from the source"
-task :gem => "pkg/#{spec.name}-#{spec.version}.gem" do
- puts "generated latest version"
-end
-
Copied: tags/release_0_2_4/hyperactive/Rakefile (from rev 94, trunk/hyperactive/Rakefile)
===================================================================
--- tags/release_0_2_4/hyperactive/Rakefile (rev 0)
+++ tags/release_0_2_4/hyperactive/Rakefile 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,60 @@
+
+require 'rake'
+require 'rake/testtask'
+require 'rubygems'
+Gem::manage_gems
+require 'rake/gempackagetask'
+
+
+spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = "hyperactive"
+ s.version = "0.2.4"
+ s.author = "Martin Kihlgren"
+ s.email = "zond at troja dot ath dot cx"
+ s.summary = "A base class for persistent objects that uses archipelago for persistence. Useful for Ruby on Rails models for example."
+ s.files = FileList['lib/hyperactive.rb', 'lib/hyperactive/*.rb', 'tests/*', 'GPL-2', 'TODO'].to_a
+ s.require_path = "lib"
+ s.autorequire = "hyperactive"
+ s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
+ s.has_rdoc = true
+ s.rdoc_options << '--line-numbers'
+ s.rdoc_options << '--inline-source'
+ s.extra_rdoc_files = ["README"]
+ s.add_dependency('archipelago', '>= 0.2.0')
+end
+
+
+SOURCE_FILES = FileList.new do |fl|
+ [ "lib", "tests" ].each do |dir|
+ fl.include "#{dir}/**/*"
+ end
+ fl.include "Rakefile"
+end
+
+Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.need_tar = true
+end
+
+task :default => [:units] do
+end
+
+desc "Run all tests"
+Rake::TestTask.new(:units) do |t|
+ t.pattern = 'tests/*_test.rb'
+ t.verbose = true
+ t.warning = true
+end
+
+desc "Run all benchmarks"
+Rake::TestTask.new(:bench) do |t|
+ t.pattern = 'tests/*_benchmark.rb'
+ t.verbose = true
+ t.warning = true
+end
+
+desc "Package a gem from the source"
+task :gem => "pkg/#{spec.name}-#{spec.version}.gem" do
+ puts "generated latest version"
+end
+
Copied: tags/release_0_2_4/hyperactive/TODO (from rev 93, trunk/hyperactive/TODO)
===================================================================
--- tags/release_0_2_4/hyperactive/TODO (rev 0)
+++ tags/release_0_2_4/hyperactive/TODO 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,4 @@
+
+ * Create a validation framework for Hyperactive::Record::Bass
+
+ * Create a sorted data structure, for example AA trees: http://www.eternallyconfuzzled.com/tuts/andersson.html
\ No newline at end of file
Deleted: tags/release_0_2_4/hyperactive/lib/hyperactive/hash.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/hash.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/hash.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,172 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-require 'rubygems'
-require 'archipelago'
-require 'digest/sha1'
-
-module Hyperactive
-
- #
- # The package containing the Hash class that provides any
- # kind of index for your Hyperactive classes.
- #
- # Is supposed to be constantly scaling, but preliminary benchmarks show some
- # problems with that assumption?
- #
- module Hash
-
- #
- # A wrapper class that knows what key, value and list_element belong together.
- #
- class Element < Hyperactive::Record::Bass
- attr_accessor :key, :value, :list_element
- #
- # Initialize a new Hash::Element with given +key+, +value+ and +list_element+.
- #
- def initialize(key, value, list_element)
- self.key = key
- self.value = value
- self.list_element = list_element
- end
- end
-
- #
- # A class suitable for storing large and often-changing datasets in
- # an Archipelago environment.
- #
- class Head < Hyperactive::Record::Bass
-
- attr_accessor :list
-
- include Archipelago::Current::ThreadedCollection
-
- #
- # Initialize a Hash::Head.
- #
- # NB: Remember to call create on the new instance or use Head.get_instance to get that done automatically.
- #
- def initialize
- self.list = nil
- end
-
- #
- # Return the size of this Hash.
- #
- def size
- self.list.size
- end
-
- #
- # Return the value for +key+.
- #
- def [](key)
- element = Hyperactive::Record::CAPTAIN[my_key_for(key), @transaction]
- if element
- return element.value
- else
- return nil
- end
- end
-
- #
- # Returns whether +key+ is included in this Hash.
- #
- def include?(key)
- Hyperactive::Record::CAPTAIN.include?(my_key_for(key), @transaction)
- end
-
- #
- # Insert +value+ under +key+ in this Hash.
- #
- def []=(key, value)
- self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
-
- if (element = Hyperactive::Record::CAPTAIN[my_key_for(key), @transaction])
- element.value = value
- else
- element = Element.get_instance_with_transaction(@transaction, key, value, nil)
- self.list << element
- element.list_element = self.list.last_element
- Hyperactive::Record::CAPTAIN[my_key_for(key), @transaction] = element
- end
- end
-
- #
- # Delete +key+ from this Hash.
- #
- def delete(key)
- self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
-
- return_value = nil
-
- element = Hyperactive::Record::CAPTAIN[my_key_for(key), @transaction]
- if element
- Hyperactive::Record::CAPTAIN.delete(my_key_for(key), @transaction)
- self.list.unlink!(element.list_element)
- return_value = element.value
- element.destroy!
- end
- return return_value
- end
-
- #
- # Will yield to +block+ once for each key/value pair in this Hash.
- #
- def each(&block)
- self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
-
- self.list.each do |element|
- yield([element.key, element.value])
- end
- end
-
- #
- # Remove all key/value pairs from this Hash.
- #
- def clear!
- self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
-
- self.list.t_each do |element|
- element.destroy!
- end
- self.list.clear!
- end
-
- #
- # Clear everything from this Tree and destroy it.
- #
- def destroy!
- self.clear!
- super
- end
-
- private
-
- #
- # Get my private key for a given +key+.
- #
- def my_key_for(key)
- Digest::SHA1.hexdigest("#{Marshal.dump(key)}#{self.record_id}")
- end
-
- end
-
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/lib/hyperactive/hash.rb (from rev 89, trunk/hyperactive/lib/hyperactive/hash.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/lib/hyperactive/hash.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/hash.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,180 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+require 'rubygems'
+require 'archipelago'
+require 'digest/sha1'
+
+module Hyperactive
+
+ #
+ # The package containing the Hash class that provides any
+ # kind of index for your Hyperactive classes.
+ #
+ # Is supposed to be constantly scaling, but preliminary benchmarks show some
+ # problems with that assumption?
+ #
+ module Hash
+
+ #
+ # A wrapper class that knows what key, value and list_element belong together.
+ #
+ class Element < Hyperactive::Record::Bass
+ attr_accessor :key, :value, :list_element
+ #
+ # Initialize a new Hash::Element with given +key+, +value+ and +list_element+.
+ #
+ def initialize(key, value, list_element)
+ self.key = key
+ self.value = value
+ self.list_element = list_element
+ end
+ end
+
+ #
+ # A class suitable for storing large and often-changing datasets in
+ # an Archipelago environment.
+ #
+ class Head < Hyperactive::Record::Bass
+
+ attr_accessor :list
+
+ include Archipelago::Current::ThreadedCollection
+
+ #
+ # Initialize a Hash::Head.
+ #
+ # NB: Remember to call create on the new instance or use Head.get_instance to get that done automatically.
+ #
+ def initialize
+ super
+ self.list = nil
+ end
+
+ #
+ # Return the size of this Hash.
+ #
+ def size
+ self.list.size
+ end
+
+ #
+ # Return whether this Hash is empty.
+ #
+ def empty?
+ self.list.empty?
+ end
+
+ #
+ # Return the value for +key+.
+ #
+ def [](key)
+ element = Hyperactive::CAPTAIN[my_key_for(key), @transaction]
+ if element
+ return element.value
+ else
+ return nil
+ end
+ end
+
+ #
+ # Returns whether +key+ is included in this Hash.
+ #
+ def include?(key)
+ Hyperactive::CAPTAIN.include?(my_key_for(key), @transaction)
+ end
+
+ #
+ # Insert +value+ under +key+ in this Hash.
+ #
+ def []=(key, value)
+ self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
+
+ if (element = Hyperactive::CAPTAIN[my_key_for(key), @transaction])
+ element.value = value
+ else
+ element = Element.get_instance_with_transaction(@transaction, key, value, nil)
+ self.list << element
+ element.list_element = self.list.last_element
+ Hyperactive::CAPTAIN[my_key_for(key), @transaction] = element
+ end
+ end
+
+ #
+ # Delete +key+ from this Hash.
+ #
+ def delete(key)
+ self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
+
+ return_value = nil
+
+ element = Hyperactive::CAPTAIN[my_key_for(key), @transaction]
+ if element
+ Hyperactive::CAPTAIN.delete(my_key_for(key), @transaction)
+ self.list.unlink!(element.list_element)
+ return_value = element.value
+ element.destroy!
+ end
+ return return_value
+ end
+
+ #
+ # Will yield to +block+ once for each key/value pair in this Hash.
+ #
+ def each(&block)
+ self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
+
+ self.list.each do |element|
+ yield([element.key, element.value])
+ end
+ end
+
+ #
+ # Remove all key/value pairs from this Hash.
+ #
+ def clear!
+ self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
+
+ self.list.t_each do |element|
+ element.destroy!
+ end
+ self.list.clear!
+ end
+
+ #
+ # Clear everything from this Tree and destroy it.
+ #
+ def destroy!
+ self.clear!
+ super
+ end
+
+ private
+
+ #
+ # Get my private key for a given +key+.
+ #
+ def my_key_for(key)
+ Digest::SHA1.hexdigest("#{Marshal.dump(key)}#{self.record_id}")
+ end
+
+ end
+
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/lib/hyperactive/hooker.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/hooker.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/hooker.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,80 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-module Hyperactive
-
- #
- # A utility method to simplify using around-hooks for any block.
- #
- module Hooker
-
- #
- # Will call each hook in +hooks+ with a block that
- # calls the rest of the +hooks+ with +argument+ as argument
- # and after that yields to the given +block+.
- #
- # This will allow you wrap any method call in a dynamic set
- # of other methods.
- #
- # For more examples, see Hyperactive::Record.
- #
- # Example:
- # class ImportantStuff
- # attr_accessor :timestamp
- # def is_valid?
- # # do nifty stuff
- # end
- # def notify_someone_that_i_am_changed!(message)
- # # do even more nifty stuff
- # end
- # def validate_and_notify(message)
- # raise "i am invalid!" unless is_valid?
- # yield
- # notify_someone_that_i_am_changed!(message)
- # end
- # def do_save
- # # save me in persistent storage
- # end
- # end
- # class ImportantHandler
- # def update_timestamp(important_stuff_instance)
- # important_stuff_instance.timestamp = Time.now
- # Hyperactive::Hooker.call_with_hooks("changed at #{Time.now}",
- # important_stuff_instance.method(:validate_and_notify)) do
- # important_stuff_instance.do_save
- # end
- # end
- # end
- #
- def call_with_hooks(argument, *hooks, &block)
- if hooks.empty?
- yield
- else
- first = hooks.first
- rest = hooks[1..-1]
- first.call(argument) do
- call_with_hooks(argument, *rest, &block)
- end
- end
- end
-
- module_function :call_with_hooks
-
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/lib/hyperactive/hooker.rb (from rev 89, trunk/hyperactive/lib/hyperactive/hooker.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/lib/hyperactive/hooker.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/hooker.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,190 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+module Hyperactive
+
+ #
+ # A container of utility hook methods.
+ #
+ module Hooker
+
+ #
+ # Something that uses hooks a lot, include if you want support for various types of hooks.
+ #
+ module Pimp
+
+ #
+ # Upon inclusion, our +base+ class will be given a set of hook
+ # arrays, and then get extended by ClassMethods.
+ #
+ def self.append_features(base)
+ super
+ base.instance_variable_set(:@create_hooks, [])
+ base.instance_variable_set(:@destroy_hooks, [])
+ base.instance_variable_set(:@save_hooks, [])
+ base.instance_variable_set(:@load_hooks, [])
+ base.extend(ClassMethods)
+ end
+
+ #
+ # This will allow us to wrap any write of us to persistent storage
+ # in the @save_hooks as long as the Archipelago::Hashish provider
+ # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
+ # of Hashish providers that do this.
+ #
+ def save_hook(old_value, &block)
+ self.class.with_hooks(:instance => self, :arguments => [old_value], :hooks => self.class.save_hooks) do
+ yield
+ end
+ end
+
+ #
+ # This will allow us to wrap any load of us from persistent storage
+ # in the @@load_hooks as long as the Archipelago::Hashish provider
+ # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
+ # of Hashish providers that do this.
+ #
+ def load_hook(&block)
+ self.class.with_hooks(:instance => self, :hooks => self.class.load_hooks) do
+ yield
+ end
+ end
+
+
+ #
+ # The class methods of a Pimp.
+ #
+ module ClassMethods
+
+ #
+ # Will wrap a block within nested calls to given hooks.
+ #
+ # Parameters:
+ # * :instance: An instance to send methods to, defaults to self
+ # * :arguments: Extra arguments to send to whatever we call, defaults to self
+ # * :hooks: An Array of hook objects. They can be either Strings or Symbols, or
+ # whatever else can be given to respond_to?, or they can be anything
+ # that respond_to?(:call). If the hook is something that
+ # respond_to?(:call) it will be called and given
+ # the the :instance and *:arguments and the provided +block+.
+ # Else the :instance.respond_to?(the given hook)
+ # must be true, and that :instance will be sent the given hook along with the :arguments and
+ # a block that does the rest of the hooks.
+ #
+ def with_hooks(options = {}, &block)
+ instance = options[:instance] || self
+ arguments = options[:arguments] || []
+ hooks = options[:hooks] || []
+
+ if hooks.empty?
+ yield
+ else
+ first = hooks.first
+ rest = hooks[1..-1]
+ if first.respond_to?(:call)
+ first.call(instance, *arguments) do
+ with_hooks(:instance => instance, :hooks => rest, :arguments => arguments, &block)
+ end
+ elsif instance.respond_to?(first)
+ instance.send(first, *arguments) do
+ with_hooks(:instance => instance, :hooks => rest, :arguments => arguments, &block)
+ end
+ else
+ raise "You can only send in hooks that are Symbols in the given instance or call'able objects"
+ end
+ end
+ end
+
+ #
+ # Upon inheritance, our +subclass+ will be given copies of our hooks.
+ #
+ def inherited(subclass)
+ subclass.instance_variable_set(:@create_hooks, @create_hooks.clone)
+ subclass.instance_variable_set(:@destroy_hooks, @destroy_hooks.clone)
+ subclass.instance_variable_set(:@save_hooks, @save_hooks.clone)
+ subclass.instance_variable_set(:@load_hooks, @load_hooks.clone)
+ end
+
+ #
+ # Return our create_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent the instance about to be created (initial
+ # insertion into the database system) that take a block argument.
+ #
+ # The block argument will be a Proc that actually injects the
+ # instance into the database system.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon creation.
+ #
+ attr_reader :create_hooks
+
+ #
+ # Return our destroy_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent the instance about to be destroyed (removal
+ # from the database system) that take a block argument.
+ #
+ # The block argument will be a Proc that actually removes the
+ # instance from the database system.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon destruction.
+ #
+ attr_reader :destroy_hooks
+
+ #
+ # Return our load_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent the instance about to be loaded (insertion
+ # into the live hash of the database in question) that take a block argument.
+ #
+ # The block argument will be a Proc that actually puts the
+ # instance into the live hash.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon loading.
+ #
+ attr_reader :load_hooks
+
+ #
+ # Return our save_hooks, which can then be treated as any old Array.
+ #
+ # These must be callable objects with an arity of 1
+ # that will be sent [the old version, the new version] of the
+ # instance about to be saved (storage into the database system)
+ # along with a block argument.
+ #
+ # The block argument will be a Proc that actually saves the
+ # instance into the database system.
+ #
+ # Use this to preprocess, validate and/or postprocess your
+ # instances upon saving.
+ #
+ attr_reader :save_hooks
+
+ end
+
+ end
+
+ end
+
+end
Copied: tags/release_0_2_4/hyperactive/lib/hyperactive/index.rb (from rev 90, trunk/hyperactive/lib/hyperactive/index.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/lib/hyperactive/index.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/index.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,210 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Hyperactive
+
+ module Index
+
+ #
+ # A tiny callable class that saves stuff in
+ # indexes depending on certain attributes.
+ #
+ class IndexBuilder
+ #
+ # Get the key for the given attributes and values.
+ #
+ def self.get_key(klass, attributes, values)
+ "Hyperactive::IndexBuilder::#{klass}::#{attributes.join(",")}::#{values.join(",")}"
+ end
+ #
+ # Initialize an IndexBuilder giving it an array of +attributes+
+ # that will be indexed.
+ #
+ def initialize(klass, attributes)
+ @klass = klass
+ @attributes = attributes
+ end
+ #
+ # Get the key for the given +record+.
+ #
+ def get_key_for(record)
+ values = @attributes.collect do |att|
+ if record.respond_to?(att)
+ record.send(att)
+ else
+ nil
+ end
+ end
+ key = self.class.get_key(@klass, @attributes, values)
+ end
+ #
+ # Call this IndexBuilder and pass it a +block+.
+ #
+ # If the +argument+ is an Array then we know we are a save hook,
+ # otherwise we are a destroy hook.
+ #
+ def call(*arguments, &block)
+ yield
+
+ #
+ # If the argument is an Array (of old value, new value)
+ # then we are a save hook, otherwise a destroy hook.
+ #
+ if arguments.size > 1
+ record = arguments.first
+ old_record = arguments.last
+ old_key = get_key_for(old_record)
+ new_key = get_key_for(record)
+ if old_key != new_key
+ (CAPTAIN[old_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
+ (CAPTAIN[new_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction))[record.record_id] = record
+ end
+ else
+ record = arguments.first
+ (CAPTAIN[get_key_for(record)] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
+ end
+ end
+ end
+
+ #
+ # A tiny callable class that saves stuff inside containers
+ # if they match certain criteria.
+ #
+ class MatchSaver
+ #
+ # Initialize this MatchSaver with a +key+, a callable +matcher+
+ # and a +mode+ (:select, :reject, :delete_if_match or :delete_unless_match).
+ #
+ def initialize(key, matcher, mode)
+ @key = key
+ @matcher = matcher
+ @mode = mode
+ end
+ #
+ # Depending on @mode and return value of @matcher.call
+ # may save record in the Hash-like container named @key in
+ # the main database after having yielded to +block+.
+ #
+ def call(*arguments, &block)
+ yield
+
+ record = arguments.first
+
+ case @mode
+ when :select
+ if @matcher.call(record)
+ CAPTAIN[@key, record.transaction][record.record_id] = record
+ else
+ CAPTAIN[@key, record.transaction].delete(record.record_id)
+ end
+ when :reject
+ if @matcher.call(record)
+ CAPTAIN[@key, record.transaction].delete(record.record_id)
+ else
+ CAPTAIN[@key, record.transaction][record.record_id] = record
+ end
+ when :delete_if_match
+ if @matcher.call(record)
+ CAPTAIN[@key, record.transaction].delete(record.record_id)
+ end
+ when :delete_unless_match
+ unless @matcher.call(record)
+ CAPTAIN[@key, record.transaction].delete(record.record_id)
+ end
+ end
+ end
+ end
+
+ module Indexable
+
+ def self.append_features(base)
+ super
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ #
+ # Create an index for this class.
+ #
+ # Will create a method find_by_#{attributes.join("_and_")} for this
+ # class that will return what you expect.
+ #
+ def index_by(*attributes)
+ klass = self
+ self.class.class_eval do
+ define_method("find_by_#{attributes.join("_and_")}") do |*args|
+ CAPTAIN[IndexBuilder.get_key(klass, attributes, args)]
+ end
+ end
+ index_builder = IndexBuilder.new(self, attributes)
+ self.save_hooks << index_builder
+ self.destroy_hooks << index_builder
+ end
+
+ #
+ # Will define a method called +name+ that will include all
+ # existing instances of this class that when yielded to the +block+
+ # returns true. Will only return instances saved after this selector
+ # is defined.
+ #
+ def select(name, &block) #:yields: instance
+ key = collection_key(name)
+ CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
+ self.class.class_eval do
+ define_method(name) do
+ CAPTAIN[key]
+ end
+ end
+ self.save_hooks << MatchSaver.new(key, block, :select)
+ self.destroy_hooks << MatchSaver.new(key, block, :delete_if_match)
+ end
+
+ #
+ # Will define a method called +name+ that will include all
+ # existing instances of this class that when yielded to +block+
+ # does not return true. Will only return instances saved after this
+ # rejector is defined.
+ #
+ def reject(name, &block) #:yields: instance
+ key = collection_key(name)
+ CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
+ self.class.class_eval do
+ define_method(name) do
+ CAPTAIN[key]
+ end
+ end
+ self.save_hooks << MatchSaver.new(key, block, :reject)
+ self.destroy_hooks << MatchSaver.new(key, block, :delete_unless_match)
+ end
+
+ private
+
+ #
+ # The key used to store the collection with the given +sym+ as name.
+ #
+ def collection_key(sym)
+ "Hyperactive::Index::Indexable::collection_key::#{sym}"
+ end
+
+
+ end
+
+ end
+
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/lib/hyperactive/list.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/list.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/list.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,239 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-require 'rubygems'
-require 'archipelago'
-
-module Hyperactive
-
- #
- # A package that simplifies putting dumb linked lists in the distributed database.
- #
- module List
-
- #
- # A wrapper class that knows its previous and next List::Elements as well as its value and the id of its list.
- #
- class Element < Hyperactive::Record::Bass
- attr_accessor :previous, :next, :value, :list_id
-
- include Archipelago::Current::ThreadedCollection
-
- #
- # Initialize this List::Element with given +previous_element+, +next_element+, +value+ and +list_id+.
- #
- def initialize(previous_element, next_element, value, list_id)
- self.previous = previous_element
- self.next = next_element
- self.value = value
- self.list_id = list_id
- end
-
- #
- # Yield to +block+ once for this and each following element.
- #
- def each(&block)
- element = self
- while element
- yield(element)
- element = self.next
- end
- end
- end
-
- #
- # A List head.
- #
- class Head < Hyperactive::Record::Bass
- attr_accessor :first_element, :last_element, :size
-
- include Archipelago::Current::ThreadedCollection
-
- #
- # Create a List::Head. This is in essence the linked list.
- #
- # NB: Remember to call create on the new instance or use Head.get_instance to get that done automatically.
- #
- def initialize
- self.size = 0
- self.first_element = self.last_element = nil
- end
-
- #
- # Unlinks the given +element+ and reconnects the List around it.
- #
- def unlink!(element)
- raise "#{element} is not a part of #{self}" unless element.list_id == @record_id
-
- if size > 1
- if element == self.first_element
- self.first_element = element.next
- self.first_element.previous = nil
- elsif element == self.last_element
- self.last_element = element.previous
- self.last_element.next = nil
- else
- element.previous.next = element.next
- element.next.previous = element.previous
- end
- else
- if element == self.first_element
- self.first_element = self.last_element = nil
- else
- raise "#{element} is not a part of #{self} even though it claims to be"
- end
- end
- self.size -= 1
- element.destroy!
- end
-
- #
- # Remove all elements from this List::Head.
- #
- def clear!
- self.first_element.t_each do |element|
- element.destroy!
- end
- self.first_element = self.last_element = nil
- self.size = 0
- end
-
- #
- # Destroys this list and all its elements.
- #
- def destroy!
- self.clear!
- super
- end
-
- #
- # Return the first value of the list.
- #
- def first
- if self.first_element
- self.first_element.value
- else
- nil
- end
- end
-
- #
- # Return the last value of the list.
- #
- def last
- if self.last_element
- self.last_element.value
- else
- end
- end
-
- #
- # Push +v+ onto the end of this list.
- #
- def <<(v)
- if self.first_element
- new_element = Element.get_instance_with_transaction(@transaction, self.last_element, nil, v, @record_id)
- self.last_element.next = new_element
- self.last_element = new_element
- else
- start(v)
- end
- self.size += 1
- return v
- end
-
- #
- # Push +v+ onto the beginning of this list.
- #
- def unshift(v)
- if self.first_element
- new_element = Element.get_instance_with_transaction(@transaction, nil, self.first_element, v, @record_id)
- self.first_element.previous = new_element
- self.first_element = new_element
- else
- start(v)
- end
- self.size += 1
- return v
- end
-
- #
- # Remove the last value from this list and return it.
- #
- def pop
- v = nil
- if size > 1
- element = self.last_element
- self.last_element = element.previous
- self.last_element.next = nil
- v = element.value
- element.destroy!
- else
- v = self.first_element.value
- self.first_element.destroy!
- self.first_element = self.last_element = nil
- end
- self.size -= 1
- return v
- end
-
- #
- # Yield to +block+ once for each value in this list.
- #
- def each(&block)
- element = self.first_element
- while element
- yield(element.value)
- element = element.next
- end
- end
-
- #
- # Remove the first value from this list and return it.
- #
- def shift
- v = nil
- if size > 1
- element = self.first_element
- self.first_element = element.next
- self.first_element.previous = nil
- v = element.value
- element.destroy!
- else
- v = self.first_element.value
- self.first_element.destroy!
- self.first_element = self.last_element = nil
- end
- self.size -= 1
- return v
- end
-
- private
-
- #
- # Start this list with +v+ when it has no other values.
- #
- def start(v)
- self.first_element = self.last_element = Element.get_instance_with_transaction(@transaction, nil, nil, v, @record_id)
- end
-
- end
-
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/lib/hyperactive/list.rb (from rev 89, trunk/hyperactive/lib/hyperactive/list.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/lib/hyperactive/list.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/list.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,247 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+require 'rubygems'
+require 'archipelago'
+
+module Hyperactive
+
+ #
+ # A package that simplifies putting dumb linked lists in the distributed database.
+ #
+ module List
+
+ #
+ # A wrapper class that knows its previous and next List::Elements as well as its value and the id of its list.
+ #
+ class Element < Hyperactive::Record::Bass
+ attr_accessor :previous, :next, :value, :list_id
+
+ include Archipelago::Current::ThreadedCollection
+
+ #
+ # Initialize this List::Element with given +previous_element+, +next_element+, +value+ and +list_id+.
+ #
+ def initialize(previous_element, next_element, value, list_id)
+ self.previous = previous_element
+ self.next = next_element
+ self.value = value
+ self.list_id = list_id
+ end
+
+ #
+ # Yield to +block+ once for this and each following element.
+ #
+ def each(&block)
+ element = self
+ while element
+ yield(element)
+ element = self.next
+ end
+ end
+ end
+
+ #
+ # A List head.
+ #
+ class Head < Hyperactive::Record::Bass
+ attr_accessor :first_element, :last_element, :size
+
+ include Archipelago::Current::ThreadedCollection
+
+ #
+ # Create a List::Head. This is in essence the linked list.
+ #
+ # NB: Remember to call create on the new instance or use Head.get_instance to get that done automatically.
+ #
+ def initialize
+ super
+ self.size = 0
+ self.first_element = self.last_element = nil
+ end
+
+ #
+ # Unlinks the given +element+ and reconnects the List around it.
+ #
+ def unlink!(element)
+ raise "#{element} is not a part of #{self}" unless element.list_id == @record_id
+
+ if size > 1
+ if element == self.first_element
+ self.first_element = element.next
+ self.first_element.previous = nil
+ elsif element == self.last_element
+ self.last_element = element.previous
+ self.last_element.next = nil
+ else
+ element.previous.next = element.next
+ element.next.previous = element.previous
+ end
+ else
+ if element == self.first_element
+ self.first_element = self.last_element = nil
+ else
+ raise "#{element} is not a part of #{self} even though it claims to be"
+ end
+ end
+ self.size -= 1
+ element.destroy!
+ end
+
+ #
+ # Return whether this List is empty.
+ #
+ def empty?
+ return self.size == 0
+ end
+
+ #
+ # Remove all elements from this List::Head.
+ #
+ def clear!
+ self.first_element.t_each do |element|
+ element.destroy!
+ end
+ self.first_element = self.last_element = nil
+ self.size = 0
+ end
+
+ #
+ # Destroys this list and all its elements.
+ #
+ def destroy!
+ self.clear!
+ super
+ end
+
+ #
+ # Return the first value of the list.
+ #
+ def first
+ if self.first_element
+ self.first_element.value
+ else
+ nil
+ end
+ end
+
+ #
+ # Return the last value of the list.
+ #
+ def last
+ if self.last_element
+ self.last_element.value
+ else
+ end
+ end
+
+ #
+ # Push +v+ onto the end of this list.
+ #
+ def <<(v)
+ if self.first_element
+ new_element = Element.get_instance_with_transaction(@transaction, self.last_element, nil, v, @record_id)
+ self.last_element.next = new_element
+ self.last_element = new_element
+ else
+ start(v)
+ end
+ self.size += 1
+ return v
+ end
+
+ #
+ # Push +v+ onto the beginning of this list.
+ #
+ def unshift(v)
+ if self.first_element
+ new_element = Element.get_instance_with_transaction(@transaction, nil, self.first_element, v, @record_id)
+ self.first_element.previous = new_element
+ self.first_element = new_element
+ else
+ start(v)
+ end
+ self.size += 1
+ return v
+ end
+
+ #
+ # Remove the last value from this list and return it.
+ #
+ def pop
+ v = nil
+ if size > 1
+ element = self.last_element
+ self.last_element = element.previous
+ self.last_element.next = nil
+ v = element.value
+ element.destroy!
+ else
+ v = self.first_element.value
+ self.first_element.destroy!
+ self.first_element = self.last_element = nil
+ end
+ self.size -= 1
+ return v
+ end
+
+ #
+ # Yield to +block+ once for each value in this list.
+ #
+ def each(&block)
+ element = self.first_element
+ while element
+ yield(element.value)
+ element = element.next
+ end
+ end
+
+ #
+ # Remove the first value from this list and return it.
+ #
+ def shift
+ v = nil
+ if size > 1
+ element = self.first_element
+ self.first_element = element.next
+ self.first_element.previous = nil
+ v = element.value
+ element.destroy!
+ else
+ v = self.first_element.value
+ self.first_element.destroy!
+ self.first_element = self.last_element = nil
+ end
+ self.size -= 1
+ return v
+ end
+
+ private
+
+ #
+ # Start this list with +v+ when it has no other values.
+ #
+ def start(v)
+ self.first_element = self.last_element = Element.get_instance_with_transaction(@transaction, nil, nil, v, @record_id)
+ end
+
+ end
+
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/record.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,518 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-require 'rubygems'
-require 'archipelago'
-
-#
-# A utility module to provide the functionality required for example
-# if you want to use archipelago in a Ruby on Rails project *hint hint*.
-#
-module Hyperactive
-
- #
- # The package containing the base class Bass that simplifies
- # using archipelago for generic database stuff.
- #
- module Record
-
- #
- # The default database connector.
- #
- CAPTAIN = Archipelago::Pirate::Captain.new
-
- #
- # A tiny callable class that saves stuff in
- # indexes depending on certain attributes.
- #
- class IndexBuilder
- #
- # Get the first part of the key, that depends on the +attributes+.
- #
- def self.get_attribute_key_part(attributes)
- "Hyperactive::IndexBuilder::#{attributes.join(",")}"
- end
- #
- # Get the last part of the key, that depends on the +values+.
- #
- def self.get_value_key_part(values)
- "#{values.join(",")}"
- end
- #
- # Initialize an IndexBuilder giving it an array of +attributes+
- # that will be indexed.
- #
- def initialize(attributes)
- @attributes = attributes
- end
- #
- # Get the key for the given +record+.
- #
- def get_key_for(record)
- values = @attributes.collect do |att|
- if record.respond_to?(att)
- record.send(att)
- else
- nil
- end
- end
- key = "#{self.class.get_attribute_key_part(@attributes)}::#{self.class.get_value_key_part(values)}"
- end
- #
- # Call this IndexBuilder and pass it a +block+.
- #
- # If the +argument+ is an Array then we know we are a save hook,
- # otherwise we are a destroy hook.
- #
- def call(argument, &block)
- yield
-
- #
- # If the argument is an Array (of old value, new value)
- # then we are a save hook, otherwise a destroy hook.
- #
- if Array === argument
- record = argument.last
- old_record = argument.first
- old_key = get_key_for(old_record)
- new_key = get_key_for(record)
- if old_key != new_key
- (CAPTAIN[old_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
- (CAPTAIN[new_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction))[record.record_id] = record
- end
- else
- record = argument
- (CAPTAIN[get_key_for(record)] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
- end
- end
- end
-
- #
- # A tiny callable class that saves stuff inside containers
- # if they match certain criteria.
- #
- class MatchSaver
- #
- # Initialize this MatchSaver with a +key+, a callable +matcher+
- # and a +mode+ (:select, :reject, :delete_if_match or :delete_unless_match).
- #
- def initialize(key, matcher, mode)
- @key = key
- @matcher = matcher
- @mode = mode
- end
- #
- # Depending on @mode and return value of @matcher.call
- # may save record in the Hash-like container named @key in
- # the main database after having yielded to +block+.
- #
- def call(argument, &block)
- yield
-
- record = argument
- record = argument.last if Array === argument
-
- case @mode
- when :select
- if @matcher.call(record)
- CAPTAIN[@key, record.transaction][record.record_id] = record
- else
- CAPTAIN[@key, record.transaction].delete(record.record_id)
- end
- when :reject
- if @matcher.call(record)
- CAPTAIN[@key, record.transaction].delete(record.record_id)
- else
- CAPTAIN[@key, record.transaction][record.record_id] = record
- end
- when :delete_if_match
- if @matcher.call(record)
- CAPTAIN[@key, record.transaction].delete(record.record_id)
- end
- when :delete_unless_match
- unless @matcher.call(record)
- CAPTAIN[@key, record.transaction].delete(record.record_id)
- end
- end
- end
- end
-
- #
- # A convenient base class to inherit when you want the basic utility methods
- # provided by for example ActiveRecord::Base *hint hint*.
- #
- # NB: When an instance is created you will actually have a copy within your local machine
- # which is not what you usually want. Every other time you fetch it using a select or other
- # method you will instead receive a proxy object to the database. This means that nothing you
- # do to it at that point will be persistent or even necessarily have a defined result.
- # Therefore: do not use the instantiated object, instead call my_instance.save
- # to get a proxy to the object stored into the database.
- #
- class Bass
-
- @@create_hooks_by_class = {}
- @@destroy_hooks_by_class = {}
- @@save_hooks_by_class = {}
- @@load_hooks_by_class = {}
-
- #
- # The host we are running on.
- #
- HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
-
- #
- # Call this if you want to change the default database connector
- # to something else.
- #
- def self.setup(options = {})
- CAPTAIN.setup(options[:pirate_options])
- end
-
- #
- # Works like normal attr_reader but with transactional awareness.
- #
- def self.attr_reader(*attributes)
- attributes.each do |attribute|
- define_method(attribute) do
- value = instance_variable_get("@#{attribute}")
- if Archipelago::Treasure::Dubloon === value
- if @transaction ||= nil
- return value.join(@transaction)
- else
- return value
- end
- else
- return value
- end
- end
- end
- end
-
- #
- # Works like normal attr_writer but with transactional awareness.
- #
- def self.attr_writer(*attributes)
- attributes.each do |attribute|
- define_method("#{attribute}=") do |new_value|
- if Archipelago::Treasure::Dubloon === new_value
- new_value.assert_transaction(@transaction) if @transaction ||= nil
- instance_variable_set("@#{attribute}", new_value)
- else
- instance_variable_set("@#{attribute}", new_value)
- end
- end
- end
- end
-
- #
- # Works like normal attr_accessor but with transactional awareness.
- #
- def self.attr_accessor(*attributes)
- attr_reader(*attributes)
- attr_writer(*attributes)
- end
-
- #
- # Return our create_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent the instance about to be created (initial
- # insertion into the database system) that take a block argument.
- #
- # The block argument will be a Proc that actually injects the
- # instance into the database system.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon creation.
- #
- def self.create_hooks
- self.get_hook_array_by_class(@@create_hooks_by_class)
- end
-
- #
- # Return our destroy_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent the instance about to be destroyed (removal
- # from the database system) that take a block argument.
- #
- # The block argument will be a Proc that actually removes the
- # instance from the database system.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon destruction.
- #
- def self.destroy_hooks
- self.get_hook_array_by_class(@@destroy_hooks_by_class)
- end
-
- #
- # Return our load_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent the instance about to be loaded (insertion
- # into the live hash of the database in question) that take a block argument.
- #
- # The block argument will be a Proc that actually puts the
- # instance into the live hash.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon loading.
- #
- def self.load_hooks
- self.get_hook_array_by_class(@@load_hooks_by_class)
- end
-
- #
- # Return our save_hooks, which can then be treated as any old Array.
- #
- # These must be callable objects with an arity of 1
- # that will be sent [the old version, the new version] of the
- # instance about to be saved (storage into the database system)
- # along with a block argument.
- #
- # The block argument will be a Proc that actually saves the
- # instance into the database system.
- #
- # Use this to preprocess, validate and/or postprocess your
- # instances upon saving.
- #
- def self.save_hooks
- self.get_hook_array_by_class(@@save_hooks_by_class)
- end
-
- #
- # Create an index for this class.
- #
- # Will create a method find_by_#{attributes.join("_and_")} for this
- # class that will return what you expect.
- #
- def self.index_by(*attributes)
- attribute_key_part = IndexBuilder.get_attribute_key_part(attributes)
- self.class_eval <(o)
- if Record === o
- @record_id <=> o.record_id
- else
- 0
- end
- end
-
- #
- # Save this Record instance into the distributed database and return a proxy to the saved object.
- #
- # This will also wrap the actual insertion within the create_hooks you have defined for this class.
- #
- def create
- @record_id ||= Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}").to_s
- @transaction ||= nil
-
- Hyperactive::Hooker.call_with_hooks(self, *self.class.create_hooks) do
- CAPTAIN[self.record_id, @transaction] = self
- end
-
- proxy = CAPTAIN[@record_id, @transaction]
-
- return proxy
- end
-
- #
- # Will execute +block+ within a transaction.
- #
- # What it does is just set the @transaction instance variable
- # before calling the block, and unsetting it after.
- #
- # This means that any classes that want to be transaction sensitive
- # need to take heed regarding the @transaction instance variable.
- #
- # For example, when creating new Record instances you may want to use
- # get_instance_with_transaction(@transaction, *args) to ensure that the
- # new instance exists within the same transaction as yourself.
- #
- # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
- #
- def with_transaction(transaction, &block)
- @transaction = transaction
- begin
- yield
- ensure
- @transaction = nil
- end
- end
-
- #
- # This will allow us to wrap any write of us to persistent storage
- # in the @@save_hooks as long as the Archipelago::Hashish provider
- # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
- # of Hashish providers that do this.
- #
- def save_hook(old_value, &block)
- Hyperactive::Hooker.call_with_hooks([old_value, self], *self.class.save_hooks) do
- yield
- end
- end
-
- #
- # This will allow us to wrap any load of us from persistent storage
- # in the @@load_hooks as long as the Archipelago::Hashish provider
- # supports it. See Archipelago::Hashish::BerkeleyHashish for an example
- # of Hashish providers that do this.
- #
- def load_hook(&block)
- Hyperactive::Hooker.call_with_hooks(self, *self.class.load_hooks) do
- yield
- end
- end
-
- #
- # Remove this instance from the database calling all the right hooks.
- #
- # Freezes this instance after having deleted it.
- #
- # Returns false without destroying anything if any of the @@pre_destroy_hooks
- # returns false.
- #
- # Returns true otherwise.
- #
- def destroy!
- Hyperactive::Hooker.call_with_hooks(self, *self.class.destroy_hooks) do
- CAPTAIN.delete(@record_id, @transaction)
- self.freeze
- end
- end
-
- private
-
- #
- # The key used to store the collection with the given +sym+ as name.
- #
- def self.collection_key(sym)
- "Hyperactive::Record::Bass::collection_key::#{sym}"
- end
-
- #
- # Get an Array from +hash+ using self as
- # key. If self doesnt exist in the +hash+
- # it will recurse by calling the same method in the
- # superclass until it has been called in Hyperactive::Record::Base.
- #
- def self.get_hook_array_by_class(hash)
- return hash[self] if hash.include?(self)
-
- if self == Bass
- hash[self] = []
- return self.get_hook_array_by_class(hash)
- else
- hash[self] = self.superclass.get_hook_array_by_class(hash).clone
- return self.get_hook_array_by_class(hash)
- end
- end
-
- end
- end
-end
-
Copied: tags/release_0_2_4/hyperactive/lib/hyperactive/record.rb (from rev 90, trunk/hyperactive/lib/hyperactive/record.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/lib/hyperactive/record.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/record.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,131 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+require 'rubygems'
+require 'archipelago'
+
+#
+# A utility module to provide the functionality required for example
+# if you want to use archipelago in a Ruby on Rails project *hint hint*.
+#
+module Hyperactive
+
+ #
+ # The default database connector.
+ #
+ CAPTAIN = Archipelago::Pirate::Captain.new
+
+ #
+ # The package containing the base class Bass that simplifies
+ # using archipelago for generic database stuff.
+ #
+ module Record
+
+ #
+ # A convenient base class to inherit when you want the basic utility methods
+ # provided by for example ActiveRecord::Base *hint hint*.
+ #
+ # NB: When an instance is created you will actually have a copy within your local machine
+ # which is not what you usually want. Every other time you fetch it using a select or other
+ # method you will instead receive a proxy object to the database. This means that nothing you
+ # do to it at that point will be persistent or even necessarily have a defined result.
+ # Therefore: do not use the instantiated object, instead call my_instance.save
+ # to get a proxy to the object stored into the database.
+ #
+ class Bass
+
+ include Hyperactive::Index::Indexable
+ include Hyperactive::Transactions::Accessors
+ include Hyperactive::Transactions::Participant
+ include Hyperactive::Hooker::Pimp
+
+ #
+ # The host we are running on.
+ #
+ HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
+
+ #
+ # Return the record with +record_id+, optionally within a +transaction+.
+ #
+ def self.find(record_id, transaction = nil)
+ CAPTAIN[record_id, transaction]
+ end
+
+ #
+ # Utility method to get a proxy to a newly saved instance of this class in one call.
+ #
+ def self.get_instance(*args)
+ instance = self.new(*args)
+ return instance.create
+ end
+
+ #
+ # Our semi-unique id.
+ #
+ attr_reader :record_id
+
+ #
+ # Utility compare method. Override as you please.
+ #
+ def <=>(o)
+ if Record === o
+ @record_id <=> o.record_id
+ else
+ 0
+ end
+ end
+
+ def initialize
+ @record_id = nil
+ @transaction = nil
+ end
+
+ #
+ # Save this Record instance into the distributed database and return a proxy to the saved object.
+ #
+ # This will also wrap the actual insertion within the create_hooks you have defined for this class.
+ #
+ def create
+ @record_id ||= Digest::SHA1.hexdigest("#{HOST}:#{Time.new.to_f}:#{self.object_id}:#{rand(1 << 32)}").to_s
+ @transaction ||= nil
+
+ self.class.with_hooks(:instance => self, :hooks => self.class.create_hooks) do
+ CAPTAIN[self.record_id, @transaction] = self
+ end
+
+ proxy = CAPTAIN[@record_id, @transaction]
+
+ return proxy
+ end
+
+ #
+ # Remove this instance from the database wrapped in our destroy_hooks.
+ #
+ # Freezes this instance after having deleted it.
+ #
+ def destroy!
+ self.class.with_hooks(:instance => self, :hooks => self.class.destroy_hooks) do
+ CAPTAIN.delete(@record_id, @transaction)
+ self.freeze
+ end
+ end
+
+ end
+ end
+end
+
Copied: tags/release_0_2_4/hyperactive/lib/hyperactive/transactions.rb (from rev 90, trunk/hyperactive/lib/hyperactive/transactions.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/lib/hyperactive/transactions.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive/transactions.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,154 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Hyperactive
+
+ #
+ # A utility package of transaction handling methods.
+ #
+ module Transactions
+
+ #
+ # Include this to get methods to do with participating in a transaction.
+ #
+ module Participant
+
+ #
+ # The transaction we are currently in.
+ #
+ attr_reader :transaction
+
+ #
+ # Will execute +block+ within a transaction.
+ #
+ # What it does is just set the @transaction instance variable
+ # before calling the block, and unsetting it after.
+ #
+ # This means that any classes that want to be transaction sensitive
+ # need to take heed regarding the @transaction instance variable.
+ #
+ # For example, when creating new Record instances you may want to use
+ # get_instance_with_transaction(@transaction, *args) to ensure that the
+ # new instance exists within the same transaction as yourself.
+ #
+ # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
+ #
+ def with_transaction(transaction, &block)
+ @transaction = transaction
+ begin
+ yield
+ ensure
+ @transaction = nil
+ end
+ end
+
+ #
+ # Add our ClassMethods to anyone that includes us.
+ #
+ def self.append_features(base)
+ super
+ base.extend(ClassMethods)
+ end
+
+ #
+ # Class methods for transaction participants.
+ #
+ module ClassMethods
+ #
+ # Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
+ #
+ def get_instance_with_transaction(transaction, *args)
+ instance = self.new(*args)
+ return_value = nil
+ instance.with_transaction(transaction) do
+ return_value = instance.create
+ end
+ return return_value
+ end
+
+ end
+
+ end
+
+ #
+ # Include this to get the default attr_reader at al redefined to be transactionally aware.
+ #
+ module Accessors
+
+ #
+ # The +base+ class including this will get a our ClassMethods as well.
+ #
+ def self.append_features(base)
+ super
+ base.extend(ClassMethods)
+ end
+
+ #
+ # The class methods that help us set/get instance variables in a transactionally aware way.
+ #
+ module ClassMethods
+ #
+ # Works like normal attr_reader but with transactional awareness.
+ #
+ def attr_reader(*attributes)
+ attributes.each do |attribute|
+ define_method(attribute) do
+ value = instance_variable_get("@#{attribute}")
+ if Archipelago::Treasure::Dubloon === value
+ if @transaction ||= nil
+ return value.join(@transaction)
+ else
+ return value
+ end
+ else
+ return value
+ end
+ end
+ end
+ end
+
+ #
+ # Works like normal attr_writer but with transactional awareness.
+ #
+ def attr_writer(*attributes)
+ attributes.each do |attribute|
+ define_method("#{attribute}=") do |new_value|
+ if Archipelago::Treasure::Dubloon === new_value
+ new_value.assert_transaction(@transaction) if @transaction ||= nil
+ instance_variable_set("@#{attribute}", new_value)
+ else
+ instance_variable_set("@#{attribute}", new_value)
+ end
+ end
+ end
+ end
+
+ #
+ # Works like normal attr_accessor but with transactional awareness.
+ #
+ def attr_accessor(*attributes)
+ attr_reader(*attributes)
+ attr_writer(*attributes)
+ end
+
+ end
+
+ end
+
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/lib/hyperactive.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,23 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-$: << File.dirname(__FILE__)
-
-require 'hyperactive/hooker'
-require 'hyperactive/record'
-require 'hyperactive/hash'
-require 'hyperactive/list'
Copied: tags/release_0_2_4/hyperactive/lib/hyperactive.rb (from rev 87, trunk/hyperactive/lib/hyperactive.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/lib/hyperactive.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/lib/hyperactive.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,25 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+$: << File.dirname(__FILE__)
+
+require 'hyperactive/hooker'
+require 'hyperactive/index'
+require 'hyperactive/transactions'
+require 'hyperactive/record'
+require 'hyperactive/hash'
+require 'hyperactive/list'
Deleted: tags/release_0_2_4/hyperactive/tests/hash_benchmark.rb
===================================================================
--- trunk/hyperactive/tests/hash_benchmark.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/tests/hash_benchmark.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,66 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class HashBenchmark < Test::Unit::TestCase
-
- def setup
- @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
- @c.publish!
- @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
- @c2.publish!
- @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
- @tm.publish!
- Hyperactive::Record::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
- :tranny_description => {:class => 'TestManager'})
- assert_within(20) do
- Set.new(Hyperactive::Record::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
- end
- assert_within(20) do
- Hyperactive::Record::CAPTAIN.trannies.keys == [@tm.service_id]
- end
- end
-
- def teardown
- @c.stop!
- @c.persistence_provider.unlink!
- @c2.stop!
- @c2.persistence_provider.unlink!
- @tm.stop!
- @tm.persistence_provider.unlink!
- end
-
- def test_set_get
- h = Hyperactive::Hash::Head.get_instance
- r = Hyperactive::Record::Bass.get_instance
- hash_test("Hyperactive::Hash", h, r, 100)
- end
-
- def test_regular_hash_set_get
- Hyperactive::Record::CAPTAIN["h"] = {}
- h = Hyperactive::Record::CAPTAIN["h"]
- r = Hyperactive::Record::Bass.get_instance
- hash_test("Hash", h, r, 100)
- end
-
- private
-
- def hash_test(label, h, r, c)
- bm("#{label}#set/get/delete", :n => c * 1) do
- f = rand(1 << 32)
- h[f] = r
- x = h[f]
- h.delete(f)
- end
- bm("#{label}#set", :n => c * 10) do
- f = rand(1 << 32)
- h[f] = r
- end
- bm("#{label}#set/get/delete (big)", :n => c * 1) do
- f = rand(1 << 32)
- h[f] = r
- x = h[f]
- h.delete(f)
- end
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/tests/hash_benchmark.rb (from rev 87, trunk/hyperactive/tests/hash_benchmark.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/tests/hash_benchmark.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/tests/hash_benchmark.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,66 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class HashBenchmark < Test::Unit::TestCase
+
+ def setup
+ @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
+ @c.publish!
+ @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
+ @c2.publish!
+ @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
+ @tm.publish!
+ Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ :tranny_description => {:class => 'TestManager'})
+ assert_within(20) do
+ Set.new(Hyperactive::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
+ end
+ assert_within(20) do
+ Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ end
+ end
+
+ def teardown
+ @c.stop!
+ @c.persistence_provider.unlink!
+ @c2.stop!
+ @c2.persistence_provider.unlink!
+ @tm.stop!
+ @tm.persistence_provider.unlink!
+ end
+
+ def test_set_get
+ h = Hyperactive::Hash::Head.get_instance
+ r = Hyperactive::Record::Bass.get_instance
+ hash_test("Hyperactive::Hash", h, r, 100)
+ end
+
+ def test_regular_hash_set_get
+ Hyperactive::CAPTAIN["h"] = {}
+ h = Hyperactive::CAPTAIN["h"]
+ r = Hyperactive::Record::Bass.get_instance
+ hash_test("Hash", h, r, 100)
+ end
+
+ private
+
+ def hash_test(label, h, r, c)
+ bm("#{label}#set/get/delete", :n => c * 1) do
+ f = rand(1 << 32)
+ h[f] = r
+ x = h[f]
+ h.delete(f)
+ end
+ bm("#{label}#set", :n => c * 10) do
+ f = rand(1 << 32)
+ h[f] = r
+ end
+ bm("#{label}#set/get/delete (big)", :n => c * 1) do
+ f = rand(1 << 32)
+ h[f] = r
+ x = h[f]
+ h.delete(f)
+ end
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/tests/hash_test.rb
===================================================================
--- trunk/hyperactive/tests/hash_test.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/tests/hash_test.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,76 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class RecordMatcher
- def initialize(i)
- @i = i
- end
- def call(k,v)
- k == @i
- end
-end
-
-class HashTest < Test::Unit::TestCase
-
- def setup
- @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
- @c.publish!
- @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
- @c2.publish!
- @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
- @tm.publish!
- Hyperactive::Record::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
- :tranny_description => {:class => 'TestManager'})
- Hyperactive::Record::CAPTAIN.update_services!
- assert_within(10) do
- Hyperactive::Record::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
- end
- assert_within(10) do
- Hyperactive::Record::CAPTAIN.trannies.keys == [@tm.service_id]
- end
- end
-
- def teardown
- @c.stop!
- @c.persistence_provider.unlink!
- @c2.stop!
- @c2.persistence_provider.unlink!
- @tm.stop!
- @tm.persistence_provider.unlink!
- end
-
- def test_select_reject
- h = Hyperactive::Hash::Head.get_instance
- r1 = Hyperactive::Record::Bass.get_instance
- r2 = Hyperactive::Record::Bass.get_instance
- h[r1.record_id] = r1
- h[r2.record_id] = r2
- assert_equal(r1.record_id, h.t_select(RecordMatcher.new(r1.record_id)).first.first)
- assert_equal(r1.record_id, h.t_reject(RecordMatcher.new(r2.record_id)).first.first)
- end
-
- def test_delete
- h = Hyperactive::Hash::Head.get_instance
- r = Hyperactive::Record::Bass.get_instance
- h[r.record_id] = r
- assert(h.include?(r.record_id))
- h.delete(r.record_id)
- assert(!h.include?(r.record_id))
- end
-
- def test_set_get
- h = Hyperactive::Hash::Head.get_instance
- h2 = {}
- 10.times do
- r = Hyperactive::Record::Bass.get_instance
- h[r.record_id] = r
- h2[r.record_id] = r
- end
-
- h2.each do |k,v|
- assert_equal(v, h[k])
- assert_equal(v, Hyperactive::Record::CAPTAIN[h.record_id][k])
- end
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/tests/hash_test.rb (from rev 87, trunk/hyperactive/tests/hash_test.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/tests/hash_test.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/tests/hash_test.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,76 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class RecordMatcher
+ def initialize(i)
+ @i = i
+ end
+ def call(k,v)
+ k == @i
+ end
+end
+
+class HashTest < Test::Unit::TestCase
+
+ def setup
+ @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
+ @c.publish!
+ @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
+ @c2.publish!
+ @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
+ @tm.publish!
+ Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ :tranny_description => {:class => 'TestManager'})
+ Hyperactive::CAPTAIN.update_services!
+ assert_within(10) do
+ Hyperactive::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
+ end
+ assert_within(10) do
+ Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ end
+ end
+
+ def teardown
+ @c.stop!
+ @c.persistence_provider.unlink!
+ @c2.stop!
+ @c2.persistence_provider.unlink!
+ @tm.stop!
+ @tm.persistence_provider.unlink!
+ end
+
+ def test_select_reject
+ h = Hyperactive::Hash::Head.get_instance
+ r1 = Hyperactive::Record::Bass.get_instance
+ r2 = Hyperactive::Record::Bass.get_instance
+ h[r1.record_id] = r1
+ h[r2.record_id] = r2
+ assert_equal(r1.record_id, h.t_select(RecordMatcher.new(r1.record_id)).first.first)
+ assert_equal(r1.record_id, h.t_reject(RecordMatcher.new(r2.record_id)).first.first)
+ end
+
+ def test_delete
+ h = Hyperactive::Hash::Head.get_instance
+ r = Hyperactive::Record::Bass.get_instance
+ h[r.record_id] = r
+ assert(h.include?(r.record_id))
+ h.delete(r.record_id)
+ assert(!h.include?(r.record_id))
+ end
+
+ def test_set_get
+ h = Hyperactive::Hash::Head.get_instance
+ h2 = {}
+ 10.times do
+ r = Hyperactive::Record::Bass.get_instance
+ h[r.record_id] = r
+ h2[r.record_id] = r
+ end
+
+ h2.each do |k,v|
+ assert_equal(v, h[k])
+ assert_equal(v, Hyperactive::CAPTAIN[h.record_id][k])
+ end
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/tests/list_benchmark.rb
===================================================================
--- trunk/hyperactive/tests/list_benchmark.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/tests/list_benchmark.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,48 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class ListBenchmark < Test::Unit::TestCase
-
- def setup
- @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
- @c.publish!
- @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
- @c2.publish!
- @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
- @tm.publish!
- Hyperactive::Record::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
- :tranny_description => {:class => 'TestManager'})
- assert_within(20) do
- Set.new(Hyperactive::Record::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
- end
- assert_within(20) do
- Hyperactive::Record::CAPTAIN.trannies.keys == [@tm.service_id]
- end
- end
-
- def teardown
- @c.stop!
- @c.persistence_provider.unlink!
- @c2.stop!
- @c2.persistence_provider.unlink!
- @tm.stop!
- @tm.persistence_provider.unlink!
- end
-
- def test_set_get
- l = Hyperactive::List::Head.get_instance
- r = Hyperactive::Record::Bass.get_instance
- bm("List::Head#push/pop", :n => 1000) do
- l << r
- l.pop
- end
- bm("List::Head#push", :n => 1000) do
- l << r
- end
- bm("List::Head#push/pop (big)", :n => 1000) do
- l << r
- l.pop
- end
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/tests/list_benchmark.rb (from rev 87, trunk/hyperactive/tests/list_benchmark.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/tests/list_benchmark.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/tests/list_benchmark.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,48 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class ListBenchmark < Test::Unit::TestCase
+
+ def setup
+ @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
+ @c.publish!
+ @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
+ @c2.publish!
+ @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
+ @tm.publish!
+ Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ :tranny_description => {:class => 'TestManager'})
+ assert_within(20) do
+ Set.new(Hyperactive::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
+ end
+ assert_within(20) do
+ Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ end
+ end
+
+ def teardown
+ @c.stop!
+ @c.persistence_provider.unlink!
+ @c2.stop!
+ @c2.persistence_provider.unlink!
+ @tm.stop!
+ @tm.persistence_provider.unlink!
+ end
+
+ def test_set_get
+ l = Hyperactive::List::Head.get_instance
+ r = Hyperactive::Record::Bass.get_instance
+ bm("List::Head#push/pop", :n => 1000) do
+ l << r
+ l.pop
+ end
+ bm("List::Head#push", :n => 1000) do
+ l << r
+ end
+ bm("List::Head#push/pop (big)", :n => 1000) do
+ l << r
+ l.pop
+ end
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/tests/list_test.rb
===================================================================
--- trunk/hyperactive/tests/list_test.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/tests/list_test.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,134 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class Collector
- attr_accessor :es
- def call(e)
- @es ||= []
- @es << e
- end
-end
-
-class ListTest < Test::Unit::TestCase
-
- def setup
- @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
- @c.publish!
- @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
- @c2.publish!
- @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
- @tm.publish!
- Hyperactive::Record::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
- :tranny_description => {:class => 'TestManager'})
- Hyperactive::Record::CAPTAIN.update_services!
- assert_within(10) do
- Hyperactive::Record::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
- end
- assert_within(10) do
- Hyperactive::Record::CAPTAIN.trannies.keys == [@tm.service_id]
- end
- end
-
- def teardown
- @c.stop!
- @c.persistence_provider.unlink!
- @c2.stop!
- @c2.persistence_provider.unlink!
- @tm.stop!
- @tm.persistence_provider.unlink!
- end
-
- def test_clear
- l = Hyperactive::List::Head.get_instance
- l << (r = Hyperactive::Record::Bass.get_instance)
- assert_equal(1, l.size)
- assert_equal(r, l.first)
- assert_equal(r, l.last)
- l.clear!
- assert_equal(0, l.size)
- assert_equal(nil, l.first)
- assert_equal(nil, l.last)
- end
-
- def test_destroy
- l = Hyperactive::List::Head.get_instance
- l << (r = Hyperactive::Record::Bass.get_instance)
- r1 = l.first_element.record_id
- r2 = l.record_id
- l.destroy!
- assert(!Hyperactive::Record::CAPTAIN.include?(r1))
- assert(!Hyperactive::Record::CAPTAIN.include?(r2))
- end
-
- def test_each
- l = Hyperactive::List::Head.get_instance
- l << (r = Hyperactive::Record::Bass.get_instance)
- l << (r2 = Hyperactive::Record::Bass.get_instance)
- l << (r3 = Hyperactive::Record::Bass.get_instance)
- c = Collector.new
- l.t_each(c)
- assert_equal(3, c.es.size)
- assert(c.es.include?(r))
- assert(c.es.include?(r2))
- assert(c.es.include?(r3))
- end
-
- def test_unlink
- l = Hyperactive::List::Head.get_instance
- l << (r = Hyperactive::Record::Bass.get_instance)
- l << (r2 = Hyperactive::Record::Bass.get_instance)
- e = l.last_element
- l << (r3 = Hyperactive::Record::Bass.get_instance)
- assert_equal([r, r2, r3].sort, l.t_collect do |ec| ec end.sort)
- l.unlink!(e)
- assert_equal(2, l.size)
- assert_equal(r, l.first)
- assert_equal(r3, l.last)
- assert_equal(r3, l.first_element.next.value)
- l.unlink!(l.last_element)
- assert_equal(1, l.size)
- assert_equal(r, l.first)
- assert_equal(r, l.last)
- l.unlink!(l.first_element)
- assert_equal(0, l.size)
- assert_equal(nil, l.first)
- assert_equal(nil, l.last)
- assert_equal([], l.t_collect do |e| e end)
- end
-
- def test_push_unshift_pop_shift
- l = Hyperactive::List::Head.get_instance
- assert_equal(0, l.size)
- l << (r = Hyperactive::Record::Bass.get_instance)
- assert_equal(1, l.size)
- assert_equal(l.first, l.last)
- assert_equal(r, l.first)
- l << (r2 = Hyperactive::Record::Bass.get_instance)
- assert_equal(2, l.size)
- assert_equal(r2, l.last)
- assert_equal(r, l.first)
- assert_equal(r2, l.first_element.next.value)
- l.unshift(r3 = Hyperactive::Record::Bass.get_instance)
- assert_equal(3, l.size)
- assert_equal(r3, l.first)
- assert_equal(r2, l.last)
- assert_equal(r, l.first_element.next.value)
- assert_equal(r2, l.first_element.next.next.value)
- assert_equal(r3, l.last_element.previous.previous.value)
- r4 = l.shift
- assert_equal(r3, r4)
- assert_equal(2, l.size)
- assert_equal(r, l.first)
- assert_equal(r2, l.last)
- r5 = l.pop
- assert_equal(1, l.size)
- assert_equal(r, l.first)
- assert_equal(r, l.last)
- assert_equal(r2, r5)
- r6 = l.pop
- assert_equal(0, l.size)
- assert_equal(nil, l.first_element)
- assert_equal(nil, l.last_element)
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/tests/list_test.rb (from rev 87, trunk/hyperactive/tests/list_test.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/tests/list_test.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/tests/list_test.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,134 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class Collector
+ attr_accessor :es
+ def call(e)
+ @es ||= []
+ @es << e
+ end
+end
+
+class ListTest < Test::Unit::TestCase
+
+ def setup
+ @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
+ @c.publish!
+ @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
+ @c2.publish!
+ @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
+ @tm.publish!
+ Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ :tranny_description => {:class => 'TestManager'})
+ Hyperactive::CAPTAIN.update_services!
+ assert_within(10) do
+ Hyperactive::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
+ end
+ assert_within(10) do
+ Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ end
+ end
+
+ def teardown
+ @c.stop!
+ @c.persistence_provider.unlink!
+ @c2.stop!
+ @c2.persistence_provider.unlink!
+ @tm.stop!
+ @tm.persistence_provider.unlink!
+ end
+
+ def test_clear
+ l = Hyperactive::List::Head.get_instance
+ l << (r = Hyperactive::Record::Bass.get_instance)
+ assert_equal(1, l.size)
+ assert_equal(r, l.first)
+ assert_equal(r, l.last)
+ l.clear!
+ assert_equal(0, l.size)
+ assert_equal(nil, l.first)
+ assert_equal(nil, l.last)
+ end
+
+ def test_destroy
+ l = Hyperactive::List::Head.get_instance
+ l << (r = Hyperactive::Record::Bass.get_instance)
+ r1 = l.first_element.record_id
+ r2 = l.record_id
+ l.destroy!
+ assert(!Hyperactive::CAPTAIN.include?(r1))
+ assert(!Hyperactive::CAPTAIN.include?(r2))
+ end
+
+ def test_each
+ l = Hyperactive::List::Head.get_instance
+ l << (r = Hyperactive::Record::Bass.get_instance)
+ l << (r2 = Hyperactive::Record::Bass.get_instance)
+ l << (r3 = Hyperactive::Record::Bass.get_instance)
+ c = Collector.new
+ l.t_each(c)
+ assert_equal(3, c.es.size)
+ assert(c.es.include?(r))
+ assert(c.es.include?(r2))
+ assert(c.es.include?(r3))
+ end
+
+ def test_unlink
+ l = Hyperactive::List::Head.get_instance
+ l << (r = Hyperactive::Record::Bass.get_instance)
+ l << (r2 = Hyperactive::Record::Bass.get_instance)
+ e = l.last_element
+ l << (r3 = Hyperactive::Record::Bass.get_instance)
+ assert_equal([r, r2, r3].sort, l.t_collect do |ec| ec end.sort)
+ l.unlink!(e)
+ assert_equal(2, l.size)
+ assert_equal(r, l.first)
+ assert_equal(r3, l.last)
+ assert_equal(r3, l.first_element.next.value)
+ l.unlink!(l.last_element)
+ assert_equal(1, l.size)
+ assert_equal(r, l.first)
+ assert_equal(r, l.last)
+ l.unlink!(l.first_element)
+ assert_equal(0, l.size)
+ assert_equal(nil, l.first)
+ assert_equal(nil, l.last)
+ assert_equal([], l.t_collect do |e| e end)
+ end
+
+ def test_push_unshift_pop_shift
+ l = Hyperactive::List::Head.get_instance
+ assert_equal(0, l.size)
+ l << (r = Hyperactive::Record::Bass.get_instance)
+ assert_equal(1, l.size)
+ assert_equal(l.first, l.last)
+ assert_equal(r, l.first)
+ l << (r2 = Hyperactive::Record::Bass.get_instance)
+ assert_equal(2, l.size)
+ assert_equal(r2, l.last)
+ assert_equal(r, l.first)
+ assert_equal(r2, l.first_element.next.value)
+ l.unshift(r3 = Hyperactive::Record::Bass.get_instance)
+ assert_equal(3, l.size)
+ assert_equal(r3, l.first)
+ assert_equal(r2, l.last)
+ assert_equal(r, l.first_element.next.value)
+ assert_equal(r2, l.first_element.next.next.value)
+ assert_equal(r3, l.last_element.previous.previous.value)
+ r4 = l.shift
+ assert_equal(r3, r4)
+ assert_equal(2, l.size)
+ assert_equal(r, l.first)
+ assert_equal(r2, l.last)
+ r5 = l.pop
+ assert_equal(1, l.size)
+ assert_equal(r, l.first)
+ assert_equal(r, l.last)
+ assert_equal(r2, r5)
+ r6 = l.pop
+ assert_equal(0, l.size)
+ assert_equal(nil, l.first_element)
+ assert_equal(nil, l.last_element)
+ end
+
+end
Deleted: tags/release_0_2_4/hyperactive/tests/record_test.rb
===================================================================
--- trunk/hyperactive/tests/record_test.rb 2006-11-29 05:45:13 UTC (rev 85)
+++ tags/release_0_2_4/hyperactive/tests/record_test.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -1,152 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class MyRecord < Hyperactive::Record::Bass
- attr_accessor :bajs
- def initialize
- @bajs = nil
- end
- def self.save_hook(instance, &block)
- $BEFORE_SAVE += 1
- yield
- $AFTER_SAVE += 1
- end
- save_hooks << self.method(:save_hook)
-
- def self.create_hook(instance, &block)
- $BEFORE_CREATE += 1
- yield
- $AFTER_CREATE += 1
- end
- create_hooks << self.method(:create_hook)
-
- def self.destroy_hook(instance, &block)
- $BEFORE_DESTROY += 1
- yield
- $AFTER_DESTROY += 1
- end
- destroy_hooks << self.method(:destroy_hook)
-end
-
-class RecordTest < Test::Unit::TestCase
-
- def setup
- @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
- @c.publish!
- @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
- @c2.publish!
- @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
- @tm.publish!
- Hyperactive::Record::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
- :tranny_description => {:class => 'TestManager'})
- Hyperactive::Record::CAPTAIN.update_services!
- assert_within(10) do
- Hyperactive::Record::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
- end
- assert_within(10) do
- Hyperactive::Record::CAPTAIN.trannies.keys == [@tm.service_id]
- end
- $BEFORE_SAVE = 0
- $AFTER_SAVE = 0
- $BEFORE_DESTROY = 0
- $AFTER_DESTROY = 0
- $BEFORE_CREATE = 0
- $AFTER_CREATE = 0
- end
-
- def teardown
- @c.stop!
- @c.persistence_provider.unlink!
- @c2.stop!
- @c2.persistence_provider.unlink!
- @tm.stop!
- @tm.persistence_provider.unlink!
- end
-
- def test_index_find
- MyRecord.class_eval do
- index_by :bajs
- end
- r1 = MyRecord.get_instance
- r1.bajs = "brunt"
- r2 = MyRecord.get_instance
- r2.bajs = "brunt"
- r3 = MyRecord.get_instance
- r3.bajs = "gult"
- r4 = MyRecord.get_instance
- r4.bajs = "beige"
-
- assert_equal(Set.new([r2.record_id,r1.record_id]), Set.new(MyRecord.find_by_bajs("brunt").t_collect(Proc.new do |k,v|
- v.record_id
- end)))
- assert_equal([r3.record_id], MyRecord.find_by_bajs("gult").t_collect(Proc.new do |k,v|
- v.record_id
- end))
-
- r1.destroy!
-
- assert_equal([r2.record_id], MyRecord.find_by_bajs("brunt").t_collect(Proc.new do |k,v|
- v.record_id
- end))
-
- end
-
- def test_select_reject
- MyRecord.class_eval do
- select :brunt do |record|
- record.bajs == "brunt"
- end
- reject :not_brunt do |record|
- record.bajs == "brunt"
- end
- end
- r1 = MyRecord.get_instance
- r1.bajs = "brunt"
- r2 = MyRecord.get_instance
- r2.bajs = "brunt"
- r3 = MyRecord.get_instance
- r3.bajs = "gult"
- r4 = MyRecord.get_instance
- r4.bajs = "beige"
-
- assert_equal(Set.new([r2.record_id,r1.record_id]), Set.new(MyRecord.brunt.t_collect(Proc.new do |k,v|
- v.record_id
- end)))
- assert_equal(Set.new([r3.record_id,r4.record_id]), Set.new(MyRecord.not_brunt.t_collect(Proc.new do |k,v|
- v.record_id
- end)))
-
- r1.destroy!
- r2.destroy!
- r3.destroy!
- r4.destroy!
-
- assert_equal(Set.new, Set.new(MyRecord.brunt.t_collect(Proc.new do |k,v|
- v.record_id
- end)))
- assert_equal(Set.new, Set.new(MyRecord.not_brunt.t_collect(Proc.new do |k,v|
- v.record_id
- end)))
- end
-
- def test_create_update_destroy
- r = MyRecord.get_instance
- assert(Archipelago::Treasure::Dubloon === r)
- assert_equal(1, $BEFORE_SAVE)
- assert_equal(1, $AFTER_SAVE)
- assert_equal(1, $BEFORE_CREATE)
- assert_equal(1, $AFTER_CREATE)
- r.bajs = "brunt"
- assert_equal(2, $BEFORE_SAVE)
- assert_equal(2, $AFTER_SAVE)
- assert_equal("brunt", r.bajs)
- assert_equal("brunt", Hyperactive::Record::CAPTAIN[r.record_id].bajs)
- i = r.record_id
- assert_equal(r, Hyperactive::Record::CAPTAIN[i])
- r.destroy!
- assert_equal(1, $BEFORE_DESTROY)
- assert_equal(1, $AFTER_DESTROY)
- assert_equal(nil, Hyperactive::Record::CAPTAIN[i])
- end
-
-end
Copied: tags/release_0_2_4/hyperactive/tests/record_test.rb (from rev 89, trunk/hyperactive/tests/record_test.rb)
===================================================================
--- tags/release_0_2_4/hyperactive/tests/record_test.rb (rev 0)
+++ tags/release_0_2_4/hyperactive/tests/record_test.rb 2006-12-02 12:49:10 UTC (rev 95)
@@ -0,0 +1,152 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class MyRecord < Hyperactive::Record::Bass
+ attr_accessor :bajs
+ def initialize
+ @bajs = nil
+ end
+ def self.save_hook(instance, old_value, &block)
+ $BEFORE_SAVE += 1
+ yield
+ $AFTER_SAVE += 1
+ end
+ save_hooks << self.method(:save_hook)
+
+ def self.create_hook(instance, &block)
+ $BEFORE_CREATE += 1
+ yield
+ $AFTER_CREATE += 1
+ end
+ create_hooks << self.method(:create_hook)
+
+ def self.destroy_hook(instance, &block)
+ $BEFORE_DESTROY += 1
+ yield
+ $AFTER_DESTROY += 1
+ end
+ destroy_hooks << self.method(:destroy_hook)
+end
+
+class RecordTest < Test::Unit::TestCase
+
+ def setup
+ @c = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest.db")))
+ @c.publish!
+ @c2 = TestChest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("chest2.db")))
+ @c2.publish!
+ @tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
+ @tm.publish!
+ Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ :tranny_description => {:class => 'TestManager'})
+ Hyperactive::CAPTAIN.update_services!
+ assert_within(10) do
+ Hyperactive::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
+ end
+ assert_within(10) do
+ Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ end
+ $BEFORE_SAVE = 0
+ $AFTER_SAVE = 0
+ $BEFORE_DESTROY = 0
+ $AFTER_DESTROY = 0
+ $BEFORE_CREATE = 0
+ $AFTER_CREATE = 0
+ end
+
+ def teardown
+ @c.stop!
+ @c.persistence_provider.unlink!
+ @c2.stop!
+ @c2.persistence_provider.unlink!
+ @tm.stop!
+ @tm.persistence_provider.unlink!
+ end
+
+ def test_index_find
+ MyRecord.class_eval do
+ index_by :bajs
+ end
+ r1 = MyRecord.get_instance
+ r1.bajs = "brunt"
+ r2 = MyRecord.get_instance
+ r2.bajs = "brunt"
+ r3 = MyRecord.get_instance
+ r3.bajs = "gult"
+ r4 = MyRecord.get_instance
+ r4.bajs = "beige"
+
+ assert_equal(Set.new([r2.record_id,r1.record_id]), Set.new(MyRecord.find_by_bajs("brunt").t_collect(Proc.new do |k,v|
+ v.record_id
+ end)))
+ assert_equal([r3.record_id], MyRecord.find_by_bajs("gult").t_collect(Proc.new do |k,v|
+ v.record_id
+ end))
+
+ r1.destroy!
+
+ assert_equal([r2.record_id], MyRecord.find_by_bajs("brunt").t_collect(Proc.new do |k,v|
+ v.record_id
+ end))
+
+ end
+
+ def test_select_reject
+ MyRecord.class_eval do
+ select :brunt do |record|
+ record.bajs == "brunt"
+ end
+ reject :not_brunt do |record|
+ record.bajs == "brunt"
+ end
+ end
+ r1 = MyRecord.get_instance
+ r1.bajs = "brunt"
+ r2 = MyRecord.get_instance
+ r2.bajs = "brunt"
+ r3 = MyRecord.get_instance
+ r3.bajs = "gult"
+ r4 = MyRecord.get_instance
+ r4.bajs = "beige"
+
+ assert_equal(Set.new([r2.record_id,r1.record_id]), Set.new(MyRecord.brunt.t_collect(Proc.new do |k,v|
+ v.record_id
+ end)))
+ assert_equal(Set.new([r3.record_id,r4.record_id]), Set.new(MyRecord.not_brunt.t_collect(Proc.new do |k,v|
+ v.record_id
+ end)))
+
+ r1.destroy!
+ r2.destroy!
+ r3.destroy!
+ r4.destroy!
+
+ assert_equal(Set.new, Set.new(MyRecord.brunt.t_collect(Proc.new do |k,v|
+ v.record_id
+ end)))
+ assert_equal(Set.new, Set.new(MyRecord.not_brunt.t_collect(Proc.new do |k,v|
+ v.record_id
+ end)))
+ end
+
+ def test_create_update_destroy
+ r = MyRecord.get_instance
+ assert(Archipelago::Treasure::Dubloon === r)
+ assert_equal(1, $BEFORE_SAVE)
+ assert_equal(1, $AFTER_SAVE)
+ assert_equal(1, $BEFORE_CREATE)
+ assert_equal(1, $AFTER_CREATE)
+ r.bajs = "brunt"
+ assert_equal(2, $BEFORE_SAVE)
+ assert_equal(2, $AFTER_SAVE)
+ assert_equal("brunt", r.bajs)
+ assert_equal("brunt", Hyperactive::CAPTAIN[r.record_id].bajs)
+ i = r.record_id
+ assert_equal(r, Hyperactive::CAPTAIN[i])
+ r.destroy!
+ assert_equal(1, $BEFORE_DESTROY)
+ assert_equal(1, $AFTER_DESTROY)
+ assert_equal(nil, Hyperactive::CAPTAIN[i])
+ end
+
+end
From nobody at rubyforge.org Sat Dec 2 08:40:41 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 2 Dec 2006 08:40:41 -0500 (EST)
Subject: [Archipelago-submits] [96] trunk: fixed READMEs, added comments
Message-ID: <20061202134041.1F69B5240DD9@rubyforge.org>
Revision: 96
Author: zond
Date: 2006-12-02 08:40:40 -0500 (Sat, 02 Dec 2006)
Log Message:
-----------
fixed READMEs, added comments
Modified Paths:
--------------
trunk/archipelago/README
trunk/hyperactive/README
trunk/hyperactive/lib/hyperactive/index.rb
Modified: trunk/archipelago/README
===================================================================
--- trunk/archipelago/README 2006-12-02 12:49:10 UTC (rev 95)
+++ trunk/archipelago/README 2006-12-02 13:40:40 UTC (rev 96)
@@ -31,7 +31,7 @@
:include:script/services.rb
-To set up an Archipelago::Pirate::Captain do the following (from script/pirate.rb):
+To set up an Archipelago::Pirate::Captain and load some debugging overloads do the following (from script/pirate.rb):
:include:script/pirate.rb
Modified: trunk/hyperactive/README
===================================================================
--- trunk/hyperactive/README 2006-12-02 12:49:10 UTC (rev 95)
+++ trunk/hyperactive/README 2006-12-02 13:40:40 UTC (rev 96)
@@ -9,6 +9,7 @@
Hyperactive::List:: A collection class that contains any number of Hyperactive::Records in a list like structure.
Hyperactive::Index:: A module included into Hyperactive::Record that adds simple indexing capabilities of the find_by_... type.
Hyperactive::Transactions:: A module included into Hyperactive::Record that adds a few simplifications in handling transactions properly.
+Hyperactive::Hooker:: A module that provides around-hook functinality to Hyperactive::Record, so that you can implement save, destroy, create and load hooks that wrap the actual event.
== Usage:
@@ -28,12 +29,12 @@
To define a Record subclass that has the properties @active and @city that are indexed in two ways:
- class MyClass < Hyperactive::Record
+ class MyClass < Hyperactive::Record:Bass
attr_accessor :active, :city
- select(:active_records, Proc.new do |record|
+ select :active_records do |record|
record.active == true
- end)
- index_by(:city)
+ end
+ index_by :city
end
This will allow you to find all active MyClass instances by:
Modified: trunk/hyperactive/lib/hyperactive/index.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/index.rb 2006-12-02 12:49:10 UTC (rev 95)
+++ trunk/hyperactive/lib/hyperactive/index.rb 2006-12-02 13:40:40 UTC (rev 96)
@@ -17,6 +17,10 @@
module Hyperactive
+ #
+ # A package containing methods that will help you create automatically
+ # updated indexes of your Records.
+ #
module Index
#
From nobody at rubyforge.org Sat Dec 2 08:46:25 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 2 Dec 2006 08:46:25 -0500 (EST)
Subject: [Archipelago-submits] [97] trunk/archipelago/TODO: more TODO
Message-ID: <20061202134625.7CE2B5240DDF@rubyforge.org>
Revision: 97
Author: zond
Date: 2006-12-02 08:46:25 -0500 (Sat, 02 Dec 2006)
Log Message:
-----------
more TODO
Modified Paths:
--------------
trunk/archipelago/TODO
Modified: trunk/archipelago/TODO
===================================================================
--- trunk/archipelago/TODO 2006-12-02 13:40:40 UTC (rev 96)
+++ trunk/archipelago/TODO 2006-12-02 13:46:25 UTC (rev 97)
@@ -5,6 +5,11 @@
* Or: Create migration methods that move objects between Chests opon
startup and shutdown, and make them keep backups at each others
persistence backends.
+ * Or: Create something that stores data the way Chord does (with erasure
+ codes) but doesnt use the same look up mechanism.
+ * Problem: We still have to implement the entire maintenance protocol
+ of Chord (continously checking if our data is safely replicated across
+ the network, continously checking that our data belong with us)
* Make Chest aware about whether transactions have affected it 'for real' ie
check whether the instance before the call differs from the instance after
From nobody at rubyforge.org Sun Dec 3 06:29:10 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 3 Dec 2006 06:29:10 -0500 (EST)
Subject: [Archipelago-submits] [98] trunk/archipelago: (re)added DRB-URI
argument to the services script.
Message-ID: <20061203112910.DEAD95240A01@rubyforge.org>
Revision: 98
Author: zond
Date: 2006-12-03 06:29:10 -0500 (Sun, 03 Dec 2006)
Log Message:
-----------
(re)added DRB-URI argument to the services script. removed DEBUG messages from Disco. made Disco require not only a validator but a validator that respond_to?(:valid?). made hashish use dirty? and is_clean! on stored values if available
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/disco.rb
trunk/archipelago/lib/archipelago/hashish.rb
trunk/archipelago/script/services.rb
Modified: trunk/archipelago/lib/archipelago/disco.rb
===================================================================
--- trunk/archipelago/lib/archipelago/disco.rb 2006-12-02 13:46:25 UTC (rev 97)
+++ trunk/archipelago/lib/archipelago/disco.rb 2006-12-03 11:29:10 UTC (rev 98)
@@ -252,7 +252,7 @@
#
def initialize(hash)
raise "Record must have a :service_id" unless hash.include?(:service_id)
- raise "Record must have a :validator" unless hash.include?(:validator)
+ raise "Record must have a :validator" unless hash.include?(:validator) && hash[:validator].respond_to?(:valid?)
super(hash)
end
#
@@ -532,17 +532,9 @@
recipient, data = @outgoing.pop
if recipient
address, port = recipient.split(/:/)
- if $DEBUG
- puts "sending to #{address}:#{port}:"
- puts Marshal.dump(data)
- end
@unisender.send(Marshal.dump(data), 0, address, port.to_i)
else
begin
- if $DEBUG
- puts "broadcasting to #{@multiaddress}:#{@multiport}:"
- puts Marshal.dump(data)
- end
@sender.write(Marshal.dump(data))
rescue Errno::ECONNREFUSED => e
retry
Modified: trunk/archipelago/lib/archipelago/hashish.rb
===================================================================
--- trunk/archipelago/lib/archipelago/hashish.rb 2006-12-02 13:46:25 UTC (rev 97)
+++ trunk/archipelago/lib/archipelago/hashish.rb 2006-12-03 11:29:10 UTC (rev 98)
@@ -115,15 +115,28 @@
#
def store_if_changed(key)
@lock.synchronize_on(key) do
-
- serialized_key = Marshal.dump(key)
value = @content[key]
- serialized_value = Marshal.dump(value)
- old_serialized_value = @content_db[serialized_key]
- write_to_db(key, serialized_key, serialized_value, value) if old_serialized_value && old_serialized_value != serialized_value
-
+ if value.respond_to?(:dirty?)
+
+ if value.dirty?
+ serialized_value = Marshal.dump(value)
+ serialized_key = Marshal.dump(key)
+ write_to_db(key, serialized_key, serialized_value, value)
+ value.is_clean! if value.respond_to?(:is_clean!)
+ end
+
+ else
+
+ serialized_value = Marshal.dump(value)
+ serialized_key = Marshal.dump(key)
+ old_serialized_value = @content_db[serialized_key]
+
+ write_to_db(key, serialized_key, serialized_value, value) if old_serialized_value && old_serialized_value != serialized_value
+
+ end
+
end
end
#
Modified: trunk/archipelago/script/services.rb
===================================================================
--- trunk/archipelago/script/services.rb 2006-12-02 13:46:25 UTC (rev 97)
+++ trunk/archipelago/script/services.rb 2006-12-03 11:29:10 UTC (rev 98)
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
if ARGV.size < 1
- puts "Usage: #{$0} DB-PATH [EXTRA-LIBS]"
+ puts "Usage: #{$0} DB-PATH [DRB-URI [EXTRA-LIBS]]"
exit 1
end
@@ -10,12 +10,15 @@
require 'archipelago/treasure'
require 'archipelago/tranny'
-ARGV[1..-1].each do |lib|
- load lib
+if ARGV.size > 1
+ DRb.start_service(ARGV[1])
+ ARGV[2..-1].each do |lib|
+ load lib
+ end
+else
+ DRb.start_service
end
-DRb.start_service
-
t = Archipelago::Tranny::Manager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(File.join(ARGV[0], "tranny"))))
t.publish!
c = Archipelago::Treasure::Chest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(File.join(ARGV[0], "chest"))))
From nobody at rubyforge.org Sun Dec 3 06:34:37 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 3 Dec 2006 06:34:37 -0500 (EST)
Subject: [Archipelago-submits] [99] trunk/hyperactive/lib: created a Cleaner
module that keeps track of cleanliness.
Message-ID: <20061203113437.6B13052410FA@rubyforge.org>
Revision: 99
Author: zond
Date: 2006-12-03 06:34:37 -0500 (Sun, 03 Dec 2006)
Log Message:
-----------
created a Cleaner module that keeps track of cleanliness. made Hash use it for optimization. made Transactions::Accessors use the old accessors instead of redefine them completely.
Modified Paths:
--------------
trunk/hyperactive/lib/hyperactive/hash.rb
trunk/hyperactive/lib/hyperactive/list.rb
trunk/hyperactive/lib/hyperactive/transactions.rb
trunk/hyperactive/lib/hyperactive.rb
Added Paths:
-----------
trunk/hyperactive/lib/hyperactive/cleaner.rb
Added: trunk/hyperactive/lib/hyperactive/cleaner.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/cleaner.rb (rev 0)
+++ trunk/hyperactive/lib/hyperactive/cleaner.rb 2006-12-03 11:34:37 UTC (rev 99)
@@ -0,0 +1,94 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Hyperactive
+
+ #
+ # A utility package for classes being aware of their dirtyness.
+ #
+ module Cleaner
+
+ #
+ # Include this to get the new accessor methods that automatically check if you are dirty.
+ #
+ module Accessors
+
+ #
+ # The +base+ class including this will get a our ClassMethods as well.
+ #
+ def self.append_features(base)
+ super
+ base.extend(ClassMethods)
+ end
+
+ #
+ # Replies whether we are dirty.
+ #
+ def dirty?
+ @dirty ||= false
+ end
+
+ #
+ # Mark us as dirty.
+ #
+ def is_dirty!
+ @dirty = true
+ end
+
+ #
+ # Mark us as clean.
+ #
+ def is_clean!
+ @dirty = false
+ end
+
+ #
+ # The class methods that help us set/get instance variables in a dirt-aware way.
+ #
+ module ClassMethods
+ self.class.class_eval do
+ alias_method :hyperactive_cleaner_accessors_attr_writer, :attr_writer
+ end
+ #
+ # Works like normal attr_writer but sets us to dirty.
+ #
+ def attr_writer(*attributes)
+ hyperactive_cleaner_accessors_attr_writer(*attributes)
+ attributes.each do |attribute|
+ alias_method "hyperactive_cleaner_accessors_#{attribute}=", "#{attribute}="
+ define_method("#{attribute}=") do |new_value|
+ self.send("hyperactive_cleaner_accessors_#{attribute}=", new_value)
+ self.is_dirty!
+ end
+ end
+ end
+
+ #
+ # Works like normal attr_accessor but with with dirt-aware attr_writer.
+ #
+ def attr_accessor(*attributes)
+ attr_reader(*attributes)
+ attr_writer(*attributes)
+ end
+
+ end
+
+ end
+
+ end
+
+end
Modified: trunk/hyperactive/lib/hyperactive/hash.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-03 11:29:10 UTC (rev 98)
+++ trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-03 11:34:37 UTC (rev 99)
@@ -35,7 +35,11 @@
# A wrapper class that knows what key, value and list_element belong together.
#
class Element < Hyperactive::Record::Bass
+
+ include Hyperactive::Cleaner::Accessors
+
attr_accessor :key, :value, :list_element
+
#
# Initialize a new Hash::Element with given +key+, +value+ and +list_element+.
#
@@ -52,10 +56,11 @@
#
class Head < Hyperactive::Record::Bass
+ include Archipelago::Current::ThreadedCollection
+ include Hyperactive::Cleaner::Accessors
+
attr_accessor :list
- include Archipelago::Current::ThreadedCollection
-
#
# Initialize a Hash::Head.
#
Modified: trunk/hyperactive/lib/hyperactive/list.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/list.rb 2006-12-03 11:29:10 UTC (rev 98)
+++ trunk/hyperactive/lib/hyperactive/list.rb 2006-12-03 11:34:37 UTC (rev 99)
@@ -30,10 +30,11 @@
# A wrapper class that knows its previous and next List::Elements as well as its value and the id of its list.
#
class Element < Hyperactive::Record::Bass
- attr_accessor :previous, :next, :value, :list_id
include Archipelago::Current::ThreadedCollection
+ attr_accessor :previous, :next, :value, :list_id
+
#
# Initialize this List::Element with given +previous_element+, +next_element+, +value+ and +list_id+.
#
@@ -43,7 +44,6 @@
self.value = value
self.list_id = list_id
end
-
#
# Yield to +block+ once for this and each following element.
#
@@ -60,10 +60,11 @@
# A List head.
#
class Head < Hyperactive::Record::Bass
- attr_accessor :first_element, :last_element, :size
include Archipelago::Current::ThreadedCollection
+ attr_accessor :first_element, :last_element, :size
+
#
# Create a List::Head. This is in essence the linked list.
#
Modified: trunk/hyperactive/lib/hyperactive/transactions.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-03 11:29:10 UTC (rev 98)
+++ trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-03 11:34:37 UTC (rev 99)
@@ -101,13 +101,18 @@
# The class methods that help us set/get instance variables in a transactionally aware way.
#
module ClassMethods
+ self.class.class_eval do
+ alias_method :hyperactive_transactions_accessors_attr_reader, :attr_reader
+ end
#
# Works like normal attr_reader but with transactional awareness.
#
def attr_reader(*attributes)
+ hyperactive_transactions_accessors_attr_reader(*attributes)
attributes.each do |attribute|
+ alias_method "hyperactive_transactions_accessors_#{attribute}", attribute
define_method(attribute) do
- value = instance_variable_get("@#{attribute}")
+ value = self.send("hyperactive_transactions_accessors_#{attribute}")
if Archipelago::Treasure::Dubloon === value
if @transaction ||= nil
return value.join(@transaction)
@@ -121,17 +126,22 @@
end
end
+ self.class.class_eval do
+ alias_method :hyperactive_transactions_accessors_attr_writer, :attr_writer
+ end
#
# Works like normal attr_writer but with transactional awareness.
#
def attr_writer(*attributes)
+ hyperactive_transactions_accessors_attr_writer(*attributes)
attributes.each do |attribute|
+ alias_method "hyperactive_transactions_accessors_#{attribute}=", "#{attribute}="
define_method("#{attribute}=") do |new_value|
if Archipelago::Treasure::Dubloon === new_value
new_value.assert_transaction(@transaction) if @transaction ||= nil
- instance_variable_set("@#{attribute}", new_value)
+ self.send("hyperactive_transactions_accessors_#{attribute}=", new_value)
else
- instance_variable_set("@#{attribute}", new_value)
+ self.send("hyperactive_transactions_accessors_#{attribute}=", new_value)
end
end
end
Modified: trunk/hyperactive/lib/hyperactive.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive.rb 2006-12-03 11:29:10 UTC (rev 98)
+++ trunk/hyperactive/lib/hyperactive.rb 2006-12-03 11:34:37 UTC (rev 99)
@@ -20,6 +20,7 @@
require 'hyperactive/hooker'
require 'hyperactive/index'
require 'hyperactive/transactions'
+require 'hyperactive/cleaner'
require 'hyperactive/record'
require 'hyperactive/hash'
require 'hyperactive/list'
From nobody at rubyforge.org Sun Dec 3 10:15:29 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 3 Dec 2006 10:15:29 -0500 (EST)
Subject: [Archipelago-submits] [100] trunk: split Hyperactive::Record::Bass
into more modules.
Message-ID: <20061203151529.631845241255@rubyforge.org>
Revision: 100
Author: zond
Date: 2006-12-03 10:15:28 -0500 (Sun, 03 Dec 2006)
Log Message:
-----------
split Hyperactive::Record::Bass into more modules. made them include each other. is nice!
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/current.rb
trunk/hyperactive/lib/hyperactive/index.rb
trunk/hyperactive/lib/hyperactive/record.rb
trunk/hyperactive/lib/hyperactive/transactions.rb
Modified: trunk/archipelago/lib/archipelago/current.rb
===================================================================
--- trunk/archipelago/lib/archipelago/current.rb 2006-12-03 11:34:37 UTC (rev 99)
+++ trunk/archipelago/lib/archipelago/current.rb 2006-12-03 15:15:28 UTC (rev 100)
@@ -134,9 +134,12 @@
# object.
#
module Synchronized
+
include MonitorMixin
+
alias :lock :mon_enter
alias :unlock :mon_exit
+
#
# We dont care about lock ownership.
#
Modified: trunk/hyperactive/lib/hyperactive/index.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/index.rb 2006-12-03 11:34:37 UTC (rev 99)
+++ trunk/hyperactive/lib/hyperactive/index.rb 2006-12-03 15:15:28 UTC (rev 100)
@@ -134,9 +134,15 @@
end
module Indexable
-
+
def self.append_features(base)
super
+ base.class_eval do
+ #
+ # We depend on lots of hooks.
+ #
+ include(Hyperactive::Hooker::Pimp)
+ end
base.extend(ClassMethods)
end
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-03 11:34:37 UTC (rev 99)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-03 15:15:28 UTC (rev 100)
@@ -29,55 +29,43 @@
# The default database connector.
#
CAPTAIN = Archipelago::Pirate::Captain.new
+
+ #
+ # The host we are running on.
+ #
+ HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
#
# The package containing the base class Bass that simplifies
# using archipelago for generic database stuff.
#
module Record
-
+
#
- # A convenient base class to inherit when you want the basic utility methods
- # provided by for example ActiveRecord::Base *hint hint*.
+ # The methods that make Hyperactive::Record::Bass persistent.
#
- # NB: When an instance is created you will actually have a copy within your local machine
- # which is not what you usually want. Every other time you fetch it using a select or other
- # method you will instead receive a proxy object to the database. This means that nothing you
- # do to it at that point will be persistent or even necessarily have a defined result.
- # Therefore: do not use the instantiated object, instead call my_instance.save
- # to get a proxy to the object stored into the database.
- #
- class Bass
+ module Persistent
- include Hyperactive::Index::Indexable
- include Hyperactive::Transactions::Accessors
- include Hyperactive::Transactions::Participant
- include Hyperactive::Hooker::Pimp
-
#
- # The host we are running on.
+ # Give the class a @record_id getter/setter pair,
+ # our instance methods and the class methods of ClassMethods.
#
- HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
+ def self.append_features(base)
+ super
- #
- # Return the record with +record_id+, optionally within a +transaction+.
- #
- def self.find(record_id, transaction = nil)
- CAPTAIN[record_id, transaction]
- end
+ base.class_eval do
+ #
+ # We basically depend on this module.
+ #
+ include(Hyperactive::Transactions::Participant)
+ #
+ # Our semi-unique id.
+ #
+ attr_reader :record_id
+ end
- #
- # Utility method to get a proxy to a newly saved instance of this class in one call.
- #
- def self.get_instance(*args)
- instance = self.new(*args)
- return instance.create
+ base.extend(ClassMethods)
end
-
- #
- # Our semi-unique id.
- #
- attr_reader :record_id
#
# Utility compare method. Override as you please.
@@ -90,11 +78,6 @@
end
end
- def initialize
- @record_id = nil
- @transaction = nil
- end
-
#
# Save this Record instance into the distributed database and return a proxy to the saved object.
#
@@ -125,7 +108,44 @@
end
end
+ module ClassMethods
+ #
+ # Return the record with +record_id+, optionally within a +transaction+.
+ #
+ def find(record_id, transaction = nil)
+ CAPTAIN[record_id, transaction]
+ end
+
+ #
+ # Utility method to get a proxy to a newly saved instance of this class in one call.
+ #
+ def get_instance(*args)
+ instance = self.new(*args)
+ return instance.create
+ end
+
+ end
+
end
+
+ #
+ # A convenient base class to inherit when you want the basic utility methods
+ # provided by for example ActiveRecord::Base *hint hint*.
+ #
+ # NB: When an instance is created you will actually have a copy within your local machine
+ # which is not what you usually want. Every other time you fetch it using a select or other
+ # method you will instead receive a proxy object to the database. This means that nothing you
+ # do to it at that point will be persistent or even necessarily have a defined result.
+ # Therefore: do not use the instantiated object, instead call my_instance.save
+ # to get a proxy to the object stored into the database.
+ #
+ class Bass
+
+ include Hyperactive::Record::Persistent
+ include Hyperactive::Index::Indexable
+ include Hyperactive::Transactions::Accessors
+
+ end
end
end
Modified: trunk/hyperactive/lib/hyperactive/transactions.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-03 11:34:37 UTC (rev 99)
+++ trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-03 15:15:28 UTC (rev 100)
@@ -25,6 +25,11 @@
#
# Include this to get methods to do with participating in a transaction.
#
+ # To work fully, the class this is included into needs an instance
+ # method create that does the actual saving of the instance into
+ # persistent storage. This method also has to be aware of the @transaction
+ # instance variable for full effect.
+ #
module Participant
#
From nobody at rubyforge.org Sun Dec 3 10:17:32 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 3 Dec 2006 10:17:32 -0500 (EST)
Subject: [Archipelago-submits] [101] trunk/archipelago/TODO: clarified TODO
Message-ID: <20061203151733.6312F5241252@rubyforge.org>
Revision: 101
Author: zond
Date: 2006-12-03 10:17:30 -0500 (Sun, 03 Dec 2006)
Log Message:
-----------
clarified TODO
Modified Paths:
--------------
trunk/archipelago/TODO
Modified: trunk/archipelago/TODO
===================================================================
--- trunk/archipelago/TODO 2006-12-03 15:15:28 UTC (rev 100)
+++ trunk/archipelago/TODO 2006-12-03 15:17:30 UTC (rev 101)
@@ -16,6 +16,8 @@
the call. Preferably without incurring performance lossage.
* For example: Make Dubloon proxy targets able to provide a dirty_state
method that decide whether they are to be considered dirty, clean or auto-select.
+ * This is now done. But it is not yet used to provide intelligence for the
+ transaction mechanism. How should it compare dirty state before and after?
* Test the transaction recovery mechanism of Chest.
From nobody at rubyforge.org Sun Dec 3 16:43:14 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 3 Dec 2006 16:43:14 -0500 (EST)
Subject: [Archipelago-submits] [102] trunk/hyperactive/lib/hyperactive: more
comments
Message-ID: <20061203214314.AB87152416CE@rubyforge.org>
Revision: 102
Author: zond
Date: 2006-12-03 16:43:13 -0500 (Sun, 03 Dec 2006)
Log Message:
-----------
more comments
Modified Paths:
--------------
trunk/hyperactive/lib/hyperactive/record.rb
trunk/hyperactive/lib/hyperactive/transactions.rb
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-03 15:17:30 UTC (rev 101)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-03 21:43:13 UTC (rev 102)
@@ -44,6 +44,8 @@
#
# The methods that make Hyperactive::Record::Bass persistent.
#
+ #
+ #
module Persistent
#
@@ -55,7 +57,7 @@
base.class_eval do
#
- # We basically depend on this module.
+ # We basically depend on this module to get the transactions right.
#
include(Hyperactive::Transactions::Participant)
#
Modified: trunk/hyperactive/lib/hyperactive/transactions.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-03 15:17:30 UTC (rev 101)
+++ trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-03 21:43:13 UTC (rev 102)
@@ -25,9 +25,11 @@
#
# Include this to get methods to do with participating in a transaction.
#
- # To work fully, the class this is included into needs an instance
- # method create that does the actual saving of the instance into
- # persistent storage. This method also has to be aware of the @transaction
+ # To use the get_instance_with_transaction method, the class this is included into needs an instance
+ # method create that does the actual saving of the instance into
+ # persistent storage.
+ #
+ # Also, the class this is included into has to actually use the @transaction
# instance variable for full effect.
#
module Participant
From nobody at rubyforge.org Mon Dec 4 12:19:50 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Mon, 4 Dec 2006 12:19:50 -0500 (EST)
Subject: [Archipelago-submits] [103] trunk/hyperactive/lib/hyperactive:
removed the Transactions::Participant module and incorporated
its features into the Record::Persistent module.
Message-ID: <20061204171950.203095240E83@rubyforge.org>
Revision: 103
Author: zond
Date: 2006-12-04 12:19:49 -0500 (Mon, 04 Dec 2006)
Log Message:
-----------
removed the Transactions::Participant module and incorporated its features into the Record::Persistent module.
Modified Paths:
--------------
trunk/hyperactive/lib/hyperactive/cleaner.rb
trunk/hyperactive/lib/hyperactive/record.rb
trunk/hyperactive/lib/hyperactive/transactions.rb
Modified: trunk/hyperactive/lib/hyperactive/cleaner.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/cleaner.rb 2006-12-03 21:43:13 UTC (rev 102)
+++ trunk/hyperactive/lib/hyperactive/cleaner.rb 2006-12-04 17:19:49 UTC (rev 103)
@@ -60,14 +60,11 @@
# The class methods that help us set/get instance variables in a dirt-aware way.
#
module ClassMethods
- self.class.class_eval do
- alias_method :hyperactive_cleaner_accessors_attr_writer, :attr_writer
- end
#
# Works like normal attr_writer but sets us to dirty.
#
def attr_writer(*attributes)
- hyperactive_cleaner_accessors_attr_writer(*attributes)
+ super
attributes.each do |attribute|
alias_method "hyperactive_cleaner_accessors_#{attribute}=", "#{attribute}="
define_method("#{attribute}=") do |new_value|
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-03 21:43:13 UTC (rev 102)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-04 17:19:49 UTC (rev 103)
@@ -44,12 +44,10 @@
#
# The methods that make Hyperactive::Record::Bass persistent.
#
- #
- #
module Persistent
#
- # Give the class a @record_id getter/setter pair,
+ # Give the class a @record_id getter/setter pair, @transaction getter/setter pair,
# our instance methods and the class methods of ClassMethods.
#
def self.append_features(base)
@@ -57,19 +55,43 @@
base.class_eval do
#
- # We basically depend on this module to get the transactions right.
+ # Our semi-unique id.
#
- include(Hyperactive::Transactions::Participant)
+ attr_reader :record_id
#
- # Our semi-unique id.
+ # The transaction we are currently in.
#
- attr_reader :record_id
+ attr_reader :transaction
end
base.extend(ClassMethods)
end
#
+ # Will execute +block+ within a transaction.
+ #
+ # What it does is just set the @transaction instance variable
+ # before calling the block, and unsetting it after.
+ #
+ # This means that any classes that want to be transaction sensitive
+ # need to take heed regarding the @transaction instance variable.
+ #
+ # For example, when creating new Record instances you may want to use
+ # get_instance_with_transaction(@transaction, *args) to ensure that the
+ # new instance exists within the same transaction as yourself.
+ #
+ # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
+ #
+ def with_transaction(transaction, &block)
+ @transaction = transaction
+ begin
+ yield
+ ensure
+ @transaction = nil
+ end
+ end
+
+ #
# Utility compare method. Override as you please.
#
def <=>(o)
@@ -112,6 +134,18 @@
module ClassMethods
#
+ # Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
+ #
+ def get_instance_with_transaction(transaction, *args)
+ instance = self.new(*args)
+ return_value = nil
+ instance.with_transaction(transaction) do
+ return_value = instance.create
+ end
+ return return_value
+ end
+
+ #
# Return the record with +record_id+, optionally within a +transaction+.
#
def find(record_id, transaction = nil)
Modified: trunk/hyperactive/lib/hyperactive/transactions.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-03 21:43:13 UTC (rev 102)
+++ trunk/hyperactive/lib/hyperactive/transactions.rb 2006-12-04 17:19:49 UTC (rev 103)
@@ -23,75 +23,6 @@
module Transactions
#
- # Include this to get methods to do with participating in a transaction.
- #
- # To use the get_instance_with_transaction method, the class this is included into needs an instance
- # method create that does the actual saving of the instance into
- # persistent storage.
- #
- # Also, the class this is included into has to actually use the @transaction
- # instance variable for full effect.
- #
- module Participant
-
- #
- # The transaction we are currently in.
- #
- attr_reader :transaction
-
- #
- # Will execute +block+ within a transaction.
- #
- # What it does is just set the @transaction instance variable
- # before calling the block, and unsetting it after.
- #
- # This means that any classes that want to be transaction sensitive
- # need to take heed regarding the @transaction instance variable.
- #
- # For example, when creating new Record instances you may want to use
- # get_instance_with_transaction(@transaction, *args) to ensure that the
- # new instance exists within the same transaction as yourself.
- #
- # See Hyperactive::List::Head and Hyperactive::Hash::Head for examples of this behaviour.
- #
- def with_transaction(transaction, &block)
- @transaction = transaction
- begin
- yield
- ensure
- @transaction = nil
- end
- end
-
- #
- # Add our ClassMethods to anyone that includes us.
- #
- def self.append_features(base)
- super
- base.extend(ClassMethods)
- end
-
- #
- # Class methods for transaction participants.
- #
- module ClassMethods
- #
- # Utility method to get a proxy to a within a transaction newly saved instance of this class in one call.
- #
- def get_instance_with_transaction(transaction, *args)
- instance = self.new(*args)
- return_value = nil
- instance.with_transaction(transaction) do
- return_value = instance.create
- end
- return return_value
- end
-
- end
-
- end
-
- #
# Include this to get the default attr_reader at al redefined to be transactionally aware.
#
module Accessors
@@ -108,14 +39,11 @@
# The class methods that help us set/get instance variables in a transactionally aware way.
#
module ClassMethods
- self.class.class_eval do
- alias_method :hyperactive_transactions_accessors_attr_reader, :attr_reader
- end
#
# Works like normal attr_reader but with transactional awareness.
#
def attr_reader(*attributes)
- hyperactive_transactions_accessors_attr_reader(*attributes)
+ super
attributes.each do |attribute|
alias_method "hyperactive_transactions_accessors_#{attribute}", attribute
define_method(attribute) do
@@ -133,14 +61,11 @@
end
end
- self.class.class_eval do
- alias_method :hyperactive_transactions_accessors_attr_writer, :attr_writer
- end
#
# Works like normal attr_writer but with transactional awareness.
#
def attr_writer(*attributes)
- hyperactive_transactions_accessors_attr_writer(*attributes)
+ super
attributes.each do |attribute|
alias_method "hyperactive_transactions_accessors_#{attribute}=", "#{attribute}="
define_method("#{attribute}=") do |new_value|
From nobody at rubyforge.org Sun Dec 10 09:22:29 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 10 Dec 2006 09:22:29 -0500 (EST)
Subject: [Archipelago-submits] [104] trunk/archipelago: added a bitstring
class to do fast xoring of strings.
Message-ID: <20061210142229.CDD9C5240C84@rubyforge.org>
Revision: 104
Author: zond
Date: 2006-12-10 09:22:29 -0500 (Sun, 10 Dec 2006)
Log Message:
-----------
added a bitstring class to do fast xoring of strings. added a raider module that splits and joins stuff in a raid-like manner. added tests and some kind of benchmarks
Modified Paths:
--------------
trunk/archipelago/README
trunk/archipelago/lib/archipelago.rb
Added Paths:
-----------
trunk/archipelago/lib/archipelago/bitstring.rb
trunk/archipelago/lib/archipelago/raider.rb
trunk/archipelago/tests/raider_benchmark.rb
trunk/archipelago/tests/raider_test.rb
trunk/archipelago/tests/string_benchmark.rb
trunk/archipelago/tests/string_test.rb
Modified: trunk/archipelago/README
===================================================================
--- trunk/archipelago/README 2006-12-04 17:19:49 UTC (rev 103)
+++ trunk/archipelago/README 2006-12-10 14:22:29 UTC (rev 104)
@@ -4,6 +4,7 @@
== Dependencies:
Archipelago::Hashish::BerkeleyHashishProvider:: ruby bdb: http://moulon.inra.fr/ruby/bdb.html
+String:: ruby inline: http://www.zenspider.com/ZSS/Products/RubyInline/
== Sub packages:
Archipelago::Disco:: A UDP multicast discovery service useful to find services in your network with a minimum of configuration.
Added: trunk/archipelago/lib/archipelago/bitstring.rb
===================================================================
--- trunk/archipelago/lib/archipelago/bitstring.rb (rev 0)
+++ trunk/archipelago/lib/archipelago/bitstring.rb 2006-12-10 14:22:29 UTC (rev 104)
@@ -0,0 +1,88 @@
+
+require 'rubygems'
+require 'inline'
+
+#
+# Adds a few methods to String, some using the inline gem.
+#
+class String
+
+ inline do |builder|
+ builder.c_raw <len != RSTRING(other)->len)
+ rb_raise(rb_eRuntimeError, "xor argument must be of same size");
+
+ return_value = rb_str_new(0, RSTRING(self)->len);
+
+ for (i = 0; i < RSTRING(return_value)->len; i++)
+ RSTRING(return_value)->ptr[i] = RSTRING(self)->ptr[i] ^ RSTRING(other)->ptr[i];
+
+ return return_value;
+}
+EOC
+
+ #
+ # Returns a String that is self ^ +s+.
+ #
+ def xor(s)
+ self.xor1(s)
+ end
+
+ alias :^ :xor
+
+ builder.c_raw <len != RSTRING(other)->len)
+ rb_raise(rb_eRuntimeError, "xor argument must be of same size");
+
+ for (i = 0; i < RSTRING(self)->len; i++)
+ RSTRING(self)->ptr[i] = RSTRING(self)->ptr[i] ^ RSTRING(other)->ptr[i];
+
+ return self;
+}
+EOC
+ end
+
+ #
+ # Returns whether self begins with +s+.
+ #
+ def begins?(s)
+ self[0...(s.size)] == s
+ end
+
+ #
+ # Modifies self so that it becomes self ^ +s+.
+ #
+ def xor!(s)
+ self.xor2(s)
+ end
+
+end
Added: trunk/archipelago/lib/archipelago/raider.rb
===================================================================
--- trunk/archipelago/lib/archipelago/raider.rb (rev 0)
+++ trunk/archipelago/lib/archipelago/raider.rb 2006-12-10 14:22:29 UTC (rev 104)
@@ -0,0 +1,183 @@
+
+require 'pp'
+
+module Archipelago
+
+ #
+ # A module providing methods to split any String into parts that can be rejoined to provide
+ # the original String again.
+ #
+ module Raider
+
+ #
+ # Raised when the given parts are not enough to recreate the original data.
+ #
+ class NotEnoughBulkError < RuntimeError
+ def initialize(parts)
+ super("#{parts.inspect} is not enough to recreate the original data")
+ end
+ end
+
+ #
+ # A part of the original data.
+ #
+ class Bulk
+ attr_accessor :data, :size, :length
+ def initialize(size, length)
+ @size = size
+ @length = length
+ @data = nil
+ end
+ def <<(data)
+ if @data
+ @data.xor!(data)
+ else
+ @data = data.clone
+ end
+ end
+ def <=>(other)
+ @data <=> other.data
+ end
+ end
+
+ #
+ # Join +parts+ of Bulk together to form the String they were once created from.
+ #
+ def self.join(*parts)
+ #
+ # We know that this is not enough if the parts are empty or if they are fewer than the
+ # minimum size needed to rejoin this data.
+ #
+ raise NotEnoughBulkError.new(parts) if parts.empty? or parts.size < parts.first.size
+
+ #
+ # For each bit of the data, create a String that is the beginning of
+ # all parts having this bit as the first set bit, and another String that is the beginning
+ # of all parts having ONLY this bit set.
+ #
+ # Then go through all parts and find one that has this bit as the first one
+ # and all the others having at least this bit set.
+ #
+ # Then xor the one having this bit as the first one into each other part having at least
+ # this bit set.
+ #
+ covered_bits = 0
+ has_only = []
+ has_only_markers = []
+ 0.upto(parts.first.size - 1) do |n|
+ having_this_bit = []
+ beginning_with_this_bit = nil
+ beginning_marker = ""
+ 0.upto(n - 1) do
+ beginning_marker << "\000"
+ end
+ beginning_marker << "\001"
+ has_only_marker = beginning_marker.clone
+ while has_only_marker.size < parts.first.size
+ has_only_marker << "\000"
+ end
+ has_only_markers[n] = has_only_marker
+
+ parts.each do |part|
+ if part.data.begins?(beginning_marker) && beginning_with_this_bit.nil?
+ beginning_with_this_bit = part
+ elsif part.data[n] == 1
+ having_this_bit << part
+ end
+ end
+ unless beginning_with_this_bit.nil?
+ covered_bits += 1
+ having_this_bit.each do |having|
+ having << beginning_with_this_bit.data
+ end
+ end
+ end
+
+ #
+ # Reject all parts having only 0 bits to get the ones
+ # having one 1 bit each.
+ #
+ parts.reject! do |part|
+ part.data.begins?("\000" * parts.first.size)
+ end
+
+ #
+ # Raise an error if we didnt find all bits needed.
+ #
+ raise NotEnoughBulkError.new(parts) if parts.empty? || parts.size != parts.first.size
+
+ #
+ # Sort the bits having only one bit set in reverse order and collect their actual
+ # data (throw away the bit padding), join them and truncate them at the wanted size.
+ #
+ return parts.sort do |a,b|
+ b <=> a
+ end.collect do |having|
+ having.data[parts.first.size..-1]
+ end.join[0...parts.first.length]
+ end
+
+ #
+ # Split a String of +data+ into +parts+.
+ #
+ # You will get 2 ** +parts+ - 1 parts from the String,
+ # and ( 2 ** +parts+ ) / 2 + 1 will always be enough to
+ # recreate it using join.
+ #
+ def self.split(original_data, parts = 3)
+ data = original_data.clone
+
+ #
+ # Remember the original size of data.
+ #
+ size = data.size
+
+ #
+ # Make sure that the data is divisible by +parts+.
+ #
+ if (rest = (data.size % parts)) != 0
+ data << " " * (parts - rest)
+ end
+
+ #
+ # Split the data into +parts+ bits and append a positional marker at the start of each.
+ #
+ data_parts = []
+ 0.upto(parts - 1) do |n|
+ pos_marker = ""
+ 0.upto(parts - 1) do |m|
+ if m == n
+ pos_marker << "\001"
+ else
+ pos_marker << "\000"
+ end
+ end
+ data_parts << (pos_marker + data[(n * (data.size / parts))...( (n + 1) * (data.size / parts) )])
+ end
+
+ return_parts = []
+
+ #
+ # Create (1 << +parts+) - 1 parts to return
+ #
+ 1.upto((1 << parts) - 1) do |n|
+ this_part = Bulk.new(parts, size)
+ #
+ # For each of our data parts, if our number in the return part order
+ # has the bit ouf our order number in the data part array set,
+ # xor us into this return part.
+ #
+ 0.upto(data_parts.size - 1) do |m|
+ if n & (1 << m) > 0
+ this_part << data_parts[m]
+ end
+ end
+ return_parts << this_part
+ end
+
+ return return_parts
+ end
+
+ end
+
+end
Modified: trunk/archipelago/lib/archipelago.rb
===================================================================
--- trunk/archipelago/lib/archipelago.rb 2006-12-04 17:19:49 UTC (rev 103)
+++ trunk/archipelago/lib/archipelago.rb 2006-12-10 14:22:29 UTC (rev 104)
@@ -22,3 +22,5 @@
require 'archipelago/tranny'
require 'archipelago/treasure'
require 'archipelago/pirate'
+require 'archipelago/bitstring'
+require 'archipelago/raider'
Added: trunk/archipelago/tests/raider_benchmark.rb
===================================================================
--- trunk/archipelago/tests/raider_benchmark.rb (rev 0)
+++ trunk/archipelago/tests/raider_benchmark.rb 2006-12-10 14:22:29 UTC (rev 104)
@@ -0,0 +1,44 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class RaiderBenchmark < Test::Unit::TestCase
+
+ def test_split_join
+ split_and_join(random_string(1000), 1000, 3)
+ split_and_join(random_string(1000), 1000, 4)
+ split_and_join(random_string(1000), 1000, 5)
+ split_and_join(random_string(1000), 1000, 6)
+ split_and_join(random_string(1000), 1000, 7)
+ split_and_join(random_string(1000), 1000, 10)
+ end
+
+ private
+
+ def random_string(n)
+ s = ""
+ rand(n).times do
+ s << (rand(27) + 65).chr
+ end
+ return s
+ end
+
+ def split_and_join(s, n, size)
+ enough = []
+ n.times do
+ p = Archipelago::Raider.split(s, size)
+ assert_equal((1 << size) - 1,p.size)
+ parts_to_use = []
+ begin
+ parts_to_use << p.delete_at(rand(p.size))
+ assert_equal(s, Archipelago::Raider.join(*parts_to_use))
+ enough[parts_to_use.size] ||= 0
+ enough[parts_to_use.size] += 1
+ rescue Archipelago::Raider::NotEnoughBulkError => e
+ retry
+ end
+ end
+ puts "enough bits for #{size} parts"
+ puts enough.inspect
+ end
+
+end
Added: trunk/archipelago/tests/raider_test.rb
===================================================================
--- trunk/archipelago/tests/raider_test.rb (rev 0)
+++ trunk/archipelago/tests/raider_test.rb 2006-12-10 14:22:29 UTC (rev 104)
@@ -0,0 +1,47 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class RaiderTest < Test::Unit::TestCase
+
+ def test_split_join
+ 3.times do
+ split_and_join(random_string(1000), 100, 3)
+ end
+ 3.times do
+ split_and_join(random_string(1000), 100, 4)
+ end
+ 3.times do
+ split_and_join(random_string(1000), 100, 5)
+ end
+ 3.times do
+ split_and_join(random_string(1000), 100, 6)
+ end
+ 3.times do
+ split_and_join(random_string(1000), 100, 7)
+ end
+ end
+
+ private
+
+ def random_string(n)
+ s = ""
+ rand(n).times do
+ s << (rand(27) + 65).chr
+ end
+ return s
+ end
+
+ def split_and_join(s, n, size)
+ n.times do
+ p = Archipelago::Raider.split(s, size)
+ assert_equal((1 << size) - 1,p.size)
+ parts_to_use = []
+ ((1 << (size - 1)) + 1).times do
+ parts_to_use << p.delete_at(rand(p.size))
+ end
+
+ assert_equal(s, Archipelago::Raider.join(*parts_to_use))
+ end
+ end
+
+end
Added: trunk/archipelago/tests/string_benchmark.rb
===================================================================
--- trunk/archipelago/tests/string_benchmark.rb (rev 0)
+++ trunk/archipelago/tests/string_benchmark.rb 2006-12-10 14:22:29 UTC (rev 104)
@@ -0,0 +1,17 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class StringBenchmark < Test::Unit::TestCase
+
+ def test_xor
+ s = " " * (1 << 16)
+ s2 = " " * (1 << 16)
+ bm("String#xor!") do
+ s.xor!(s2)
+ end
+ bm("String#^") do
+ s ^ s2
+ end
+ end
+
+end
Added: trunk/archipelago/tests/string_test.rb
===================================================================
--- trunk/archipelago/tests/string_test.rb (rev 0)
+++ trunk/archipelago/tests/string_test.rb 2006-12-10 14:22:29 UTC (rev 104)
@@ -0,0 +1,23 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class StringTest < Test::Unit::TestCase
+
+ def test_begins
+ assert("hej".begins?("he"))
+ assert("hejsan".begins?("hejsan"))
+ assert(!"epa".begins?("pa"))
+ assert(!"epa".begins?("gnu"))
+ end
+
+ def test_xor
+ assert("hej" ^ "hej" == "\000\000\000")
+ assert("\003\003" ^ "\001\001" == "\002\002")
+ s = "\002"
+ assert(s ^ "\001" == "\003")
+ assert_equal("\002", s)
+ s.xor!("\001")
+ assert_equal("\003", s)
+ end
+
+end
From nobody at rubyforge.org Sun Dec 10 10:03:47 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 10 Dec 2006 10:03:47 -0500 (EST)
Subject: [Archipelago-submits] [105] trunk/archipelago: added more tests and
relevance to raider stuff
Message-ID: <20061210150347.807595240D02@rubyforge.org>
Revision: 105
Author: zond
Date: 2006-12-10 10:03:46 -0500 (Sun, 10 Dec 2006)
Log Message:
-----------
added more tests and relevance to raider stuff
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/raider.rb
trunk/archipelago/tests/raider_benchmark.rb
trunk/archipelago/tests/string_benchmark.rb
Modified: trunk/archipelago/lib/archipelago/raider.rb
===================================================================
--- trunk/archipelago/lib/archipelago/raider.rb 2006-12-10 14:22:29 UTC (rev 104)
+++ trunk/archipelago/lib/archipelago/raider.rb 2006-12-10 15:03:46 UTC (rev 105)
@@ -22,7 +22,27 @@
# A part of the original data.
#
class Bulk
- attr_accessor :data, :size, :length
+ #
+ # The data of this Bulk appended to its position
+ # definition (a String of \000 and \001 defining what
+ # parts of the original String were xored to get this data
+ #
+ attr_accessor :data
+ #
+ # The number of parts the original data were split into
+ # to create the Bulk parts.
+ #
+ attr_accessor :size
+ #
+ # The size of the original data String.
+ #
+ attr_accessor :length
+ #
+ # The number of original data parts that were xored to
+ # get this Bulk (ie the number of \001's in the beginning
+ # of the dat of this Bulk.
+ #
+ attr_accessor :relevance
def initialize(size, length)
@size = size
@length = length
@@ -162,6 +182,7 @@
#
1.upto((1 << parts) - 1) do |n|
this_part = Bulk.new(parts, size)
+ relevance = 0
#
# For each of our data parts, if our number in the return part order
# has the bit ouf our order number in the data part array set,
@@ -170,8 +191,10 @@
0.upto(data_parts.size - 1) do |m|
if n & (1 << m) > 0
this_part << data_parts[m]
+ relevance += 1
end
end
+ this_part.relevance = relevance
return_parts << this_part
end
Modified: trunk/archipelago/tests/raider_benchmark.rb
===================================================================
--- trunk/archipelago/tests/raider_benchmark.rb 2006-12-10 14:22:29 UTC (rev 104)
+++ trunk/archipelago/tests/raider_benchmark.rb 2006-12-10 15:03:46 UTC (rev 105)
@@ -3,17 +3,38 @@
class RaiderBenchmark < Test::Unit::TestCase
- def test_split_join
+ def test_enough
split_and_join(random_string(1000), 1000, 3)
split_and_join(random_string(1000), 1000, 4)
split_and_join(random_string(1000), 1000, 5)
split_and_join(random_string(1000), 1000, 6)
split_and_join(random_string(1000), 1000, 7)
- split_and_join(random_string(1000), 1000, 10)
end
+ def test_speed
+ s = string(1024)
+ bm("Raider.split([#{s.size} String], 3)/Raider.join") do
+ p = Archipelago::Raider.split(s, 3)
+ parts_to_use = []
+ begin
+ parts_to_use << p.delete_at(rand(p.size))
+ assert_equal(s, Archipelago::Raider.join(*parts_to_use))
+ rescue Archipelago::Raider::NotEnoughBulkError => e
+ retry
+ end
+ end
+ end
+
private
+ def string(n)
+ s = ""
+ n.times do
+ s << (rand(27) + 65).chr
+ end
+ return s
+ end
+
def random_string(n)
s = ""
rand(n).times do
Modified: trunk/archipelago/tests/string_benchmark.rb
===================================================================
--- trunk/archipelago/tests/string_benchmark.rb 2006-12-10 14:22:29 UTC (rev 104)
+++ trunk/archipelago/tests/string_benchmark.rb 2006-12-10 15:03:46 UTC (rev 105)
@@ -4,12 +4,12 @@
class StringBenchmark < Test::Unit::TestCase
def test_xor
- s = " " * (1 << 16)
- s2 = " " * (1 << 16)
- bm("String#xor!") do
+ s = " " * (1 << 20)
+ s2 = " " * (1 << 20)
+ bm("String#xor! (size #{s.size})") do
s.xor!(s2)
end
- bm("String#^") do
+ bm("String#^ (size #{s.size})") do
s ^ s2
end
end
From nobody at rubyforge.org Sun Dec 10 18:14:17 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 10 Dec 2006 18:14:17 -0500 (EST)
Subject: [Archipelago-submits] [106] trunk/archipelago: made raider
benchmarks go faster.
Message-ID: <20061210231417.0B2575241415@rubyforge.org>
Revision: 106
Author: zond
Date: 2006-12-10 18:14:16 -0500 (Sun, 10 Dec 2006)
Log Message:
-----------
made raider benchmarks go faster. added a client class that pirate captain inherits. added license to the bitstring and raider classes.
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/bitstring.rb
trunk/archipelago/lib/archipelago/pirate.rb
trunk/archipelago/lib/archipelago/raider.rb
trunk/archipelago/lib/archipelago.rb
trunk/archipelago/tests/raider_benchmark.rb
Added Paths:
-----------
trunk/archipelago/lib/archipelago/client.rb
Modified: trunk/archipelago/lib/archipelago/bitstring.rb
===================================================================
--- trunk/archipelago/lib/archipelago/bitstring.rb 2006-12-10 15:03:46 UTC (rev 105)
+++ trunk/archipelago/lib/archipelago/bitstring.rb 2006-12-10 23:14:16 UTC (rev 106)
@@ -1,3 +1,19 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'rubygems'
require 'inline'
@@ -75,7 +91,7 @@
# Returns whether self begins with +s+.
#
def begins?(s)
- self[0...(s.size)] == s
+ self.index(s) == 0
end
#
Added: trunk/archipelago/lib/archipelago/client.rb
===================================================================
--- trunk/archipelago/lib/archipelago/client.rb (rev 0)
+++ trunk/archipelago/lib/archipelago/client.rb 2006-12-10 23:14:16 UTC (rev 106)
@@ -0,0 +1,90 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Archipelago
+
+ module Client
+
+ class Base
+ #
+ # Initialize an instance using an Archipelago::Disco::Jockey with :jockey_options
+ # if given, that looks for new services :initial_service_update_interval or INITIAL_SERVICE_UPDATE_INTERVAL,
+ # when it starts and never slower than every :maximum_service_update_interval or MAXIMUM_SERVICE_UPDATE_INTERVAL.
+ #
+ def initialize(options = {})
+ setup(options)
+ end
+ #
+ # Sets up this instance with the given +options+.
+ #
+ def setup(options = {})
+ @jockey ||= nil
+ if defined?(Archipelago::Disco::MC)
+ @jockey.stop! if @jockey && @jockey != Archipelago::Disco::MC
+ @jockey = options.include?(:jockey_options) ? Archipelago::Disco::Jockey.new(options[:jockey_options]) : Archipelago::Disco::MC
+ else
+ @jockey.stop! if @jockey
+ @jockey = Archipelago::Disco::Jockey.new(options[:jockey_options] || {})
+ end
+ end
+
+ #
+ # Stops the service update thread for this Pirate and also unpublishes and/or
+ # stops the Jockey.
+ #
+ def stop!
+ @service_update_thread.kill if @service_update_thread
+ unless defined?(Archipelago::Disco::MC) && @jockey && @jockey == Archipelago::Disco::MC
+ @jockey.stop!
+ end
+ end
+
+ #
+ # Override this to do whatever you want to when finding services.
+ #
+ def update_services!
+ # /moo
+ end
+
+ private
+
+ #
+ # Start a thread looking up existing chests between every
+ # +initial+ and +maximum+ seconds.
+ #
+ def start_service_updater(initial, maximum)
+ update_services!
+ @service_update_thread = Thread.start do
+ standoff = initial
+ loop do
+ begin
+ sleep(standoff)
+ standoff *= 2
+ standoff = maximum if standoff > maximum
+ update_services!
+ rescue Exception => e
+ puts e
+ pp e.backtrace
+ end
+ end
+ end
+ end
+ end
+
+ end
+
+end
Modified: trunk/archipelago/lib/archipelago/pirate.rb
===================================================================
--- trunk/archipelago/lib/archipelago/pirate.rb 2006-12-10 15:03:46 UTC (rev 105)
+++ trunk/archipelago/lib/archipelago/pirate.rb 2006-12-10 23:14:16 UTC (rev 106)
@@ -73,13 +73,9 @@
# The class that actually keeps track of the Archipelago::Treasure:Chests and the
# Archipelago::Treasure:Dubloons in them.
#
- class Captain
- attr_reader :chests, :treasure_map, :trannies
+ class Captain < Archipelago::Client::Base
+ attr_reader :chests, :trannies
#
- # Initialize an instance using an Archipelago::Disco::Jockey with :jockey_options
- # if given, that looks for new services :initial_service_update_interval or INITIAL_SERVICE_UPDATE_INTERVAL,
- # when it starts and never slower than every :maximum_service_update_interval or MAXIMUM_SERVICE_UPDATE_INTERVAL.
- #
# Will look for Archipelago::Treasure::Chests matching :chest_description or CHEST_DESCRIPTION and
# Archipelago::Tranny::Managers matching :tranny_description or TRANNY_DESCRIPTION.
#
@@ -87,7 +83,7 @@
# of required classes and modules at the chest.
#
def initialize(options = {})
- setup(options)
+ super(options)
@transaction = nil
@@ -100,14 +96,7 @@
# Sets up this instance with the given +options+.
#
def setup(options = {})
- @treasure_map ||= nil
- if defined?(Archipelago::Disco::MC)
- @treasure_map.stop! if @treasure_map && @treasure_map != Archipelago::Disco::MC
- @treasure_map = options.include?(:jockey_options) ? Archipelago::Disco::Jockey.new(options[:jockey_options]) : Archipelago::Disco::MC
- else
- @treasure_map.stop! if @treasure_map
- @treasure_map = Archipelago::Disco::Jockey.new(options[:jockey_options] || {})
- end
+ super(options)
@chest_description = CHEST_DESCRIPTION.merge(options[:chest_description] || {})
@tranny_description = TRANNY_DESCRIPTION.merge(options[:tranny_description] || {})
@@ -236,17 +225,6 @@
end
#
- # Stops the service update thread for this Pirate and also unpublishes and/or
- # stops the Jockey.
- #
- def stop!
- @service_update_thread.kill
- unless defined?(Archipelago::Disco::MC) && @treasure_map && @treasure_map == Archipelago::Disco::MC
- @treasure_map.stop!
- end
- end
-
- #
# Will do +callable+.call(key, value)
# for each key-and-value pair in this database network.
#
@@ -263,9 +241,9 @@
# Does an immediate update of our service lists.
#
def update_services!
- @chests = @treasure_map.lookup(Archipelago::Disco::Query.new(@chest_description), 0)
+ @chests = @jockey.lookup(Archipelago::Disco::Query.new(@chest_description), 0)
evaluate_in_chests
- @trannies = @treasure_map.lookup(Archipelago::Disco::Query.new(@tranny_description), 0)
+ @trannies = @jockey.lookup(Archipelago::Disco::Query.new(@tranny_description), 0)
end
private
@@ -329,28 +307,6 @@
end
end
- #
- # Start a thread looking up existing chests between every
- # +initial+ and +maximum+ seconds.
- #
- def start_service_updater(initial, maximum)
- update_services!
- @service_update_thread = Thread.start do
- standoff = initial
- loop do
- begin
- sleep(standoff)
- standoff *= 2
- standoff = maximum if standoff > maximum
- update_services!
- rescue Exception => e
- puts e
- pp e.backtrace
- end
- end
- end
- end
-
end
end
Modified: trunk/archipelago/lib/archipelago/raider.rb
===================================================================
--- trunk/archipelago/lib/archipelago/raider.rb 2006-12-10 15:03:46 UTC (rev 105)
+++ trunk/archipelago/lib/archipelago/raider.rb 2006-12-10 23:14:16 UTC (rev 106)
@@ -1,3 +1,19 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require 'pp'
@@ -82,8 +98,6 @@
# this bit set.
#
covered_bits = 0
- has_only = []
- has_only_markers = []
0.upto(parts.first.size - 1) do |n|
having_this_bit = []
beginning_with_this_bit = nil
@@ -92,11 +106,6 @@
beginning_marker << "\000"
end
beginning_marker << "\001"
- has_only_marker = beginning_marker.clone
- while has_only_marker.size < parts.first.size
- has_only_marker << "\000"
- end
- has_only_markers[n] = has_only_marker
parts.each do |part|
if part.data.begins?(beginning_marker) && beginning_with_this_bit.nil?
@@ -138,7 +147,7 @@
end
#
- # Split a String of +data+ into +parts+.
+ # Split a String of +data+ into +parts+ pieces.
#
# You will get 2 ** +parts+ - 1 parts from the String,
# and ( 2 ** +parts+ ) / 2 + 1 will always be enough to
Modified: trunk/archipelago/lib/archipelago.rb
===================================================================
--- trunk/archipelago/lib/archipelago.rb 2006-12-10 15:03:46 UTC (rev 105)
+++ trunk/archipelago/lib/archipelago.rb 2006-12-10 23:14:16 UTC (rev 106)
@@ -21,6 +21,7 @@
require 'archipelago/current'
require 'archipelago/tranny'
require 'archipelago/treasure'
+require 'archipelago/client'
require 'archipelago/pirate'
require 'archipelago/bitstring'
require 'archipelago/raider'
Modified: trunk/archipelago/tests/raider_benchmark.rb
===================================================================
--- trunk/archipelago/tests/raider_benchmark.rb 2006-12-10 15:03:46 UTC (rev 105)
+++ trunk/archipelago/tests/raider_benchmark.rb 2006-12-10 23:14:16 UTC (rev 106)
@@ -16,6 +16,8 @@
bm("Raider.split([#{s.size} String], 3)/Raider.join") do
p = Archipelago::Raider.split(s, 3)
parts_to_use = []
+ parts_to_use << p.delete_at(rand(p.size))
+ parts_to_use << p.delete_at(rand(p.size))
begin
parts_to_use << p.delete_at(rand(p.size))
assert_equal(s, Archipelago::Raider.join(*parts_to_use))
@@ -49,6 +51,9 @@
p = Archipelago::Raider.split(s, size)
assert_equal((1 << size) - 1,p.size)
parts_to_use = []
+ 0.upto(size - 2) do
+ parts_to_use << p.delete_at(rand(p.size))
+ end
begin
parts_to_use << p.delete_at(rand(p.size))
assert_equal(s, Archipelago::Raider.join(*parts_to_use))
From nobody at rubyforge.org Sun Dec 10 18:39:04 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 10 Dec 2006 18:39:04 -0500 (EST)
Subject: [Archipelago-submits] [107] trunk/archipelago: swapped around code
between pirate and client.
Message-ID: <20061210233904.2DF4E524142C@rubyforge.org>
Revision: 107
Author: zond
Date: 2006-12-10 18:39:03 -0500 (Sun, 10 Dec 2006)
Log Message:
-----------
swapped around code between pirate and client. added a default pirate BLACKBEARD. made client depend on disco. made pirate depend on client.
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/client.rb
trunk/archipelago/lib/archipelago/pirate.rb
trunk/archipelago/tests/test_helper.rb
Modified: trunk/archipelago/lib/archipelago/client.rb
===================================================================
--- trunk/archipelago/lib/archipelago/client.rb 2006-12-10 23:14:16 UTC (rev 106)
+++ trunk/archipelago/lib/archipelago/client.rb 2006-12-10 23:39:03 UTC (rev 107)
@@ -15,11 +15,17 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+require 'archipelago/disco'
+
module Archipelago
module Client
+ INITIAL_SERVICE_UPDATE_INTERVAL = 1
+ MAXIMUM_SERVICE_UPDATE_INTERVAL = 60
+
class Base
+ attr_reader :jockey
#
# Initialize an instance using an Archipelago::Disco::Jockey with :jockey_options
# if given, that looks for new services :initial_service_update_interval or INITIAL_SERVICE_UPDATE_INTERVAL,
@@ -40,6 +46,10 @@
@jockey.stop! if @jockey
@jockey = Archipelago::Disco::Jockey.new(options[:jockey_options] || {})
end
+
+ @initial_service_update_interval = options[:initial_service_update_interval] || INITIAL_SERVICE_UPDATE_INTERVAL
+ @maximum_service_update_interval = options[:maximum_service_update_interval] || MAXIMUM_SERVICE_UPDATE_INTERVAL
+
end
#
@@ -66,15 +76,15 @@
# Start a thread looking up existing chests between every
# +initial+ and +maximum+ seconds.
#
- def start_service_updater(initial, maximum)
+ def start_service_updater
update_services!
@service_update_thread = Thread.start do
- standoff = initial
+ standoff = @initial_service_update_interval
loop do
begin
sleep(standoff)
standoff *= 2
- standoff = maximum if standoff > maximum
+ standoff = @maximum_service_update_interval if standoff > @maximum_service_update_interval
update_services!
rescue Exception => e
puts e
Modified: trunk/archipelago/lib/archipelago/pirate.rb
===================================================================
--- trunk/archipelago/lib/archipelago/pirate.rb 2006-12-10 23:14:16 UTC (rev 106)
+++ trunk/archipelago/lib/archipelago/pirate.rb 2006-12-10 23:39:03 UTC (rev 107)
@@ -18,6 +18,7 @@
require 'archipelago/disco'
require 'archipelago/tranny'
require 'archipelago/treasure'
+require 'archipelago/client'
require 'pp'
require 'drb'
require 'digest/sha1'
@@ -60,8 +61,6 @@
end
end
- INITIAL_SERVICE_UPDATE_INTERVAL = 1
- MAXIMUM_SERVICE_UPDATE_INTERVAL = 60
CHEST_DESCRIPTION = {
:class => 'Archipelago::Treasure::Chest'
}
@@ -87,8 +86,7 @@
@transaction = nil
- start_service_updater(options[:initial_service_update_interval] || INITIAL_SERVICE_UPDATE_INTERVAL,
- options[:maximum_service_update_interval] || MAXIMUM_SERVICE_UPDATE_INTERVAL)
+ start_service_updater
end
@@ -309,6 +307,14 @@
end
+ #
+ # The default Archipelago::Pirate::Captain that is always available for lookups is Archipelago::Pirate::BLACKBEARD.
+ #
+ # If you really need to you can customize it by defining BLACKBEARD_OPTIONS before loading disco.rb, and if you REALLY
+ # need to you can disable it completely by setting BLACKBEARD_DISABLED to true.
+ #
+ BLACKBEARD = Captain.new(defined?(BLACKBEARD_OPTIONS) ? BLACKBEARD_OPTIONS : {}) unless defined?(BLACKBEARD_DISABLED) && BLACKBEARD_DISABLED
+
end
end
Modified: trunk/archipelago/tests/test_helper.rb
===================================================================
--- trunk/archipelago/tests/test_helper.rb 2006-12-10 23:14:16 UTC (rev 106)
+++ trunk/archipelago/tests/test_helper.rb 2006-12-10 23:39:03 UTC (rev 107)
@@ -3,6 +3,7 @@
$: << File.join(home, "..", "lib")
MC_DISABLED = true unless defined?(MC_ENABLED) && MC_ENABLED
+BLACKBEARD_DISABLED = true unless defined?(BLACKBEARD_ENABLED) && BLACKBEARD_ENABLED
require 'pp'
require 'drb'
From nobody at rubyforge.org Sun Dec 10 18:40:05 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 10 Dec 2006 18:40:05 -0500 (EST)
Subject: [Archipelago-submits] [108] trunk/hyperactive: removed the default
pirate CAPTAIN.
Message-ID: <20061210234005.E5E41524142B@rubyforge.org>
Revision: 108
Author: zond
Date: 2006-12-10 18:40:05 -0500 (Sun, 10 Dec 2006)
Log Message:
-----------
removed the default pirate CAPTAIN. used the default pirate BLACKBEARD instead.
Modified Paths:
--------------
trunk/hyperactive/README
trunk/hyperactive/lib/hyperactive/hash.rb
trunk/hyperactive/lib/hyperactive/index.rb
trunk/hyperactive/lib/hyperactive/record.rb
trunk/hyperactive/tests/hash_benchmark.rb
trunk/hyperactive/tests/hash_test.rb
trunk/hyperactive/tests/list_benchmark.rb
trunk/hyperactive/tests/list_test.rb
trunk/hyperactive/tests/record_test.rb
Modified: trunk/hyperactive/README
===================================================================
--- trunk/hyperactive/README 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/README 2006-12-10 23:40:05 UTC (rev 108)
@@ -22,9 +22,6 @@
or give you a proxy. Both of these things are good for you, so use get_instance unless you know
what you are doing.
-By loading Hyperactive::Record you will automatically define Hyperactive::CAPTAIN which will
-be an Archipelago::Pirate::Captain that is your interface to the distributed database.
-
== Examples:
To define a Record subclass that has the properties @active and @city that are indexed in two ways:
Modified: trunk/hyperactive/lib/hyperactive/hash.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -89,7 +89,7 @@
# Return the value for +key+.
#
def [](key)
- element = Hyperactive::CAPTAIN[my_key_for(key), @transaction]
+ element = Archipelago::Pirate::BLACKBEARD[my_key_for(key), @transaction]
if element
return element.value
else
@@ -101,7 +101,7 @@
# Returns whether +key+ is included in this Hash.
#
def include?(key)
- Hyperactive::CAPTAIN.include?(my_key_for(key), @transaction)
+ Archipelago::Pirate::BLACKBEARD.include?(my_key_for(key), @transaction)
end
#
@@ -110,13 +110,13 @@
def []=(key, value)
self.list = Hyperactive::List::Head.get_instance_with_transaction(@transaction) unless self.list
- if (element = Hyperactive::CAPTAIN[my_key_for(key), @transaction])
+ if (element = Archipelago::Pirate::BLACKBEARD[my_key_for(key), @transaction])
element.value = value
else
element = Element.get_instance_with_transaction(@transaction, key, value, nil)
self.list << element
element.list_element = self.list.last_element
- Hyperactive::CAPTAIN[my_key_for(key), @transaction] = element
+ Archipelago::Pirate::BLACKBEARD[my_key_for(key), @transaction] = element
end
end
@@ -128,9 +128,9 @@
return_value = nil
- element = Hyperactive::CAPTAIN[my_key_for(key), @transaction]
+ element = Archipelago::Pirate::BLACKBEARD[my_key_for(key), @transaction]
if element
- Hyperactive::CAPTAIN.delete(my_key_for(key), @transaction)
+ Archipelago::Pirate::BLACKBEARD.delete(my_key_for(key), @transaction)
self.list.unlink!(element.list_element)
return_value = element.value
element.destroy!
Modified: trunk/hyperactive/lib/hyperactive/index.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/index.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/lib/hyperactive/index.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -74,12 +74,12 @@
old_key = get_key_for(old_record)
new_key = get_key_for(record)
if old_key != new_key
- (CAPTAIN[old_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
- (CAPTAIN[new_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction))[record.record_id] = record
+ (Archipelago::Pirate::BLACKBEARD[old_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
+ (Archipelago::Pirate::BLACKBEARD[new_key] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction))[record.record_id] = record
end
else
record = arguments.first
- (CAPTAIN[get_key_for(record)] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
+ (Archipelago::Pirate::BLACKBEARD[get_key_for(record)] ||= Hyperactive::Hash::Head.get_instance_with_transaction(record.transaction)).delete(record.record_id)
end
end
end
@@ -111,23 +111,23 @@
case @mode
when :select
if @matcher.call(record)
- CAPTAIN[@key, record.transaction][record.record_id] = record
+ Archipelago::Pirate::BLACKBEARD[@key, record.transaction][record.record_id] = record
else
- CAPTAIN[@key, record.transaction].delete(record.record_id)
+ Archipelago::Pirate::BLACKBEARD[@key, record.transaction].delete(record.record_id)
end
when :reject
if @matcher.call(record)
- CAPTAIN[@key, record.transaction].delete(record.record_id)
+ Archipelago::Pirate::BLACKBEARD[@key, record.transaction].delete(record.record_id)
else
- CAPTAIN[@key, record.transaction][record.record_id] = record
+ Archipelago::Pirate::BLACKBEARD[@key, record.transaction][record.record_id] = record
end
when :delete_if_match
if @matcher.call(record)
- CAPTAIN[@key, record.transaction].delete(record.record_id)
+ Archipelago::Pirate::BLACKBEARD[@key, record.transaction].delete(record.record_id)
end
when :delete_unless_match
unless @matcher.call(record)
- CAPTAIN[@key, record.transaction].delete(record.record_id)
+ Archipelago::Pirate::BLACKBEARD[@key, record.transaction].delete(record.record_id)
end
end
end
@@ -157,7 +157,7 @@
klass = self
self.class.class_eval do
define_method("find_by_#{attributes.join("_and_")}") do |*args|
- CAPTAIN[IndexBuilder.get_key(klass, attributes, args)]
+ Archipelago::Pirate::BLACKBEARD[IndexBuilder.get_key(klass, attributes, args)]
end
end
index_builder = IndexBuilder.new(self, attributes)
@@ -173,10 +173,10 @@
#
def select(name, &block) #:yields: instance
key = collection_key(name)
- CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
+ Archipelago::Pirate::BLACKBEARD[key] ||= Hyperactive::Hash::Head.get_instance
self.class.class_eval do
define_method(name) do
- CAPTAIN[key]
+ Archipelago::Pirate::BLACKBEARD[key]
end
end
self.save_hooks << MatchSaver.new(key, block, :select)
@@ -191,10 +191,10 @@
#
def reject(name, &block) #:yields: instance
key = collection_key(name)
- CAPTAIN[key] ||= Hyperactive::Hash::Head.get_instance
+ Archipelago::Pirate::BLACKBEARD[key] ||= Hyperactive::Hash::Head.get_instance
self.class.class_eval do
define_method(name) do
- CAPTAIN[key]
+ Archipelago::Pirate::BLACKBEARD[key]
end
end
self.save_hooks << MatchSaver.new(key, block, :reject)
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -26,11 +26,6 @@
module Hyperactive
#
- # The default database connector.
- #
- CAPTAIN = Archipelago::Pirate::Captain.new
-
- #
# The host we are running on.
#
HOST = "#{Socket::gethostbyname(Socket::gethostname)[0]}" rescue "localhost"
@@ -112,10 +107,10 @@
@transaction ||= nil
self.class.with_hooks(:instance => self, :hooks => self.class.create_hooks) do
- CAPTAIN[self.record_id, @transaction] = self
+ Archipelago::Pirate::BLACKBEARD[self.record_id, @transaction] = self
end
- proxy = CAPTAIN[@record_id, @transaction]
+ proxy = Archipelago::Pirate::BLACKBEARD[@record_id, @transaction]
return proxy
end
@@ -127,7 +122,7 @@
#
def destroy!
self.class.with_hooks(:instance => self, :hooks => self.class.destroy_hooks) do
- CAPTAIN.delete(@record_id, @transaction)
+ Archipelago::Pirate::BLACKBEARD.delete(@record_id, @transaction)
self.freeze
end
end
@@ -149,7 +144,7 @@
# Return the record with +record_id+, optionally within a +transaction+.
#
def find(record_id, transaction = nil)
- CAPTAIN[record_id, transaction]
+ Archipelago::Pirate::BLACKBEARD[record_id, transaction]
end
#
Modified: trunk/hyperactive/tests/hash_benchmark.rb
===================================================================
--- trunk/hyperactive/tests/hash_benchmark.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/tests/hash_benchmark.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -10,13 +10,13 @@
@c2.publish!
@tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
@tm.publish!
- Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ Archipelago::Pirate::BLACKBEARD.setup(:chest_description => {:class => 'TestChest'},
:tranny_description => {:class => 'TestManager'})
assert_within(20) do
- Set.new(Hyperactive::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
+ Set.new(Archipelago::Pirate::BLACKBEARD.chests.keys) == Set.new([@c.service_id, @c2.service_id])
end
assert_within(20) do
- Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ Archipelago::Pirate::BLACKBEARD.trannies.keys == [@tm.service_id]
end
end
@@ -36,8 +36,8 @@
end
def test_regular_hash_set_get
- Hyperactive::CAPTAIN["h"] = {}
- h = Hyperactive::CAPTAIN["h"]
+ Archipelago::Pirate::BLACKBEARD["h"] = {}
+ h = Archipelago::Pirate::BLACKBEARD["h"]
r = Hyperactive::Record::Bass.get_instance
hash_test("Hash", h, r, 100)
end
Modified: trunk/hyperactive/tests/hash_test.rb
===================================================================
--- trunk/hyperactive/tests/hash_test.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/tests/hash_test.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -19,14 +19,14 @@
@c2.publish!
@tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
@tm.publish!
- Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ Archipelago::Pirate::BLACKBEARD.setup(:chest_description => {:class => 'TestChest'},
:tranny_description => {:class => 'TestManager'})
- Hyperactive::CAPTAIN.update_services!
+ Archipelago::Pirate::BLACKBEARD.update_services!
assert_within(10) do
- Hyperactive::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
+ Archipelago::Pirate::BLACKBEARD.chests.keys.sort == [@c.service_id, @c2.service_id].sort
end
assert_within(10) do
- Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ Archipelago::Pirate::BLACKBEARD.trannies.keys == [@tm.service_id]
end
end
@@ -69,7 +69,7 @@
h2.each do |k,v|
assert_equal(v, h[k])
- assert_equal(v, Hyperactive::CAPTAIN[h.record_id][k])
+ assert_equal(v, Archipelago::Pirate::BLACKBEARD[h.record_id][k])
end
end
Modified: trunk/hyperactive/tests/list_benchmark.rb
===================================================================
--- trunk/hyperactive/tests/list_benchmark.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/tests/list_benchmark.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -10,13 +10,13 @@
@c2.publish!
@tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
@tm.publish!
- Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ Archipelago::Pirate::BLACKBEARD.setup(:chest_description => {:class => 'TestChest'},
:tranny_description => {:class => 'TestManager'})
assert_within(20) do
- Set.new(Hyperactive::CAPTAIN.chests.keys) == Set.new([@c.service_id, @c2.service_id])
+ Set.new(Archipelago::Pirate::BLACKBEARD.chests.keys) == Set.new([@c.service_id, @c2.service_id])
end
assert_within(20) do
- Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ Archipelago::Pirate::BLACKBEARD.trannies.keys == [@tm.service_id]
end
end
Modified: trunk/hyperactive/tests/list_test.rb
===================================================================
--- trunk/hyperactive/tests/list_test.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/tests/list_test.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -18,14 +18,14 @@
@c2.publish!
@tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
@tm.publish!
- Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ Archipelago::Pirate::BLACKBEARD.setup(:chest_description => {:class => 'TestChest'},
:tranny_description => {:class => 'TestManager'})
- Hyperactive::CAPTAIN.update_services!
+ Archipelago::Pirate::BLACKBEARD.update_services!
assert_within(10) do
- Hyperactive::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
+ Archipelago::Pirate::BLACKBEARD.chests.keys.sort == [@c.service_id, @c2.service_id].sort
end
assert_within(10) do
- Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ Archipelago::Pirate::BLACKBEARD.trannies.keys == [@tm.service_id]
end
end
@@ -56,8 +56,8 @@
r1 = l.first_element.record_id
r2 = l.record_id
l.destroy!
- assert(!Hyperactive::CAPTAIN.include?(r1))
- assert(!Hyperactive::CAPTAIN.include?(r2))
+ assert(!Archipelago::Pirate::BLACKBEARD.include?(r1))
+ assert(!Archipelago::Pirate::BLACKBEARD.include?(r2))
end
def test_each
Modified: trunk/hyperactive/tests/record_test.rb
===================================================================
--- trunk/hyperactive/tests/record_test.rb 2006-12-10 23:39:03 UTC (rev 107)
+++ trunk/hyperactive/tests/record_test.rb 2006-12-10 23:40:05 UTC (rev 108)
@@ -37,14 +37,14 @@
@c2.publish!
@tm = TestManager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(__FILE__).parent.join("tranny1.db")))
@tm.publish!
- Hyperactive::CAPTAIN.setup(:chest_description => {:class => 'TestChest'},
+ Archipelago::Pirate::BLACKBEARD.setup(:chest_description => {:class => 'TestChest'},
:tranny_description => {:class => 'TestManager'})
- Hyperactive::CAPTAIN.update_services!
+ Archipelago::Pirate::BLACKBEARD.update_services!
assert_within(10) do
- Hyperactive::CAPTAIN.chests.keys.sort == [@c.service_id, @c2.service_id].sort
+ Archipelago::Pirate::BLACKBEARD.chests.keys.sort == [@c.service_id, @c2.service_id].sort
end
assert_within(10) do
- Hyperactive::CAPTAIN.trannies.keys == [@tm.service_id]
+ Archipelago::Pirate::BLACKBEARD.trannies.keys == [@tm.service_id]
end
$BEFORE_SAVE = 0
$AFTER_SAVE = 0
@@ -140,13 +140,13 @@
assert_equal(2, $BEFORE_SAVE)
assert_equal(2, $AFTER_SAVE)
assert_equal("brunt", r.bajs)
- assert_equal("brunt", Hyperactive::CAPTAIN[r.record_id].bajs)
+ assert_equal("brunt", Archipelago::Pirate::BLACKBEARD[r.record_id].bajs)
i = r.record_id
- assert_equal(r, Hyperactive::CAPTAIN[i])
+ assert_equal(r, Archipelago::Pirate::BLACKBEARD[i])
r.destroy!
assert_equal(1, $BEFORE_DESTROY)
assert_equal(1, $AFTER_DESTROY)
- assert_equal(nil, Hyperactive::CAPTAIN[i])
+ assert_equal(nil, Archipelago::Pirate::BLACKBEARD[i])
end
end
From nobody at rubyforge.org Sun Dec 10 19:46:38 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 10 Dec 2006 19:46:38 -0500 (EST)
Subject: [Archipelago-submits] [109] trunk/archipelago: added a tanker to
the services script.
Message-ID: <20061211004638.87BF15241448@rubyforge.org>
Revision: 109
Author: zond
Date: 2006-12-10 19:46:37 -0500 (Sun, 10 Dec 2006)
Log Message:
-----------
added a tanker to the services script. removed the chest and tranny scripts. added loading of bitstring, raider, cove and exxon to archipelago.rb. improved comments in client.rb. made client.rb take a specific jockey instead of jockey_options when a custom jockey is needed. added requirement of digest/sha1 to disco. created the exxon module that keeps tracks of tankers. added the cove module that handles tankers containing fragmented information (produced by raider).
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/client.rb
trunk/archipelago/lib/archipelago/disco.rb
trunk/archipelago/lib/archipelago.rb
trunk/archipelago/script/services.rb
Added Paths:
-----------
trunk/archipelago/lib/archipelago/cove.rb
trunk/archipelago/lib/archipelago/exxon.rb
Removed Paths:
-------------
trunk/archipelago/script/chest.rb
trunk/archipelago/script/tranny.rb
Modified: trunk/archipelago/lib/archipelago/client.rb
===================================================================
--- trunk/archipelago/lib/archipelago/client.rb 2006-12-10 23:40:05 UTC (rev 108)
+++ trunk/archipelago/lib/archipelago/client.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -27,9 +27,11 @@
class Base
attr_reader :jockey
#
- # Initialize an instance using an Archipelago::Disco::Jockey with :jockey_options
- # if given, that looks for new services :initial_service_update_interval or INITIAL_SERVICE_UPDATE_INTERVAL,
- # when it starts and never slower than every :maximum_service_update_interval or MAXIMUM_SERVICE_UPDATE_INTERVAL.
+ # Initialize an instance using Archipelago::Disco::MC or :jockey if given,
+ # or a new Archipelago::Disco::Jockey if none, that looks for new services
+ # :initial_service_update_interval or INITIAL_SERVICE_UPDATE_INTERVAL,
+ # when it starts and never slower than every :maximum_service_update_interval
+ # or MAXIMUM_SERVICE_UPDATE_INTERVAL.
#
def initialize(options = {})
setup(options)
@@ -38,18 +40,15 @@
# Sets up this instance with the given +options+.
#
def setup(options = {})
- @jockey ||= nil
+ @jockey.stop! if defined?(@jockey) && @jockey != Archipelago::Disco::MC
if defined?(Archipelago::Disco::MC)
- @jockey.stop! if @jockey && @jockey != Archipelago::Disco::MC
- @jockey = options.include?(:jockey_options) ? Archipelago::Disco::Jockey.new(options[:jockey_options]) : Archipelago::Disco::MC
+ @jockey = options[:jockey] || Archipelago::Disco::MC
else
- @jockey.stop! if @jockey
- @jockey = Archipelago::Disco::Jockey.new(options[:jockey_options] || {})
+ @jockey = options[:jockey] || Archipelago::Disco::Jockey.new
end
@initial_service_update_interval = options[:initial_service_update_interval] || INITIAL_SERVICE_UPDATE_INTERVAL
@maximum_service_update_interval = options[:maximum_service_update_interval] || MAXIMUM_SERVICE_UPDATE_INTERVAL
-
end
#
Added: trunk/archipelago/lib/archipelago/cove.rb
===================================================================
--- trunk/archipelago/lib/archipelago/cove.rb (rev 0)
+++ trunk/archipelago/lib/archipelago/cove.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -0,0 +1,68 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'archipelago/disco'
+require 'archipelago/hashish'
+require 'archipelago/exxon'
+require 'archipelago/raider'
+
+module Archipelago
+
+ module Cove
+
+ class Tanker
+
+ #
+ # The Tanker can be published.
+ #
+ include Archipelago::Disco::Publishable
+
+ def initialize(options = {})
+ #
+ # The provider of happy magic persistent hashes of different kinds.
+ #
+ @persistence_provider = options[:persistence_provider] || Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(File.expand_path(__FILE__)).parent.join("cove_tanker.db"))
+
+ @db = @persistence_provider.get_hashish("db")
+
+ @valdez = options[:valdez] || Archipelago::Exxon::HAZELWOOD
+
+ #
+ # Use the given options to initialize the publishable
+ # instance variables.
+ #
+ initialize_publishable(options)
+
+ end
+
+ def store_part(key, split_part)
+ @db[key] = Marshal.dump(split_part)
+ end
+
+ def get_part(key)
+ if @db.include?(key)
+ return Marshal.load(@db[key])
+ else
+ return nil
+ end
+ end
+
+ end
+
+ end
+
+end
Modified: trunk/archipelago/lib/archipelago/disco.rb
===================================================================
--- trunk/archipelago/lib/archipelago/disco.rb 2006-12-10 23:40:05 UTC (rev 108)
+++ trunk/archipelago/lib/archipelago/disco.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -22,6 +22,7 @@
require 'archipelago/current'
require 'drb'
require 'set'
+require 'digest/sha1'
module Archipelago
Added: trunk/archipelago/lib/archipelago/exxon.rb
===================================================================
--- trunk/archipelago/lib/archipelago/exxon.rb (rev 0)
+++ trunk/archipelago/lib/archipelago/exxon.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -0,0 +1,138 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'archipelago/client'
+
+module Archipelago
+
+ module Exxon
+
+ TANKER_DESCRIPTION = {
+ :class => 'Archipelago::Cove::Tanker'
+ }
+
+ PARTS = 3
+
+ #
+ # Raised when you try to do stuff without any remote database
+ # available.
+ #
+ class NoRemoteDatabaseAvailableException < RuntimeError
+ def initialize(valdez)
+ super("#{valdez} can not find any remote database for you")
+ end
+ end
+
+ class Valdez < Archipelago::Client::Base
+ attr_reader :tankers
+ def initialize(options = {})
+ super(options)
+
+ start_service_updater
+ end
+
+ def setup(options = {})
+ super(options)
+
+ @parts = options[:parts] || PARTS
+ @tanker_description = TANKER_DESCRIPTION.merge(options[:tanker_description] || {})
+ end
+
+ def []=(key, value)
+ split_parts = Archipelago::Raider.split(value, @parts)
+ followers = responsible_tankers(key, split_parts.size)
+ 0.upto(followers.size - 1) do |n|
+ followers[n].store_part(key, split_parts[n])
+ end
+ end
+
+ def [](key)
+ return_value = nil
+
+ split_parts = []
+ followers = responsible_tankers(key, (1 << @parts) - 1)
+ while split_parts.size < @parts
+ split_parts << followers.shift.get_part(key)
+ end
+ begin
+ return_value = Archipelago::Raider.join(*split_parts.compact)
+ rescue Archipelago::Raider::NotEnoughBulkError => e
+ if followers.empty?
+ raise e
+ else
+ split_parts << followers.shift.get_part(key)
+ retry
+ end
+ end
+
+ return return_value
+ end
+
+ def update_services!
+ @tankers = @jockey.lookup(Archipelago::Disco::Query.new(@tanker_description), 0)
+ end
+
+ def responsible_tankers(key, n)
+ raise NoRemoteDatabaseAvailableException.new(self) if @tankers.empty?
+
+ responsible_ids = []
+
+ key_id = Digest::SHA1.hexdigest(Marshal.dump(key))
+ sorted_tanker_ids = @tankers.keys.sort
+ 0.upto(sorted_tanker_ids.size - 1) do |index|
+ id = sorted_tanker_ids[index]
+ if id > key_id
+ responsible_ids = get_some(sorted_tanker_ids, index, n)
+ end
+ end
+ responsible_ids = get_some(sorted_tanker_ids, 0, n)
+
+ return responsible_ids.collect do |id|
+ @tankers[id][:service]
+ end
+ end
+
+ def responsible_tanker(key)
+ return responsible_tankers(key, 1).first
+ end
+
+ private
+
+ def get_some(array, index, n)
+ rval = []
+ while rval.size < n
+ index = 0 if index > array.size - 1
+ rval << array[index]
+ index += 1
+ end
+ return rval
+ end
+
+ end
+
+ #
+ # The default Archipelago::Exxon::Valdez that is always available for lookups is Archipelago::Exxon::HAZELWOOD.
+ #
+ # If you really need to you can customize it by defining HAZELWOOD_OPTIONS before loading disco.rb, and if you REALLY
+ # need to you can disable it completely by setting HAZELWOOD_DISABLED to true.
+ #
+ HAZELWOOD = Valdez.new(defined?(HAZELWOOD_OPTIONS) ? HAZELWOOD_OPTIONS : {}) unless defined?(HAZELWOOD_DISABLED) && HAZELWOOD_DISABLED
+
+
+ end
+
+end
Modified: trunk/archipelago/lib/archipelago.rb
===================================================================
--- trunk/archipelago/lib/archipelago.rb 2006-12-10 23:40:05 UTC (rev 108)
+++ trunk/archipelago/lib/archipelago.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -17,11 +17,13 @@
$: << File.dirname(File.expand_path(__FILE__))
+require 'archipelago/bitstring'
+require 'archipelago/raider'
require 'archipelago/disco'
require 'archipelago/current'
require 'archipelago/tranny'
require 'archipelago/treasure'
require 'archipelago/client'
require 'archipelago/pirate'
-require 'archipelago/bitstring'
-require 'archipelago/raider'
+require 'archipelago/cove'
+require 'archipelago/exxon'
Deleted: trunk/archipelago/script/chest.rb
===================================================================
--- trunk/archipelago/script/chest.rb 2006-12-10 23:40:05 UTC (rev 108)
+++ trunk/archipelago/script/chest.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -1,21 +0,0 @@
-#!/usr/bin/env ruby
-
-if ARGV.size < 1
- puts "Usage: #{$0} DB-PATH [EXTRA-LIBS]"
- exit 1
-end
-
-$: << File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'archipelago/treasure'
-
-ARGV[1..-1].each do |lib|
- load lib
-end
-
-DRb.start_service
-
-c = Archipelago::Treasure::Chest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(ARGV[0])))
-c.publish!
-
-DRb.thread.join
Modified: trunk/archipelago/script/services.rb
===================================================================
--- trunk/archipelago/script/services.rb 2006-12-10 23:40:05 UTC (rev 108)
+++ trunk/archipelago/script/services.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -9,6 +9,7 @@
require 'archipelago/treasure'
require 'archipelago/tranny'
+require 'archipelago/cove'
if ARGV.size > 1
DRb.start_service(ARGV[1])
@@ -23,5 +24,7 @@
t.publish!
c = Archipelago::Treasure::Chest.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(File.join(ARGV[0], "chest"))))
c.publish!
+tank = Archipelago::Cove::Tanker.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(File.join(ARGV[0], "tanker"))))
+tank.publish!
DRb.thread.join
Deleted: trunk/archipelago/script/tranny.rb
===================================================================
--- trunk/archipelago/script/tranny.rb 2006-12-10 23:40:05 UTC (rev 108)
+++ trunk/archipelago/script/tranny.rb 2006-12-11 00:46:37 UTC (rev 109)
@@ -1,21 +0,0 @@
-#!/usr/bin/env ruby
-
-if ARGV.size < 1
- puts "Usage: #{$0} DB-PATH [EXTRA-LIBS]"
- exit 1
-end
-
-$: << File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'archipelago/treasure'
-
-ARGV[1..-1].each do |lib|
- load lib
-end
-
-DRb.start_service
-
-t = Archipelago::Tranny::Manager.new(:persistence_provider => Archipelago::Hashish::BerkeleyHashishProvider.new(Pathname.new(ARGV[0])))
-t.publish!
-
-DRb.thread.join
From nobody at rubyforge.org Mon Dec 11 05:04:25 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Mon, 11 Dec 2006 05:04:25 -0500 (EST)
Subject: [Archipelago-submits] [110] trunk/archipelago/TODO: added TODO
Message-ID: <20061211100426.096415240BC3@rubyforge.org>
Revision: 110
Author: zond
Date: 2006-12-11 05:04:25 -0500 (Mon, 11 Dec 2006)
Log Message:
-----------
added TODO
Modified Paths:
--------------
trunk/archipelago/TODO
Modified: trunk/archipelago/TODO
===================================================================
--- trunk/archipelago/TODO 2006-12-11 00:46:37 UTC (rev 109)
+++ trunk/archipelago/TODO 2006-12-11 10:04:25 UTC (rev 110)
@@ -11,6 +11,9 @@
of Chord (continously checking if our data is safely replicated across
the network, continously checking that our data belong with us)
+ * Replace Raider with some well known near-optimal erasure code, for example
+ Online Codes: http://en.wikipedia.org/wiki/Online_codes
+
* Make Chest aware about whether transactions have affected it 'for real' ie
check whether the instance before the call differs from the instance after
the call. Preferably without incurring performance lossage.
From nobody at rubyforge.org Wed Dec 13 12:37:21 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 13 Dec 2006 12:37:21 -0500 (EST)
Subject: [Archipelago-submits] [111] trunk/archipelago/lib: added broken
oneliner-encoding string
Message-ID: <20061213173721.F038B5241400@rubyforge.org>
Revision: 111
Author: zond
Date: 2006-12-13 12:37:21 -0500 (Wed, 13 Dec 2006)
Log Message:
-----------
added broken oneliner-encoding string
Modified Paths:
--------------
trunk/archipelago/lib/archipelago.rb
Added Paths:
-----------
trunk/archipelago/lib/archipelago/string.rb
Added: trunk/archipelago/lib/archipelago/string.rb
===================================================================
--- trunk/archipelago/lib/archipelago/string.rb (rev 0)
+++ trunk/archipelago/lib/archipelago/string.rb 2006-12-13 17:37:21 UTC (rev 111)
@@ -0,0 +1,380 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'rubygems'
+require 'inline'
+
+#
+# Adds a few methods to String, some using the inline gem.
+#
+class String
+
+ E = 0.01
+ Q = 3
+ F = Math.log(E ** 2 / 4) / Math.log(1 - (E / 2))
+
+ class << self
+ private
+ def get_p_distribution
+ rval = "double P[] = {0.0,"
+ 1.upto(F) do |n|
+ p1 = 1 - ( (1 + (1 / F) ) / (1 + E) )
+ if n == 1
+ rval << "#{p1}"
+ else
+ rval << "#{( ( 1 - p1 ) * F ) / ( ( F - 1 ) * n * ( n - 1 ) )}"
+ end
+ rval << "," unless n + 1 > F
+ end
+ rval << "};"
+ return rval
+ end
+ end
+
+ inline do |builder|
+ #
+ # We need math.h
+ #
+ builder.include("")
+ #
+ # We need sys/time.h
+ #
+ builder.include("")
+ #
+ # Define the p distribution array so that it is easily accessible.
+ #
+ builder.prefix(get_p_distribution)
+ #
+ # Define a sane random number generator.
+ #
+ builder.prefix("#define RAND (((double)random())/((double)RAND_MAX+1))")
+ builder.prefix("#define RANDOM(n) (random() % n)")
+ #
+ # Get a random degree.
+ #
+ builder.c_raw < 0.0) {
+ rval ++;
+ d = d - P[rval];
+ }
+ if (rval > size)
+ return size;
+ else
+ return rval;
+}
+EOC
+ #
+ # Get the array of known chunks, with the new chunk appended.
+ #
+ builder.c_raw <len == 0)
+ rb_funcall(self, rb_intern("<<"), 1, rb_str_new(0, size));
+ else if (RSTRING(self)->len != size)
+ rb_raise(rb_eRuntimeError, "oneline_decode can only be called on empty Strings or strings already having been sent oneline_decode with a chunk from the same source");
+}
+EOC
+ #
+ # Check if a certain block is known.
+ #
+ builder.c_raw <len * 8); tmp++)
+ rb_funcall(return_value, push, 1, INT2NUM(_get_is_known(RSTRING(decode_status)->ptr, tmp)));
+ }
+ return return_value;
+}
+EOC
+ #
+ # Set that a certain block is known.
+ #
+ builder.c_raw < -1; size--) {
+ if (!_get_is_known(RSTRING(decode_status)->ptr, size))
+ return Qfalse;
+ }
+ return Qtrue;
+}
+EOC
+ #
+ # Decode the given chunk until we dont get any new
+ # data from it.
+ #
+ builder.c_raw <ptr )[0];
+ long size = ( (long *) RSTRING(chunk)->ptr )[1];
+ long tmp, tmp2;
+ char got_new_block;
+ char got_new_block_ever = 0;
+
+ do {
+ got_new_block = 0;
+
+ for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
+ long degree;
+
+ srandom(seed + tmp);
+
+ degree = _get_m_degree(size);
+ if (degree == 1) {
+ long block_nr;
+
+ srandom(seed + tmp + degree);
+
+ block_nr = RANDOM(size);
+
+ if (!_get_is_known(decode_status, block_nr)) {
+ rb_str_modify(self);
+ RSTRING(self)->ptr[block_nr] = RSTRING(chunk)->ptr[tmp];
+ _set_is_known(decode_status, block_nr);
+ got_new_block_ever = got_new_block = 1;
+ }
+ } else {
+ long missing_blocks;
+ long missing_block;
+ char xor_sum;
+ char first_block;
+
+ for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
+ long block_nr;
+
+ srandom(seed + tmp + tmp2);
+
+ block_nr = RANDOM(size);
+
+ if (_get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ if (first_block) {
+ xor_sum = RSTRING(self)->ptr[block_nr];
+ } else {
+ xor_sum = xor_sum ^ RSTRING(self)->ptr[block_nr];
+ }
+ } else {
+ missing_block = block_nr;
+ }
+ }
+ if (missing_blocks == 1) {
+ rb_str_modify(self);
+ RSTRING(self)->ptr[missing_block] = xor_sum ^ RSTRING(chunk)->ptr[tmp];
+ _set_is_known(decode_status, missing_block);
+ got_new_block_ever = got_new_block = 1;
+ }
+ }
+ }
+ } while (got_new_block);
+
+ return got_new_block_ever;
+}
+EOC
+ #
+ # Decode this String into another String
+ #
+ builder.c_raw <len < 8)
+ rb_raise(rb_eRuntimeError, "oneline_decode argument must be a legal chunk (> 7 bytes)");
+
+ _ensure_size(self, (size = ( (long *) RSTRING(chunk)->ptr )[1]));
+
+ known_chunks = _get_known_chunks(chunk, self);
+ decode_status = _get_decode_status(size, self);
+
+ do {
+ got_new_block = 0;
+
+ for (tmp = 0; tmp < NUM2INT(rb_funcall(known_chunks, rb_intern("size"), 0)); tmp++) {
+ got_new_block = _decode_chunk_until_done(rb_funcall(known_chunks, rb_intern("[]"), 1, INT2NUM(tmp)),
+ RSTRING(decode_status)->ptr,
+ self) || got_new_block;
+ }
+ } while (got_new_block);
+
+ return _oneline_done(decode_status, size);
+}
+EOC
+ #
+ # Get a check block from a message.
+ #
+ builder.c_raw <len); degree > 0; degree--) {
+ long block_number;
+ srandom(seed + index + degree);
+ block_number = RANDOM(RSTRING(self)->len);
+ found_block = RSTRING(self)->ptr[block_number];
+ if (empty_block) {
+ block = found_block;
+ empty_block = 0;
+ } else {
+ block = block ^ found_block;
+ }
+ }
+
+ return block;
+}
+EOC
+ #
+ # Returns a chunk of coded data for a given message.
+ #
+ builder.c <len;
+
+ for (tmp = 8; tmp < bytes_per_chunk; tmp++) {
+ chunk[tmp] = _get_check_block(self, seed, tmp);
+ }
+
+ return rb_str_new(chunk, bytes_per_chunk);
+}
+EOC
+ end
+
+end
Modified: trunk/archipelago/lib/archipelago.rb
===================================================================
--- trunk/archipelago/lib/archipelago.rb 2006-12-11 10:04:25 UTC (rev 110)
+++ trunk/archipelago/lib/archipelago.rb 2006-12-13 17:37:21 UTC (rev 111)
@@ -18,6 +18,7 @@
$: << File.dirname(File.expand_path(__FILE__))
require 'archipelago/bitstring'
+require 'archipelago/oneliner'
require 'archipelago/raider'
require 'archipelago/disco'
require 'archipelago/current'
From nobody at rubyforge.org Thu Dec 14 09:31:19 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Thu, 14 Dec 2006 09:31:19 -0500 (EST)
Subject: [Archipelago-submits] [112] trunk/archipelago/lib/archipelago:
blargh
Message-ID: <20061214143119.8CFF152410C1@rubyforge.org>
Revision: 112
Author: zond
Date: 2006-12-14 09:31:18 -0500 (Thu, 14 Dec 2006)
Log Message:
-----------
blargh
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/string.rb
Added Paths:
-----------
trunk/archipelago/lib/archipelago/oneline.rb
Added: trunk/archipelago/lib/archipelago/oneline.rb
===================================================================
--- trunk/archipelago/lib/archipelago/oneline.rb (rev 0)
+++ trunk/archipelago/lib/archipelago/oneline.rb 2006-12-14 14:31:18 UTC (rev 112)
@@ -0,0 +1,425 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'rubygems'
+require 'inline'
+
+#
+# Adds a few methods to String, some using the inline gem.
+#
+class String
+
+ E = 0.01
+ Q = 3
+ F = Math.log(E ** 2 / 4) / Math.log(1 - (E / 2))
+
+ class << self
+ private
+ def get_p_distribution
+ rval = "double P[] = {0.0,"
+ 1.upto(F) do |n|
+ p1 = 1 - ( (1 + (1 / F) ) / (1 + E) )
+ if n == 1
+ rval << "#{p1}"
+ else
+ rval << "#{( ( 1 - p1 ) * F ) / ( ( F - 1 ) * n * ( n - 1 ) )}"
+ end
+ rval << "," unless n + 1 > F
+ end
+ rval << "};"
+ return rval
+ end
+ end
+
+ def decode_level
+ status = self.decode_status
+ status.select do |s| s == 1 end.size.to_f / status.size.to_f
+ end
+
+ inline do |builder|
+ #
+ # We need math.h
+ #
+ builder.include("")
+ #
+ # We need sys/time.h
+ #
+ builder.include("")
+ #
+ # Define the p distribution array so that it is easily accessible.
+ #
+ builder.prefix(get_p_distribution)
+ #
+ # Define a sane random number generator.
+ #
+ builder.prefix("#define RAND (((double)random())/((double)RAND_MAX+1))")
+ builder.prefix("#define RANDOM(n) (random() % n)")
+ #
+ # Get a random degree.
+ #
+ builder.c_raw < 0.0) {
+ rval ++;
+ d = d - P[rval];
+ }
+ if (rval > size)
+ return size;
+ else
+ return rval;
+}
+EOC
+ builder.c_raw <len == 0)
+ rb_funcall(self, rb_intern("<<"), 1, rb_str_new(0, size));
+ else if (RSTRING(self)->len != size)
+ rb_raise(rb_eRuntimeError, "oneline_decode can only be called on empty Strings or strings already having been sent oneline_decode with a chunk from the same source");
+}
+EOC
+ #
+ # Check if a certain block is known.
+ #
+ builder.c_raw <len * 8); tmp++)
+ rb_funcall(return_value, push, 1, INT2NUM(_get_is_known(RSTRING(decode_status)->ptr, tmp)));
+ }
+ return return_value;
+}
+EOC
+ #
+ # Set that a certain block is known.
+ #
+ builder.c_raw < -1; size--) {
+ if (!_get_is_known(RSTRING(decode_status)->ptr, size))
+ return Qfalse;
+ }
+ return Qtrue;
+}
+EOC
+ #
+ # Decode the given chunk until we dont get any new
+ # data from it.
+ #
+ builder.c <ptr;
+ long seed = ( (long *) rstring_chunk->ptr )[0];
+ long size = ( (long *) rstring_chunk->ptr )[1];
+ long tmp, tmp2;
+ char got_new_block;
+ char got_new_block_ever = 0;
+
+ do {
+ got_new_block = 0;
+
+ for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
+ long degree;
+
+ srandom(seed + tmp);
+
+ degree = _get_m_degree(size);
+ if (degree == 1) {
+ long block_nr;
+
+ srandom(seed + tmp + degree);
+
+ block_nr = RANDOM(size);
+
+ if (!_get_is_known(decode_status, block_nr)) {
+ rb_str_modify(self);
+ RSTRING(self)->ptr[block_nr] = RSTRING(chunk)->ptr[tmp];
+ _set_is_known(decode_status, block_nr);
+ got_new_block_ever = got_new_block = 1;
+ }
+ } else {
+ long missing_blocks;
+ long missing_block;
+ char xor_sum;
+ char first_block = 1;
+
+ for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
+ long block_nr;
+
+ srandom(seed + tmp + tmp2);
+
+ block_nr = RANDOM(size);
+
+ if (_get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ if (first_block) {
+ xor_sum = RSTRING(self)->ptr[block_nr];
+ first_block = 0;
+ } else {
+ xor_sum = xor_sum ^ RSTRING(self)->ptr[block_nr];
+ }
+ } else {
+ missing_block = block_nr;
+ }
+ }
+ if (missing_blocks == 1) {
+ rb_str_modify(self);
+ RSTRING(self)->ptr[missing_block] = xor_sum ^ RSTRING(chunk)->ptr[tmp];
+ _set_is_known(decode_status, missing_block);
+ got_new_block_ever = got_new_block = 1;
+ }
+ }
+ }
+ } while (got_new_block);
+
+ if (got_new_block_ever)
+ return Qtrue;
+ else
+ return Qfalse;
+}
+EOC
+ #
+ # Get a check block from a message.
+ #
+ builder.c_raw <len); degree > 0; degree--) {
+ long block_number;
+ char found_block;
+
+ srandom(seed + index + degree);
+
+ block_number = RANDOM(rstring_self->len + rstring_aux_blocks->len);
+ if (block_number > (rstring_self->len - 1))
+ found_block = rstring_self->ptr[block_number];
+ else
+ found_block = rstring_aux_blocks[block_number - rstring_self->len];
+
+ if (empty_block) {
+ block = found_block;
+ empty_block = 0;
+ } else {
+ block = block ^ found_block;
+ }
+ }
+ return block;
+}
+EOC
+ #
+ # Fill our aux blocks with the proper data.
+ #
+ builder.c <len);
+
+ for (tmp = 0; tmp < rstring_self->len; tmp++) {
+ for (tmp2 = 0; tmp2 < 3; tmp2++) {
+ long aux_block_nr = RANDOM(rstring_self->len)
+ if (initialized_aux_blocks[aux_block_nr])
+ aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ rstring_self->ptr[tmp];
+ else
+ aux_blocks[aux_block_nr] = rstring_self->ptr[tmp];
+ }
+ }
+
+ rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
+}
+EOC
+ #
+ # Returns a chunk of coded data for a given message.
+ #
+ builder.c <len;
+
+ for (tmp = 8; tmp < chunk_size; tmp++) {
+ chunk[tmp] = _get_check_block(self, seed, tmp, aux_blocks);
+ }
+
+ return rb_str_new(chunk, chunk_size);
+}
+EOC
+ end
+
+ def oneline_encode(chunk_size)
+ aux_blocks = (self.size * (Q * E * 0.55 + 1)).to_i
+ ensure_aux_blocks(aux_blocks)
+ return _get_chunk(chunk_size, aux_blocks)
+ end
+
+ def oneline_decode(chunk)
+ needed_size = chunk[0..3].unpack("L").first
+ if size == 0
+ concat(" " * needed_size)
+ else
+ raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
+ end
+
+ @_decode_status ||= " " * ((needed_size / 8) + 1)
+ @_known_chunks ||= []
+
+
+ @_known_chunks.unshift(chunk)
+
+ found_new_block = nil
+ begin
+ found_new_block = false
+ @_known_chunks.each do |known_chunk|
+ found_new_block = _decode_chunk_until_done(chunk, @_decode_status) || found_new_block
+ end
+ end while found_new_block
+
+ return oneline_done
+ end
+
+ private
+
+ def ensure_aux_blocks(size)
+ _fill_aux_blocks() unless @_aux_blocks
+ end
+
+end
Modified: trunk/archipelago/lib/archipelago/string.rb
===================================================================
--- trunk/archipelago/lib/archipelago/string.rb 2006-12-13 17:37:21 UTC (rev 111)
+++ trunk/archipelago/lib/archipelago/string.rb 2006-12-14 14:31:18 UTC (rev 112)
@@ -45,6 +45,11 @@
end
end
+ def decode_level
+ status = self.decode_status
+ status.select do |s| s == 1 end.size.to_f / status.size.to_f
+ end
+
inline do |builder|
#
# We need math.h
@@ -68,17 +73,6 @@
#
builder.c_raw <ptr )[0];
- long size = ( (long *) RSTRING(chunk)->ptr )[1];
+ struct RString rstring_self = RSTRING(self);
+ struct RString rstring_chunk = RSTRING(chunk);
+ char *decode_status = RSTRING(decode_status)->ptr;
+ long seed = ( (long *) rstring_chunk->ptr )[0];
+ long size = ( (long *) rstring_chunk->ptr )[1];
long tmp, tmp2;
char got_new_block;
char got_new_block_ever = 0;
@@ -243,7 +251,7 @@
long missing_blocks;
long missing_block;
char xor_sum;
- char first_block;
+ char first_block = 1;
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
long block_nr;
@@ -251,11 +259,12 @@
srandom(seed + tmp + tmp2);
block_nr = RANDOM(size);
-
+
if (_get_is_known(decode_status, block_nr)) {
missing_blocks--;
if (first_block) {
xor_sum = RSTRING(self)->ptr[block_nr];
+ first_block = 0;
} else {
xor_sum = xor_sum ^ RSTRING(self)->ptr[block_nr];
}
@@ -273,71 +282,40 @@
}
} while (got_new_block);
- return got_new_block_ever;
+ if (got_new_block_ever)
+ return Qtrue;
+ else
+ return Qfalse;
}
EOC
#
- # Decode this String into another String
- #
- builder.c_raw <len < 8)
- rb_raise(rb_eRuntimeError, "oneline_decode argument must be a legal chunk (> 7 bytes)");
-
- _ensure_size(self, (size = ( (long *) RSTRING(chunk)->ptr )[1]));
-
- known_chunks = _get_known_chunks(chunk, self);
- decode_status = _get_decode_status(size, self);
-
- do {
- got_new_block = 0;
-
- for (tmp = 0; tmp < NUM2INT(rb_funcall(known_chunks, rb_intern("size"), 0)); tmp++) {
- got_new_block = _decode_chunk_until_done(rb_funcall(known_chunks, rb_intern("[]"), 1, INT2NUM(tmp)),
- RSTRING(decode_status)->ptr,
- self) || got_new_block;
- }
- } while (got_new_block);
-
- return _oneline_done(decode_status, size);
-}
-EOC
- #
# Get a check block from a message.
#
builder.c_raw <len); degree > 0; degree--) {
+
+ for (degree = _get_m_degree(rstring_self->len); degree > 0; degree--) {
long block_number;
+ char found_block;
+
srandom(seed + index + degree);
- block_number = RANDOM(RSTRING(self)->len);
- found_block = RSTRING(self)->ptr[block_number];
+
+ block_number = RANDOM(rstring_self->len + rstring_aux_blocks->len);
+ if (block_number > (rstring_self->len - 1))
+ found_block = rstring_self->ptr[block_number];
+ else
+ found_block = rstring_aux_blocks[block_number - rstring_self->len];
+
if (empty_block) {
block = found_block;
empty_block = 0;
@@ -345,21 +323,51 @@
block = block ^ found_block;
}
}
-
return block;
}
EOC
#
+ # Fill our aux blocks with the proper data.
+ #
+ builder.c <len);
+
+ for (tmp = 0; tmp < rstring_self->len; tmp++) {
+ for (tmp2 = 0; tmp2 < 3; tmp2++) {
+ long aux_block_nr = RANDOM(rstring_self->len)
+ if (initialized_aux_blocks[aux_block_nr])
+ aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ rstring_self->ptr[tmp];
+ else
+ aux_blocks[aux_block_nr] = rstring_self->ptr[tmp];
+ }
+ }
+
+ rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
+}
+EOC
+ #
# Returns a chunk of coded data for a given message.
#
builder.c <len;
- for (tmp = 8; tmp < bytes_per_chunk; tmp++) {
- chunk[tmp] = _get_check_block(self, seed, tmp);
+ for (tmp = 8; tmp < chunk_size; tmp++) {
+ chunk[tmp] = _get_check_block(self, seed, tmp, aux_blocks);
}
- return rb_str_new(chunk, bytes_per_chunk);
+ return rb_str_new(chunk, chunk_size);
}
EOC
end
+
+ def oneline_encode(chunk_size)
+ aux_blocks = (self.size * (Q * E * 0.55 + 1)).to_i
+ ensure_aux_blocks(aux_blocks)
+ return _get_chunk(chunk_size, aux_blocks)
+ end
+
+ def oneline_decode(chunk)
+ needed_size = chunk[0..3].unpack("L").first
+ if size == 0
+ concat(" " * needed_size)
+ else
+ raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
+ end
+
+ @_decode_status ||= " " * ((needed_size / 8) + 1)
+ @_known_chunks ||= []
+
+
+ @_known_chunks.unshift(chunk)
+ found_new_block = nil
+ begin
+ found_new_block = false
+ @_known_chunks.each do |known_chunk|
+ found_new_block = _decode_chunk_until_done(chunk, @_decode_status) || found_new_block
+ end
+ end while found_new_block
+
+ return oneline_done
+ end
+
+ private
+
+ def ensure_aux_blocks(size)
+ _fill_aux_blocks() unless @_aux_blocks
+ end
+
end
From nobody at rubyforge.org Mon Dec 18 11:45:20 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Mon, 18 Dec 2006 11:45:20 -0500 (EST)
Subject: [Archipelago-submits] [113] trunk/archipelago/lib/archipelago:
fixed a brokenness in pirate.rb.
Message-ID: <20061218164521.28E3752412E1@rubyforge.org>
Revision: 113
Author: zond
Date: 2006-12-18 11:45:19 -0500 (Mon, 18 Dec 2006)
Log Message:
-----------
fixed a brokenness in pirate.rb. added working but not good enough oneline decode/encode strings.
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/oneline.rb
trunk/archipelago/lib/archipelago/pirate.rb
Removed Paths:
-------------
trunk/archipelago/lib/archipelago/string.rb
Modified: trunk/archipelago/lib/archipelago/oneline.rb
===================================================================
--- trunk/archipelago/lib/archipelago/oneline.rb 2006-12-14 14:31:18 UTC (rev 112)
+++ trunk/archipelago/lib/archipelago/oneline.rb 2006-12-18 16:45:19 UTC (rev 113)
@@ -17,39 +17,46 @@
require 'rubygems'
require 'inline'
+require 'pp'
#
# Adds a few methods to String, some using the inline gem.
#
class String
- E = 0.01
- Q = 3
- F = Math.log(E ** 2 / 4) / Math.log(1 - (E / 2))
+ E = [0.1, 0.01]
+ Q = [6, 3]
+ THRESHOLDS = [1024]
class << self
private
- def get_p_distribution
- rval = "double P[] = {0.0,"
- 1.upto(F) do |n|
- p1 = 1 - ( (1 + (1 / F) ) / (1 + E) )
+ def get_f(e)
+ Math.log(e ** 2 / 4) / Math.log(1 - (e / 2))
+ end
+ def _get_p_distribution(name, e)
+ f = get_f(e)
+ rval = "double #{name}[] = {0.0,"
+ p1 = 1 - ( (1 + (1 / f) ) / (1 + e) )
+ 1.upto(f) do |n|
if n == 1
rval << "#{p1}"
else
- rval << "#{( ( 1 - p1 ) * F ) / ( ( F - 1 ) * n * ( n - 1 ) )}"
+ rval << "#{( ( 1 - p1 ) * f ) / ( ( f - 1 ) * n * ( n - 1 ) )}"
end
- rval << "," unless n + 1 > F
+ rval << "," unless n + 1 > f
end
- rval << "};"
+ rval << "};\n"
return rval
end
+ def get_p_distribution
+ rval = ""
+ 0.upto(E.size - 1) do |n|
+ rval << _get_p_distribution("P#{n}", E[n])
+ end
+ return rval
+ end
end
- def decode_level
- status = self.decode_status
- status.select do |s| s == 1 end.size.to_f / status.size.to_f
- end
-
inline do |builder|
#
# We need math.h
@@ -67,19 +74,21 @@
# Define a sane random number generator.
#
builder.prefix("#define RAND (((double)random())/((double)RAND_MAX+1))")
- builder.prefix("#define RANDOM(n) (random() % n)")
+ builder.prefix("#define RANDOM(n) (random() % (n))")
#
# Get a random degree.
#
- builder.c_raw < 0.0) {
rval ++;
- d = d - P[rval];
+ d = d - P#{n}[rval];
}
if (rval > size)
return size;
@@ -87,125 +96,103 @@
return rval;
}
EOC
- builder.c_raw <ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
}
EOC
#
- # Ensure that our size is either 0 or the given value.
- #
- # Will set it to the given value if it is zero.
+ # Set that a certain block is known.
#
- builder.c_raw <len == 0)
- rb_funcall(self, rb_intern("<<"), 1, rb_str_new(0, size));
- else if (RSTRING(self)->len != size)
- rb_raise(rb_eRuntimeError, "oneline_decode can only be called on empty Strings or strings already having been sent oneline_decode with a chunk from the same source");
-}
-EOC
- #
- # Check if a certain block is known.
- #
- builder.c_raw <ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
}
EOC
#
- # Get our decode status in a human readable form.
+ # Returns whether this String is decoded enough.
#
builder.c <len * 8); tmp++)
- rb_funcall(return_value, push, 1, INT2NUM(_get_is_known(RSTRING(decode_status)->ptr, tmp)));
+ long tmp;
+ if (decode_status == Qnil)
+ return Qfalse;
+ for (tmp = 0; tmp < (RSTRING(decode_status)->len - 1); tmp++) {
+ if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != 255) {
+ return Qfalse;
+ }
}
- return return_value;
+ for (tmp = 0; tmp < (RSTRING(self)->len % 8); tmp++) {
+ if (! ( (unsigned char) RSTRING(self)->ptr[tmp] ) & (1 << tmp)) {
+ return Qfalse;
+ }
+ }
+ return Qtrue;
}
EOC
#
- # Set that a certain block is known.
+ # Set a data or aux block with a known value.
#
- builder.c_raw <len) {
+ rb_str_modify(self);
+ RSTRING(self)->ptr[index] = value;
+ set_is_known(decode_status, index);
+ } else {
+ rb_str_modify(aux_blocks);
+ RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len] = value;
+ set_is_known(decode_status, index);
+ }
}
EOC
#
- # Returns whether this String is decoded enough.
+ # Get a data or aux block.
#
- builder.c_raw < -1; size--) {
- if (!_get_is_known(RSTRING(decode_status)->ptr, size))
- return Qfalse;
+ if (index < RSTRING(self)->len) {
+ return RSTRING(self)->ptr[index];
+ } else {
+ return RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len];
}
- return Qtrue;
}
EOC
#
@@ -214,107 +201,104 @@
#
builder.c <ptr;
- long seed = ( (long *) rstring_chunk->ptr )[0];
- long size = ( (long *) rstring_chunk->ptr )[1];
+ long seed = ( (long *) RSTRING(chunk)->ptr )[0];
+ long size = ( (long *) RSTRING(chunk)->ptr )[1];
long tmp, tmp2;
- char got_new_block;
- char got_new_block_ever = 0;
+ char got_new_block = 0;
+ long (*degree_func)() = get_degree_func(size);
- do {
- got_new_block = 0;
+ for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
+ long degree;
- for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
- long degree;
+ srandom(seed + tmp);
- srandom(seed + tmp);
+ //printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
- degree = _get_m_degree(size);
- if (degree == 1) {
- long block_nr;
+ degree = degree_func(size);
+ if (degree == 1) {
+ long block_nr;
- srandom(seed + tmp + degree);
+ srandom(seed + tmp + degree);
- block_nr = RANDOM(size);
+ block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
- if (!_get_is_known(decode_status, block_nr)) {
- rb_str_modify(self);
- RSTRING(self)->ptr[block_nr] = RSTRING(chunk)->ptr[tmp];
- _set_is_known(decode_status, block_nr);
- got_new_block_ever = got_new_block = 1;
- }
+ //printf(" %d", block_nr);
+
+ if (!get_is_known(decode_status, block_nr)) {
+ set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
} else {
- long missing_blocks;
- long missing_block;
- char xor_sum;
- char first_block = 1;
+ //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
+ }
+ } else {
+ long missing_blocks;
+ long missing_block;
+ char xor_sum = RSTRING(chunk)->ptr[tmp];
- for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
- long block_nr;
+ for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
+ long block_nr;
- srandom(seed + tmp + tmp2);
+ srandom(seed + tmp + tmp2);
- block_nr = RANDOM(size);
+ block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
- if (_get_is_known(decode_status, block_nr)) {
- missing_blocks--;
- if (first_block) {
- xor_sum = RSTRING(self)->ptr[block_nr];
- first_block = 0;
- } else {
- xor_sum = xor_sum ^ RSTRING(self)->ptr[block_nr];
- }
- } else {
- missing_block = block_nr;
- }
+ //printf(" %d", block_nr);
+
+ if (get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ //printf("!");
+ } else {
+ missing_block = block_nr;
+ //printf("?");
}
- if (missing_blocks == 1) {
- rb_str_modify(self);
- RSTRING(self)->ptr[missing_block] = xor_sum ^ RSTRING(chunk)->ptr[tmp];
- _set_is_known(decode_status, missing_block);
- got_new_block_ever = got_new_block = 1;
- }
}
+ if (missing_blocks == 1) {
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", missing_block, xor_sum);
+ }
}
- } while (got_new_block);
+ //printf("\\n");
+ fflush(NULL);
+ }
- if (got_new_block_ever)
- return Qtrue;
- else
- return Qfalse;
+ return got_new_block ? Qtrue : Qfalse;
}
EOC
#
# Get a check block from a message.
#
- builder.c_raw <len); degree > 0; degree--) {
+ //printf("creating check block %d:", index);
+
+ for (degree = degree_func(RSTRING(self)->len); degree > 0; degree--) {
long block_number;
char found_block;
- srandom(seed + index + degree);
+ srandom(seed + index + degree);
- block_number = RANDOM(rstring_self->len + rstring_aux_blocks->len);
- if (block_number > (rstring_self->len - 1))
- found_block = rstring_self->ptr[block_number];
- else
- found_block = rstring_aux_blocks[block_number - rstring_self->len];
+ block_number = RANDOM(RSTRING(self)->len + RSTRING(aux_blocks)->len);
+ if (block_number < RSTRING(self)->len) {
+ found_block = RSTRING(self)->ptr[block_number];
+ //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
+ } else {
+ found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
+ //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
+ }
if (empty_block) {
block = found_block;
@@ -323,6 +307,7 @@
block = block ^ found_block;
}
}
+ //printf(" => %d\\n", block);
return block;
}
EOC
@@ -331,28 +316,32 @@
#
builder.c <len);
+ srandom(RSTRING(self)->len);
- for (tmp = 0; tmp < rstring_self->len; tmp++) {
- for (tmp2 = 0; tmp2 < 3; tmp2++) {
- long aux_block_nr = RANDOM(rstring_self->len)
- if (initialized_aux_blocks[aux_block_nr])
- aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ rstring_self->ptr[tmp];
- else
- aux_blocks[aux_block_nr] = rstring_self->ptr[tmp];
+ for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ //printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
+ for (tmp2 = 0; tmp2 < q; tmp2++) {
+ long aux_block_nr = RANDOM(size);
+ //printf(" [%d]", aux_block_nr);
+ if (initialized_aux_blocks[aux_block_nr]) {
+ aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
+ } else {
+ aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
+ initialized_aux_blocks[aux_block_nr] = 1;
+ }
+ //printf(" => %d", aux_blocks[aux_block_nr]);
}
+ //printf("\\n");
}
-
rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
}
EOC
@@ -361,13 +350,13 @@
#
builder.c <len);
gettimeofday(&tmp_timeval, NULL);
srandom(tmp_timeval.tv_usec);
@@ -377,49 +366,197 @@
( (long *) chunk) [1] = RSTRING(self)->len;
for (tmp = 8; tmp < chunk_size; tmp++) {
- chunk[tmp] = _get_check_block(self, seed, tmp, aux_blocks);
+ chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func);
}
return rb_str_new(chunk, chunk_size);
}
EOC
+ #
+ # Create the @_aux_hash
+ #
+ builder.c <len);
+
+ for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ for (tmp2 = 0; tmp2 < q; tmp2++) {
+ long aux_block_nr = RANDOM(size);
+ VALUE data_blocks_for_this_aux_block;
+ if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
+ rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
+ rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2NUM(tmp));
+ }
+ }
+
+ for (tmp = 0; tmp < size; tmp++) {
+ VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
+ long number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
+ VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
+ for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
+ rb_str_modify(data_block_string);
+ ( (long *) RSTRING(data_block_string)->ptr )[tmp2] = (long) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
+ get_func,
+ 1,
+ INT2NUM(tmp2)));
+ }
+ rb_funcall(aux_ary, set_func, 2, INT2NUM(tmp), data_block_string);
+ }
+ rb_ivar_set(self, rb_intern("@_aux_hash"), aux_ary);
+}
+EOC
+ #
+ # Try to decode our data and aux blocks until we dont get any more data.
+ #
+ builder.c <len; tmp++) {
+ if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
+
+ //printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
+
+ VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
+
+ if (RSTRING(data_block_string)->len == 4) {
+ long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
+
+ //printf(" %d", block_nr);
+
+ if (!get_is_known(decode_status, block_nr)) {
+ set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ } else {
+ //printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ }
+ } else {
+ long missing_blocks;
+ long missing_block;
+ char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
+
+ for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
+ long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
+
+ //printf(" %d", block_nr);
+
+ if (get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ //printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
+ } else {
+ missing_block = block_nr;
+ //printf("?");
+ }
+ }
+ if (missing_blocks == 1) {
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", missing_block, xor_sum);
+ }
+ }
+ }
+ }
+ //printf("\\n");
+ fflush(NULL);
+
+ return got_new_block ? Qtrue : Qfalse;
+}
+EOC
end
def oneline_encode(chunk_size)
- aux_blocks = (self.size * (Q * E * 0.55 + 1)).to_i
- ensure_aux_blocks(aux_blocks)
- return _get_chunk(chunk_size, aux_blocks)
+ ensure_aux_blocks
+ return _get_chunk(chunk_size, @_aux_blocks)
end
def oneline_decode(chunk)
- needed_size = chunk[0..3].unpack("L").first
+
+ needed_size = chunk[4..7].unpack("L").first
if size == 0
- concat(" " * needed_size)
- else
+ concat("\000" * needed_size)
+ elsif size != needed_size
raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
end
- @_decode_status ||= " " * ((needed_size / 8) + 1)
+ @_decode_status ||= "\000" * (((needed_size + get_aux_blocks) / 8) + 1)
@_known_chunks ||= []
+ @_aux_blocks ||= "\000" * get_aux_blocks
+ found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks)
+ do_decode if found_new_block
@_known_chunks.unshift(chunk)
-
- found_new_block = nil
- begin
- found_new_block = false
- @_known_chunks.each do |known_chunk|
- found_new_block = _decode_chunk_until_done(chunk, @_decode_status) || found_new_block
- end
- end while found_new_block
+ nil while do_decode
+
return oneline_done
end
+ def oneline_done
+ return nil unless @_decode_status
+ return _oneline_done(@_decode_status)
+ end
+
+ def decode_status
+ return nil unless @_decode_status
+ @_decode_status.unpack("b*").first
+ end
+
private
- def ensure_aux_blocks(size)
- _fill_aux_blocks() unless @_aux_blocks
+ def get_aux_blocks
+ (self.size * (get_q * get_e * 0.55)).ceil
end
+
+ def get_q
+ 0.upto(THRESHOLDS.size - 1) do |n|
+ if size < THRESHOLDS[n]
+ return Q[n]
+ end
+ end
+ return Q.last
+ end
+
+ def do_decode
+ found_new_block = false
+ @_known_chunks.each do |known_chunk|
+ found_new_block = _decode_chunk(known_chunk, @_decode_status, @_aux_blocks) || found_new_block
+ end
+ ensure_aux_hash
+ found_new_block = _aux_decode(@_decode_status, @_aux_blocks, @_aux_hash) || found_new_block
+ return found_new_block
+ end
+
+ def get_e
+ 0.upto(THRESHOLDS.size - 1) do |n|
+ if size < THRESHOLDS[n]
+ return E[n]
+ end
+ end
+ return E.last
+ end
+
+ def ensure_aux_blocks
+ _fill_aux_blocks(get_aux_blocks, get_q) unless @_aux_blocks
+ end
+
+ def ensure_aux_hash
+ _fill_aux_hash(get_q, get_aux_blocks) unless @_aux_hash
+ end
end
Modified: trunk/archipelago/lib/archipelago/pirate.rb
===================================================================
--- trunk/archipelago/lib/archipelago/pirate.rb 2006-12-14 14:31:18 UTC (rev 112)
+++ trunk/archipelago/lib/archipelago/pirate.rb 2006-12-18 16:45:19 UTC (rev 113)
@@ -180,8 +180,11 @@
@transaction = @trannies.values.first[:service].begin
begin
- yield(@transaction)
- raise CommitFailedException.new(self, @transaction) unless @transaction.commit! == :commited
+ begin
+ return yield(@transaction)
+ ensure
+ raise CommitFailedException.new(self, @transaction) unless @transaction.commit! == :commited
+ end
rescue Exception => e
@transaction.abort! unless @transaction.state == :aborted
raise e
Deleted: trunk/archipelago/lib/archipelago/string.rb
===================================================================
--- trunk/archipelago/lib/archipelago/string.rb 2006-12-14 14:31:18 UTC (rev 112)
+++ trunk/archipelago/lib/archipelago/string.rb 2006-12-18 16:45:19 UTC (rev 113)
@@ -1,425 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'rubygems'
-require 'inline'
-
-#
-# Adds a few methods to String, some using the inline gem.
-#
-class String
-
- E = 0.01
- Q = 3
- F = Math.log(E ** 2 / 4) / Math.log(1 - (E / 2))
-
- class << self
- private
- def get_p_distribution
- rval = "double P[] = {0.0,"
- 1.upto(F) do |n|
- p1 = 1 - ( (1 + (1 / F) ) / (1 + E) )
- if n == 1
- rval << "#{p1}"
- else
- rval << "#{( ( 1 - p1 ) * F ) / ( ( F - 1 ) * n * ( n - 1 ) )}"
- end
- rval << "," unless n + 1 > F
- end
- rval << "};"
- return rval
- end
- end
-
- def decode_level
- status = self.decode_status
- status.select do |s| s == 1 end.size.to_f / status.size.to_f
- end
-
- inline do |builder|
- #
- # We need math.h
- #
- builder.include("")
- #
- # We need sys/time.h
- #
- builder.include("")
- #
- # Define the p distribution array so that it is easily accessible.
- #
- builder.prefix(get_p_distribution)
- #
- # Define a sane random number generator.
- #
- builder.prefix("#define RAND (((double)random())/((double)RAND_MAX+1))")
- builder.prefix("#define RANDOM(n) (random() % n)")
- #
- # Get a random degree.
- #
- builder.c_raw < 0.0) {
- rval ++;
- d = d - P[rval];
- }
- if (rval > size)
- return size;
- else
- return rval;
-}
-EOC
- builder.c_raw <len == 0)
- rb_funcall(self, rb_intern("<<"), 1, rb_str_new(0, size));
- else if (RSTRING(self)->len != size)
- rb_raise(rb_eRuntimeError, "oneline_decode can only be called on empty Strings or strings already having been sent oneline_decode with a chunk from the same source");
-}
-EOC
- #
- # Check if a certain block is known.
- #
- builder.c_raw <len * 8); tmp++)
- rb_funcall(return_value, push, 1, INT2NUM(_get_is_known(RSTRING(decode_status)->ptr, tmp)));
- }
- return return_value;
-}
-EOC
- #
- # Set that a certain block is known.
- #
- builder.c_raw < -1; size--) {
- if (!_get_is_known(RSTRING(decode_status)->ptr, size))
- return Qfalse;
- }
- return Qtrue;
-}
-EOC
- #
- # Decode the given chunk until we dont get any new
- # data from it.
- #
- builder.c <ptr;
- long seed = ( (long *) rstring_chunk->ptr )[0];
- long size = ( (long *) rstring_chunk->ptr )[1];
- long tmp, tmp2;
- char got_new_block;
- char got_new_block_ever = 0;
-
- do {
- got_new_block = 0;
-
- for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
- long degree;
-
- srandom(seed + tmp);
-
- degree = _get_m_degree(size);
- if (degree == 1) {
- long block_nr;
-
- srandom(seed + tmp + degree);
-
- block_nr = RANDOM(size);
-
- if (!_get_is_known(decode_status, block_nr)) {
- rb_str_modify(self);
- RSTRING(self)->ptr[block_nr] = RSTRING(chunk)->ptr[tmp];
- _set_is_known(decode_status, block_nr);
- got_new_block_ever = got_new_block = 1;
- }
- } else {
- long missing_blocks;
- long missing_block;
- char xor_sum;
- char first_block = 1;
-
- for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
- long block_nr;
-
- srandom(seed + tmp + tmp2);
-
- block_nr = RANDOM(size);
-
- if (_get_is_known(decode_status, block_nr)) {
- missing_blocks--;
- if (first_block) {
- xor_sum = RSTRING(self)->ptr[block_nr];
- first_block = 0;
- } else {
- xor_sum = xor_sum ^ RSTRING(self)->ptr[block_nr];
- }
- } else {
- missing_block = block_nr;
- }
- }
- if (missing_blocks == 1) {
- rb_str_modify(self);
- RSTRING(self)->ptr[missing_block] = xor_sum ^ RSTRING(chunk)->ptr[tmp];
- _set_is_known(decode_status, missing_block);
- got_new_block_ever = got_new_block = 1;
- }
- }
- }
- } while (got_new_block);
-
- if (got_new_block_ever)
- return Qtrue;
- else
- return Qfalse;
-}
-EOC
- #
- # Get a check block from a message.
- #
- builder.c_raw <len); degree > 0; degree--) {
- long block_number;
- char found_block;
-
- srandom(seed + index + degree);
-
- block_number = RANDOM(rstring_self->len + rstring_aux_blocks->len);
- if (block_number > (rstring_self->len - 1))
- found_block = rstring_self->ptr[block_number];
- else
- found_block = rstring_aux_blocks[block_number - rstring_self->len];
-
- if (empty_block) {
- block = found_block;
- empty_block = 0;
- } else {
- block = block ^ found_block;
- }
- }
- return block;
-}
-EOC
- #
- # Fill our aux blocks with the proper data.
- #
- builder.c <len);
-
- for (tmp = 0; tmp < rstring_self->len; tmp++) {
- for (tmp2 = 0; tmp2 < 3; tmp2++) {
- long aux_block_nr = RANDOM(rstring_self->len)
- if (initialized_aux_blocks[aux_block_nr])
- aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ rstring_self->ptr[tmp];
- else
- aux_blocks[aux_block_nr] = rstring_self->ptr[tmp];
- }
- }
-
- rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
-}
-EOC
- #
- # Returns a chunk of coded data for a given message.
- #
- builder.c <len;
-
- for (tmp = 8; tmp < chunk_size; tmp++) {
- chunk[tmp] = _get_check_block(self, seed, tmp, aux_blocks);
- }
-
- return rb_str_new(chunk, chunk_size);
-}
-EOC
- end
-
- def oneline_encode(chunk_size)
- aux_blocks = (self.size * (Q * E * 0.55 + 1)).to_i
- ensure_aux_blocks(aux_blocks)
- return _get_chunk(chunk_size, aux_blocks)
- end
-
- def oneline_decode(chunk)
- needed_size = chunk[0..3].unpack("L").first
- if size == 0
- concat(" " * needed_size)
- else
- raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
- end
-
- @_decode_status ||= " " * ((needed_size / 8) + 1)
- @_known_chunks ||= []
-
-
- @_known_chunks.unshift(chunk)
-
- found_new_block = nil
- begin
- found_new_block = false
- @_known_chunks.each do |known_chunk|
- found_new_block = _decode_chunk_until_done(chunk, @_decode_status) || found_new_block
- end
- end while found_new_block
-
- return oneline_done
- end
-
- private
-
- def ensure_aux_blocks(size)
- _fill_aux_blocks() unless @_aux_blocks
- end
-
-end
From nobody at rubyforge.org Tue Dec 19 16:25:47 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Tue, 19 Dec 2006 16:25:47 -0500 (EST)
Subject: [Archipelago-submits] [114]
trunk/archipelago/lib/archipelago/oneline.rb: more stuff with
decoding
Message-ID: <20061219212547.E7C495240F92@rubyforge.org>
Revision: 114
Author: zond
Date: 2006-12-19 16:25:47 -0500 (Tue, 19 Dec 2006)
Log Message:
-----------
more stuff with decoding
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/oneline.rb
Modified: trunk/archipelago/lib/archipelago/oneline.rb
===================================================================
--- trunk/archipelago/lib/archipelago/oneline.rb 2006-12-18 16:45:19 UTC (rev 113)
+++ trunk/archipelago/lib/archipelago/oneline.rb 2006-12-19 21:25:47 UTC (rev 114)
@@ -30,9 +30,17 @@
class << self
private
+ #
+ # Get an F value for given epsilon value
+ #
def get_f(e)
Math.log(e ** 2 / 4) / Math.log(1 - (e / 2))
end
+ #
+ # Get a p distribution with a given name and epsilon value.
+ #
+ # Will return a C variable definition for this distribution.
+ #
def _get_p_distribution(name, e)
f = get_f(e)
rval = "double #{name}[] = {0.0,"
@@ -48,6 +56,11 @@
rval << "};\n"
return rval
end
+ #
+ # Get all the p distributions we want.
+ #
+ # Will return a C variable definition for this distribution.
+ #
def get_p_distribution
rval = ""
0.upto(E.size - 1) do |n|
@@ -78,6 +91,8 @@
#
# Get a random degree.
#
+ # Will define as many get_degree{n} functions as we need.
+ #
degree_methods = ""
0.upto(E.size - 1) do |n|
degree_methods += <len; tmp++) {
long degree;
+ // Seed with our seed and the index in the chunk.
srandom(seed + tmp);
- //printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
+ printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
+ // Get the degree of this chunk.
degree = degree_func(size);
+ // If it is degree 1 then we can deduce the data/aux block immediately.
if (degree == 1) {
long block_nr;
+ // Seed with our seed, the chunk index and the degree.
srandom(seed + tmp + degree);
+ // This block can be either from ourselves or from our aux blocks.
block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
- //printf(" %d", block_nr);
+ printf(" %d", block_nr);
+ // If it is not already known, then set it as known. Otherwise just log about its state.
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
got_new_block = 1;
- //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
+ printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
} else {
- //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
+ printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
}
} else {
+ // If it is NOT degree 1, then we go through all the blocks it is xored from
+ // and see if we have exactly one missing.
long missing_blocks;
long missing_block;
+ // Create the xor_sum with this block of the chunk.
char xor_sum = RSTRING(chunk)->ptr[tmp];
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
@@ -245,24 +283,27 @@
block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
- //printf(" %d", block_nr);
+ printf(" %d", block_nr);
+ // If the block we are looking at is known, then we decrement missing_blocks
+ // and continue with our xor_sum.
if (get_is_known(decode_status, block_nr)) {
missing_blocks--;
xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- //printf("!");
+ printf("!");
} else {
missing_block = block_nr;
- //printf("?");
+ printf("?");
}
}
+ // If exactly one block is missing, set is as the final xor_sum.
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
got_new_block = 1;
- //printf(" => [%d]=%d", missing_block, xor_sum);
+ printf(" => [%d]=%d", missing_block, xor_sum);
}
}
- //printf("\\n");
+ printf("\\n");
fflush(NULL);
}
@@ -281,25 +322,30 @@
char block;
char found_block;
+ // Seed with our seed and the index of this block in the chunk.
srandom(seed + index);
- //printf("creating check block %d:", index);
+ printf("creating check block %d:", index);
+ // Find [degree] blocks.
for (degree = degree_func(RSTRING(self)->len); degree > 0; degree--) {
long block_number;
char found_block;
+ // Seed with our seed, the index in the chunk, and the degree.
srandom(seed + index + degree);
block_number = RANDOM(RSTRING(self)->len + RSTRING(aux_blocks)->len);
+ // Depending on whether the block is in our data or our own, debug about it
+ // and remember what it was.
if (block_number < RSTRING(self)->len) {
found_block = RSTRING(self)->ptr[block_number];
- //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
+ printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
} else {
found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
- //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
+ printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
}
-
+ // Create the block by xoring.
if (empty_block) {
block = found_block;
empty_block = 0;
@@ -307,7 +353,7 @@
block = block ^ found_block;
}
}
- //printf(" => %d\\n", block);
+ printf(" => %d\\n", block);
return block;
}
EOC
@@ -327,20 +373,23 @@
srandom(RSTRING(self)->len);
+ // For each block of our data.
for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
- //printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
+ printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
+ // Create q blocks.
for (tmp2 = 0; tmp2 < q; tmp2++) {
long aux_block_nr = RANDOM(size);
- //printf(" [%d]", aux_block_nr);
+ printf(" [%d]", aux_block_nr);
+ // If this aux block is already initialized, just xor to it, otherwise set it.
if (initialized_aux_blocks[aux_block_nr]) {
aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
} else {
aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
initialized_aux_blocks[aux_block_nr] = 1;
}
- //printf(" => %d", aux_blocks[aux_block_nr]);
+ printf(" => %d", aux_blocks[aux_block_nr]);
}
- //printf("\\n");
+ printf("\\n");
}
rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
}
@@ -358,13 +407,16 @@
char chunk[chunk_size];
long (*degree_func)() = get_degree_func(RSTRING(self)->len);
+ // Seed with timeofday
gettimeofday(&tmp_timeval, NULL);
srandom(tmp_timeval.tv_usec);
+ // Get the seed for this chunk.
seed = random();
( (long *) chunk) [0] = seed;
( (long *) chunk) [1] = RSTRING(self)->len;
+ // Get the requested number of check blocks and append to this chunk.
for (tmp = 8; tmp < chunk_size; tmp++) {
chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func);
}
@@ -373,7 +425,7 @@
}
EOC
#
- # Create the @_aux_hash
+ # Create the @_aux_hash so that we know what data blocks each aux block represents.
#
builder.c <len);
+ // Go through all our blocks
for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ // And for each block q aux blocks.
for (tmp2 = 0; tmp2 < q; tmp2++) {
+ // And build an Array of the data blocks each aux block represents.
long aux_block_nr = RANDOM(size);
VALUE data_blocks_for_this_aux_block;
if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
@@ -397,12 +452,18 @@
rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2NUM(tmp));
}
}
-
+
+ // Then go through all our blocks again.
for (tmp = 0; tmp < size; tmp++) {
+ // Fetch the data blocks for this aux block.
VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
+ // Count them.
long number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
+ // Create a String that is 4 times the size.
VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
+ // And go through all q blocks per data block, again.
for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
+ // And make the String contain the data blocks for this aux block, as longs.
rb_str_modify(data_block_string);
( (long *) RSTRING(data_block_string)->ptr )[tmp2] = (long) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
get_func,
@@ -425,53 +486,63 @@
char got_new_block = 0;
VALUE get_func = rb_intern("[]");
+ // Go through all aux blocks.
for (tmp = 0; tmp < RSTRING(aux_blocks)->len; tmp++) {
+ // Only check those that are actually known.
if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
- //printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
+ printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
+ // Fetch the String defining what data blocks this aux block is made out of.
VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
+ // If it is only one data block, then its easy.
if (RSTRING(data_block_string)->len == 4) {
long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
- //printf(" %d", block_nr);
+ printf(" %d", block_nr);
+ // If it is not already known, then make it known.
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
got_new_block = 1;
- //printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
} else {
- //printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
}
} else {
+ // If it is several data blocks, then we just go through them all to see if only
+ // one of them is unknown.
long missing_blocks;
long missing_block;
+ // Initialize the xor_sum as this aux_block.
char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
- //printf(" %d", block_nr);
+ printf(" %d", block_nr);
+ // If it is a known data block, decrease missing_blocks and append to the xor_sum.
if (get_is_known(decode_status, block_nr)) {
missing_blocks--;
xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- //printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
+ printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
} else {
missing_block = block_nr;
- //printf("?");
+ printf("?");
}
}
+ // If only one data block was unknown, then just set it to the built up xor_sum.
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
got_new_block = 1;
- //printf(" => [%d]=%d", missing_block, xor_sum);
+ printf(" => [%d]=%d", missing_block, xor_sum);
}
}
}
}
- //printf("\\n");
+ printf("\\n");
fflush(NULL);
return got_new_block ? Qtrue : Qfalse;
@@ -517,6 +588,14 @@
@_decode_status.unpack("b*").first
end
+ def decode_level
+ ones = 0
+ decode_status.split(//).each do |s|
+ ones += 1 if s == "1"
+ end
+ ones.to_f / size.to_f
+ end
+
private
def get_aux_blocks
From nobody at rubyforge.org Wed Dec 20 09:38:41 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 09:38:41 -0500 (EST)
Subject: [Archipelago-submits] [115]
trunk/archipelago/lib/archipelago/oneline.rb: more decode stuff
Message-ID: <20061220143842.3D06652417EB@rubyforge.org>
Revision: 115
Author: zond
Date: 2006-12-20 09:38:41 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
more decode stuff
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/oneline.rb
Modified: trunk/archipelago/lib/archipelago/oneline.rb
===================================================================
--- trunk/archipelago/lib/archipelago/oneline.rb 2006-12-19 21:25:47 UTC (rev 114)
+++ trunk/archipelago/lib/archipelago/oneline.rb 2006-12-20 14:38:41 UTC (rev 115)
@@ -244,7 +244,7 @@
// Seed with our seed and the index in the chunk.
srandom(seed + tmp);
- printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
+ //printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
// Get the degree of this chunk.
degree = degree_func(size);
@@ -258,15 +258,15 @@
// This block can be either from ourselves or from our aux blocks.
block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
- printf(" %d", block_nr);
+ //printf(" %d", block_nr);
// If it is not already known, then set it as known. Otherwise just log about its state.
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
got_new_block = 1;
- printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
+ //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
} else {
- printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
+ //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
}
} else {
// If it is NOT degree 1, then we go through all the blocks it is xored from
@@ -283,27 +283,27 @@
block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
- printf(" %d", block_nr);
+ //printf(" %d", block_nr);
// If the block we are looking at is known, then we decrement missing_blocks
// and continue with our xor_sum.
if (get_is_known(decode_status, block_nr)) {
missing_blocks--;
xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- printf("!");
+ //printf("!");
} else {
missing_block = block_nr;
- printf("?");
+ //printf("?");
}
}
// If exactly one block is missing, set is as the final xor_sum.
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
got_new_block = 1;
- printf(" => [%d]=%d", missing_block, xor_sum);
+ //printf(" => [%d]=%d", missing_block, xor_sum);
}
}
- printf("\\n");
+ //printf("\\n");
fflush(NULL);
}
@@ -325,7 +325,7 @@
// Seed with our seed and the index of this block in the chunk.
srandom(seed + index);
- printf("creating check block %d:", index);
+ //printf("creating check block %d:", index);
// Find [degree] blocks.
for (degree = degree_func(RSTRING(self)->len); degree > 0; degree--) {
@@ -340,10 +340,10 @@
// and remember what it was.
if (block_number < RSTRING(self)->len) {
found_block = RSTRING(self)->ptr[block_number];
- printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
+ //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
} else {
found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
- printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
+ //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
}
// Create the block by xoring.
if (empty_block) {
@@ -353,7 +353,7 @@
block = block ^ found_block;
}
}
- printf(" => %d\\n", block);
+ //printf(" => %d\\n", block);
return block;
}
EOC
@@ -375,11 +375,11 @@
// For each block of our data.
for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
- printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
+ //printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
// Create q blocks.
for (tmp2 = 0; tmp2 < q; tmp2++) {
long aux_block_nr = RANDOM(size);
- printf(" [%d]", aux_block_nr);
+ //printf(" [%d]", aux_block_nr);
// If this aux block is already initialized, just xor to it, otherwise set it.
if (initialized_aux_blocks[aux_block_nr]) {
aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
@@ -387,9 +387,9 @@
aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
initialized_aux_blocks[aux_block_nr] = 1;
}
- printf(" => %d", aux_blocks[aux_block_nr]);
+ //printf(" => %d", aux_blocks[aux_block_nr]);
}
- printf("\\n");
+ //printf("\\n");
}
rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
}
@@ -491,7 +491,7 @@
// Only check those that are actually known.
if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
- printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
+ //printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
// Fetch the String defining what data blocks this aux block is made out of.
VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
@@ -500,15 +500,15 @@
if (RSTRING(data_block_string)->len == 4) {
long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
- printf(" %d", block_nr);
+ //printf(" %d", block_nr);
// If it is not already known, then make it known.
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
got_new_block = 1;
- printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ //printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
} else {
- printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ //printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
}
} else {
// If it is several data blocks, then we just go through them all to see if only
@@ -521,28 +521,28 @@
for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
- printf(" %d", block_nr);
+ //printf(" %d", block_nr);
// If it is a known data block, decrease missing_blocks and append to the xor_sum.
if (get_is_known(decode_status, block_nr)) {
missing_blocks--;
xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
+ //printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
} else {
missing_block = block_nr;
- printf("?");
+ //printf("?");
}
}
// If only one data block was unknown, then just set it to the built up xor_sum.
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
got_new_block = 1;
- printf(" => [%d]=%d", missing_block, xor_sum);
+ //printf(" => [%d]=%d", missing_block, xor_sum);
}
}
}
}
- printf("\\n");
+ //printf("\\n");
fflush(NULL);
return got_new_block ? Qtrue : Qfalse;
@@ -590,10 +590,10 @@
def decode_level
ones = 0
- decode_status.split(//).each do |s|
+ decode_status[0..(size + @_aux_blocks.size)].split(//).each do |s|
ones += 1 if s == "1"
end
- ones.to_f / size.to_f
+ ones.to_f / (size + @_aux_blocks.size).to_f
end
private
From nobody at rubyforge.org Wed Dec 20 10:10:51 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 10:10:51 -0500 (EST)
Subject: [Archipelago-submits] [116] trunk/archipelago: removed old crap
Message-ID: <20061220151051.93EDB524189A@rubyforge.org>
Revision: 116
Author: zond
Date: 2006-12-20 10:10:51 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
removed old crap
Removed Paths:
-------------
trunk/archipelago/lib/archipelago/bitstring.rb
trunk/archipelago/lib/archipelago/raider.rb
trunk/archipelago/tests/raider_benchmark.rb
trunk/archipelago/tests/raider_test.rb
trunk/archipelago/tests/string_benchmark.rb
trunk/archipelago/tests/string_test.rb
Deleted: trunk/archipelago/lib/archipelago/bitstring.rb
===================================================================
--- trunk/archipelago/lib/archipelago/bitstring.rb 2006-12-20 14:38:41 UTC (rev 115)
+++ trunk/archipelago/lib/archipelago/bitstring.rb 2006-12-20 15:10:51 UTC (rev 116)
@@ -1,104 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'rubygems'
-require 'inline'
-
-#
-# Adds a few methods to String, some using the inline gem.
-#
-class String
-
- inline do |builder|
- builder.c_raw <len != RSTRING(other)->len)
- rb_raise(rb_eRuntimeError, "xor argument must be of same size");
-
- return_value = rb_str_new(0, RSTRING(self)->len);
-
- for (i = 0; i < RSTRING(return_value)->len; i++)
- RSTRING(return_value)->ptr[i] = RSTRING(self)->ptr[i] ^ RSTRING(other)->ptr[i];
-
- return return_value;
-}
-EOC
-
- #
- # Returns a String that is self ^ +s+.
- #
- def xor(s)
- self.xor1(s)
- end
-
- alias :^ :xor
-
- builder.c_raw <len != RSTRING(other)->len)
- rb_raise(rb_eRuntimeError, "xor argument must be of same size");
-
- for (i = 0; i < RSTRING(self)->len; i++)
- RSTRING(self)->ptr[i] = RSTRING(self)->ptr[i] ^ RSTRING(other)->ptr[i];
-
- return self;
-}
-EOC
- end
-
- #
- # Returns whether self begins with +s+.
- #
- def begins?(s)
- self.index(s) == 0
- end
-
- #
- # Modifies self so that it becomes self ^ +s+.
- #
- def xor!(s)
- self.xor2(s)
- end
-
-end
Deleted: trunk/archipelago/lib/archipelago/raider.rb
===================================================================
--- trunk/archipelago/lib/archipelago/raider.rb 2006-12-20 14:38:41 UTC (rev 115)
+++ trunk/archipelago/lib/archipelago/raider.rb 2006-12-20 15:10:51 UTC (rev 116)
@@ -1,215 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'pp'
-
-module Archipelago
-
- #
- # A module providing methods to split any String into parts that can be rejoined to provide
- # the original String again.
- #
- module Raider
-
- #
- # Raised when the given parts are not enough to recreate the original data.
- #
- class NotEnoughBulkError < RuntimeError
- def initialize(parts)
- super("#{parts.inspect} is not enough to recreate the original data")
- end
- end
-
- #
- # A part of the original data.
- #
- class Bulk
- #
- # The data of this Bulk appended to its position
- # definition (a String of \000 and \001 defining what
- # parts of the original String were xored to get this data
- #
- attr_accessor :data
- #
- # The number of parts the original data were split into
- # to create the Bulk parts.
- #
- attr_accessor :size
- #
- # The size of the original data String.
- #
- attr_accessor :length
- #
- # The number of original data parts that were xored to
- # get this Bulk (ie the number of \001's in the beginning
- # of the dat of this Bulk.
- #
- attr_accessor :relevance
- def initialize(size, length)
- @size = size
- @length = length
- @data = nil
- end
- def <<(data)
- if @data
- @data.xor!(data)
- else
- @data = data.clone
- end
- end
- def <=>(other)
- @data <=> other.data
- end
- end
-
- #
- # Join +parts+ of Bulk together to form the String they were once created from.
- #
- def self.join(*parts)
- #
- # We know that this is not enough if the parts are empty or if they are fewer than the
- # minimum size needed to rejoin this data.
- #
- raise NotEnoughBulkError.new(parts) if parts.empty? or parts.size < parts.first.size
-
- #
- # For each bit of the data, create a String that is the beginning of
- # all parts having this bit as the first set bit, and another String that is the beginning
- # of all parts having ONLY this bit set.
- #
- # Then go through all parts and find one that has this bit as the first one
- # and all the others having at least this bit set.
- #
- # Then xor the one having this bit as the first one into each other part having at least
- # this bit set.
- #
- covered_bits = 0
- 0.upto(parts.first.size - 1) do |n|
- having_this_bit = []
- beginning_with_this_bit = nil
- beginning_marker = ""
- 0.upto(n - 1) do
- beginning_marker << "\000"
- end
- beginning_marker << "\001"
-
- parts.each do |part|
- if part.data.begins?(beginning_marker) && beginning_with_this_bit.nil?
- beginning_with_this_bit = part
- elsif part.data[n] == 1
- having_this_bit << part
- end
- end
- unless beginning_with_this_bit.nil?
- covered_bits += 1
- having_this_bit.each do |having|
- having << beginning_with_this_bit.data
- end
- end
- end
-
- #
- # Reject all parts having only 0 bits to get the ones
- # having one 1 bit each.
- #
- parts.reject! do |part|
- part.data.begins?("\000" * parts.first.size)
- end
-
- #
- # Raise an error if we didnt find all bits needed.
- #
- raise NotEnoughBulkError.new(parts) if parts.empty? || parts.size != parts.first.size
-
- #
- # Sort the bits having only one bit set in reverse order and collect their actual
- # data (throw away the bit padding), join them and truncate them at the wanted size.
- #
- return parts.sort do |a,b|
- b <=> a
- end.collect do |having|
- having.data[parts.first.size..-1]
- end.join[0...parts.first.length]
- end
-
- #
- # Split a String of +data+ into +parts+ pieces.
- #
- # You will get 2 ** +parts+ - 1 parts from the String,
- # and ( 2 ** +parts+ ) / 2 + 1 will always be enough to
- # recreate it using join.
- #
- def self.split(original_data, parts = 3)
- data = original_data.clone
-
- #
- # Remember the original size of data.
- #
- size = data.size
-
- #
- # Make sure that the data is divisible by +parts+.
- #
- if (rest = (data.size % parts)) != 0
- data << " " * (parts - rest)
- end
-
- #
- # Split the data into +parts+ bits and append a positional marker at the start of each.
- #
- data_parts = []
- 0.upto(parts - 1) do |n|
- pos_marker = ""
- 0.upto(parts - 1) do |m|
- if m == n
- pos_marker << "\001"
- else
- pos_marker << "\000"
- end
- end
- data_parts << (pos_marker + data[(n * (data.size / parts))...( (n + 1) * (data.size / parts) )])
- end
-
- return_parts = []
-
- #
- # Create (1 << +parts+) - 1 parts to return
- #
- 1.upto((1 << parts) - 1) do |n|
- this_part = Bulk.new(parts, size)
- relevance = 0
- #
- # For each of our data parts, if our number in the return part order
- # has the bit ouf our order number in the data part array set,
- # xor us into this return part.
- #
- 0.upto(data_parts.size - 1) do |m|
- if n & (1 << m) > 0
- this_part << data_parts[m]
- relevance += 1
- end
- end
- this_part.relevance = relevance
- return_parts << this_part
- end
-
- return return_parts
- end
-
- end
-
-end
Deleted: trunk/archipelago/tests/raider_benchmark.rb
===================================================================
--- trunk/archipelago/tests/raider_benchmark.rb 2006-12-20 14:38:41 UTC (rev 115)
+++ trunk/archipelago/tests/raider_benchmark.rb 2006-12-20 15:10:51 UTC (rev 116)
@@ -1,70 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class RaiderBenchmark < Test::Unit::TestCase
-
- def test_enough
- split_and_join(random_string(1000), 1000, 3)
- split_and_join(random_string(1000), 1000, 4)
- split_and_join(random_string(1000), 1000, 5)
- split_and_join(random_string(1000), 1000, 6)
- split_and_join(random_string(1000), 1000, 7)
- end
-
- def test_speed
- s = string(1024)
- bm("Raider.split([#{s.size} String], 3)/Raider.join") do
- p = Archipelago::Raider.split(s, 3)
- parts_to_use = []
- parts_to_use << p.delete_at(rand(p.size))
- parts_to_use << p.delete_at(rand(p.size))
- begin
- parts_to_use << p.delete_at(rand(p.size))
- assert_equal(s, Archipelago::Raider.join(*parts_to_use))
- rescue Archipelago::Raider::NotEnoughBulkError => e
- retry
- end
- end
- end
-
- private
-
- def string(n)
- s = ""
- n.times do
- s << (rand(27) + 65).chr
- end
- return s
- end
-
- def random_string(n)
- s = ""
- rand(n).times do
- s << (rand(27) + 65).chr
- end
- return s
- end
-
- def split_and_join(s, n, size)
- enough = []
- n.times do
- p = Archipelago::Raider.split(s, size)
- assert_equal((1 << size) - 1,p.size)
- parts_to_use = []
- 0.upto(size - 2) do
- parts_to_use << p.delete_at(rand(p.size))
- end
- begin
- parts_to_use << p.delete_at(rand(p.size))
- assert_equal(s, Archipelago::Raider.join(*parts_to_use))
- enough[parts_to_use.size] ||= 0
- enough[parts_to_use.size] += 1
- rescue Archipelago::Raider::NotEnoughBulkError => e
- retry
- end
- end
- puts "enough bits for #{size} parts"
- puts enough.inspect
- end
-
-end
Deleted: trunk/archipelago/tests/raider_test.rb
===================================================================
--- trunk/archipelago/tests/raider_test.rb 2006-12-20 14:38:41 UTC (rev 115)
+++ trunk/archipelago/tests/raider_test.rb 2006-12-20 15:10:51 UTC (rev 116)
@@ -1,47 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class RaiderTest < Test::Unit::TestCase
-
- def test_split_join
- 3.times do
- split_and_join(random_string(1000), 100, 3)
- end
- 3.times do
- split_and_join(random_string(1000), 100, 4)
- end
- 3.times do
- split_and_join(random_string(1000), 100, 5)
- end
- 3.times do
- split_and_join(random_string(1000), 100, 6)
- end
- 3.times do
- split_and_join(random_string(1000), 100, 7)
- end
- end
-
- private
-
- def random_string(n)
- s = ""
- rand(n).times do
- s << (rand(27) + 65).chr
- end
- return s
- end
-
- def split_and_join(s, n, size)
- n.times do
- p = Archipelago::Raider.split(s, size)
- assert_equal((1 << size) - 1,p.size)
- parts_to_use = []
- ((1 << (size - 1)) + 1).times do
- parts_to_use << p.delete_at(rand(p.size))
- end
-
- assert_equal(s, Archipelago::Raider.join(*parts_to_use))
- end
- end
-
-end
Deleted: trunk/archipelago/tests/string_benchmark.rb
===================================================================
--- trunk/archipelago/tests/string_benchmark.rb 2006-12-20 14:38:41 UTC (rev 115)
+++ trunk/archipelago/tests/string_benchmark.rb 2006-12-20 15:10:51 UTC (rev 116)
@@ -1,17 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class StringBenchmark < Test::Unit::TestCase
-
- def test_xor
- s = " " * (1 << 20)
- s2 = " " * (1 << 20)
- bm("String#xor! (size #{s.size})") do
- s.xor!(s2)
- end
- bm("String#^ (size #{s.size})") do
- s ^ s2
- end
- end
-
-end
Deleted: trunk/archipelago/tests/string_test.rb
===================================================================
--- trunk/archipelago/tests/string_test.rb 2006-12-20 14:38:41 UTC (rev 115)
+++ trunk/archipelago/tests/string_test.rb 2006-12-20 15:10:51 UTC (rev 116)
@@ -1,23 +0,0 @@
-
-require File.join(File.dirname(__FILE__), 'test_helper')
-
-class StringTest < Test::Unit::TestCase
-
- def test_begins
- assert("hej".begins?("he"))
- assert("hejsan".begins?("hejsan"))
- assert(!"epa".begins?("pa"))
- assert(!"epa".begins?("gnu"))
- end
-
- def test_xor
- assert("hej" ^ "hej" == "\000\000\000")
- assert("\003\003" ^ "\001\001" == "\002\002")
- s = "\002"
- assert(s ^ "\001" == "\003")
- assert_equal("\002", s)
- s.xor!("\001")
- assert_equal("\003", s)
- end
-
-end
From nobody at rubyforge.org Wed Dec 20 10:13:15 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 10:13:15 -0500 (EST)
Subject: [Archipelago-submits] [117] trunk: changed release version.
Message-ID: <20061220151315.9432552417E3@rubyforge.org>
Revision: 117
Author: zond
Date: 2006-12-20 10:13:15 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
changed release version. added return to a yield
Modified Paths:
--------------
trunk/archipelago/Rakefile
trunk/hyperactive/Rakefile
trunk/hyperactive/lib/hyperactive/record.rb
Modified: trunk/archipelago/Rakefile
===================================================================
--- trunk/archipelago/Rakefile 2006-12-20 15:10:51 UTC (rev 116)
+++ trunk/archipelago/Rakefile 2006-12-20 15:13:15 UTC (rev 117)
@@ -9,7 +9,7 @@
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "archipelago"
- s.version = "0.2.4"
+ s.version = "0.2.5"
s.author = "Martin Kihlgren"
s.email = "zond at troja dot ath dot cx"
s.summary = "A set of tools for distributed computing in ruby."
Modified: trunk/hyperactive/Rakefile
===================================================================
--- trunk/hyperactive/Rakefile 2006-12-20 15:10:51 UTC (rev 116)
+++ trunk/hyperactive/Rakefile 2006-12-20 15:13:15 UTC (rev 117)
@@ -9,7 +9,7 @@
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "hyperactive"
- s.version = "0.2.4"
+ s.version = "0.2.5"
s.author = "Martin Kihlgren"
s.email = "zond at troja dot ath dot cx"
s.summary = "A base class for persistent objects that uses archipelago for persistence. Useful for Ruby on Rails models for example."
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-20 15:10:51 UTC (rev 116)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-20 15:13:15 UTC (rev 117)
@@ -80,7 +80,7 @@
def with_transaction(transaction, &block)
@transaction = transaction
begin
- yield
+ return yield
ensure
@transaction = nil
end
From nobody at rubyforge.org Wed Dec 20 10:16:09 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 10:16:09 -0500 (EST)
Subject: [Archipelago-submits] [118] trunk/archipelago/pkg/: removed pkg
Message-ID: <20061220151609.A640F52417E3@rubyforge.org>
Revision: 118
Author: zond
Date: 2006-12-20 10:16:09 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
removed pkg
Removed Paths:
-------------
trunk/archipelago/pkg/
From nobody at rubyforge.org Wed Dec 20 10:17:00 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 10:17:00 -0500 (EST)
Subject: [Archipelago-submits] [119] trunk/archipelago/: added ignore to pkg
Message-ID: <20061220151700.648DA52417E3@rubyforge.org>
Revision: 119
Author: zond
Date: 2006-12-20 10:17:00 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
added ignore to pkg
Property Changed:
----------------
trunk/archipelago/
Property changes on: trunk/archipelago
___________________________________________________________________
Name: svn:ignore
+ pkg
From nobody at rubyforge.org Wed Dec 20 10:17:26 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 10:17:26 -0500 (EST)
Subject: [Archipelago-submits] [120] tags: created release_0_2_5
Message-ID: <20061220151726.35D5952417E3@rubyforge.org>
Revision: 120
Author: zond
Date: 2006-12-20 10:17:26 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
created release_0_2_5
Added Paths:
-----------
tags/release_0_2_5/
tags/release_0_2_5/archipelago/
Removed Paths:
-------------
tags/release_0_2_5/archipelago/
Copied: tags/release_0_2_5 (from rev 118, trunk)
Copied: tags/release_0_2_5/archipelago (from rev 119, trunk/archipelago)
From nobody at rubyforge.org Wed Dec 20 11:23:17 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 11:23:17 -0500 (EST)
Subject: [Archipelago-submits] [121] trunk/archipelago: removed automatic
requiring of everything in archipelago
Message-ID: <20061220162317.D694252417A7@rubyforge.org>
Revision: 121
Author: zond
Date: 2006-12-20 11:23:17 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
removed automatic requiring of everything in archipelago
Modified Paths:
--------------
trunk/archipelago/lib/archipelago.rb
trunk/archipelago/tests/test_helper.rb
Modified: trunk/archipelago/lib/archipelago.rb
===================================================================
--- trunk/archipelago/lib/archipelago.rb 2006-12-20 15:17:26 UTC (rev 120)
+++ trunk/archipelago/lib/archipelago.rb 2006-12-20 16:23:17 UTC (rev 121)
@@ -16,15 +16,3 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
$: << File.dirname(File.expand_path(__FILE__))
-
-require 'archipelago/bitstring'
-require 'archipelago/oneliner'
-require 'archipelago/raider'
-require 'archipelago/disco'
-require 'archipelago/current'
-require 'archipelago/tranny'
-require 'archipelago/treasure'
-require 'archipelago/client'
-require 'archipelago/pirate'
-require 'archipelago/cove'
-require 'archipelago/exxon'
Modified: trunk/archipelago/tests/test_helper.rb
===================================================================
--- trunk/archipelago/tests/test_helper.rb 2006-12-20 15:17:26 UTC (rev 120)
+++ trunk/archipelago/tests/test_helper.rb 2006-12-20 16:23:17 UTC (rev 121)
@@ -9,6 +9,8 @@
require 'drb'
require 'test/unit'
require 'archipelago'
+require 'archipelago/treasure'
+require 'archipelago/pirate'
require 'benchmark'
require 'socket'
require 'ipaddr'
From nobody at rubyforge.org Wed Dec 20 12:19:10 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 20 Dec 2006 12:19:10 -0500 (EST)
Subject: [Archipelago-submits] [122] trunk/archipelago: reworked how
Captain.transaction does its thing.
Message-ID: <20061220171911.2365852417E9@rubyforge.org>
Revision: 122
Author: zond
Date: 2006-12-20 12:19:10 -0500 (Wed, 20 Dec 2006)
Log Message:
-----------
reworked how Captain.transaction does its thing. updated tests.
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/pirate.rb
trunk/archipelago/tests/pirate_test.rb
Modified: trunk/archipelago/lib/archipelago/pirate.rb
===================================================================
--- trunk/archipelago/lib/archipelago/pirate.rb 2006-12-20 16:23:17 UTC (rev 121)
+++ trunk/archipelago/lib/archipelago/pirate.rb 2006-12-20 17:19:10 UTC (rev 122)
@@ -175,21 +175,20 @@
#
# Will abort! the transaction if any exception is raised.
#
- def transaction(&block) #:yields: transaction
+ def transaction(&block) #:yields: a clone of this Archipelago::Pirate::Captain with the given transaction as default @transaction.
raise NoTransactionManagerAvailableException.new(self) if @trannies.empty?
- @transaction = @trannies.values.first[:service].begin
+ my_clone = self.begin
+ transa = my_clone.active_transaction
begin
begin
- return yield(@transaction)
+ return yield(my_clone)
ensure
- raise CommitFailedException.new(self, @transaction) unless @transaction.commit! == :commited
+ raise CommitFailedException.new(my_clone, transa) unless transa.commit! == :commited
end
rescue Exception => e
- @transaction.abort! unless @transaction.state == :aborted
+ transa.abort! unless transa.state == :aborted
raise e
- ensure
- @transaction = nil
end
end
@@ -204,17 +203,27 @@
#
# Commit the transaction we are a member of and forget about it.
#
+ # Returns the new state of the transaction.
+ #
def commit!
- @transaction.commit!
- @transaction = nil
+ begin
+ return @transaction.commit!
+ ensure
+ @transaction = nil
+ end
end
#
# Abort the transaction we are a member of and forget about it.
#
+ # Returns the new state of the transaction.
+ #
def abort!
- @transaction.abort!
- @transaction = nil
+ begin
+ @transaction.abort!
+ ensure
+ @transaction = nil
+ end
end
#
Modified: trunk/archipelago/tests/pirate_test.rb
===================================================================
--- trunk/archipelago/tests/pirate_test.rb 2006-12-20 16:23:17 UTC (rev 121)
+++ trunk/archipelago/tests/pirate_test.rb 2006-12-20 17:19:10 UTC (rev 122)
@@ -122,18 +122,18 @@
end
trans = nil
assert_raise(Archipelago::Pirate::CommitFailedException) do
- @p.transaction do |trans|
- assert_equal(trans.transaction_id, @p.active_transaction.transaction_id)
- @p["hehu"] = "haha"
+ @p.transaction do |copy|
+ trans = copy.active_transaction
+ copy["hehu"] = "haha"
assert(!p2.include?("hehu"))
assert(!p2.include?("hehu", nil))
assert_equal(nil, p2.active_transaction)
trans2 = nil
- p2.transaction do |trans2|
- assert_equal(trans2.transaction_id, p2.active_transaction.transaction_id)
- p2["hehu"] = "hoj"
- assert_equal("haha", @p["hehu"])
- assert_equal("hoj", @p["hehu", trans2])
+ p2.transaction do |copy2|
+ trans2 = copy2.active_transaction
+ copy2["hehu"] = "hoj"
+ assert_equal("haha", copy["hehu"])
+ assert_equal("hoj", copy["hehu", trans2])
end
assert_equal(:commited, trans2.state)
assert_equal(:active, trans.state)
From nobody at rubyforge.org Fri Dec 22 15:55:29 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 15:55:29 -0500 (EST)
Subject: [Archipelago-submits] [123] trunk: initial commit of all the new
gemmy stuff
Message-ID: <20061222205529.694C25241CE7@rubyforge.org>
Revision: 123
Author: zond
Date: 2006-12-22 15:55:28 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
initial commit of all the new gemmy stuff
Added Paths:
-----------
trunk/oneliner/
trunk/oneliner/GPL-2
trunk/oneliner/README
trunk/oneliner/Rakefile
trunk/oneliner/lib/
trunk/oneliner/lib/oneliner/
trunk/oneliner/lib/oneliner/superstring.rb
trunk/oneliner/lib/oneliner.rb
Added: trunk/oneliner/GPL-2
===================================================================
--- trunk/oneliner/GPL-2 (rev 0)
+++ trunk/oneliner/GPL-2 2006-12-22 20:55:28 UTC (rev 123)
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
Added: trunk/oneliner/README
===================================================================
--- trunk/oneliner/README (rev 0)
+++ trunk/oneliner/README 2006-12-22 20:55:28 UTC (rev 123)
@@ -0,0 +1,9 @@
+= This is Oneliner, an online code implementation for Ruby.
+
+== Dependencies:
+
+== Sub packages:
+
+== Usage:
+
+== Examples:
Added: trunk/oneliner/Rakefile
===================================================================
--- trunk/oneliner/Rakefile (rev 0)
+++ trunk/oneliner/Rakefile 2006-12-22 20:55:28 UTC (rev 123)
@@ -0,0 +1,60 @@
+
+require 'rake'
+require 'rake/testtask'
+require 'rubygems'
+Gem::manage_gems
+require 'rake/gempackagetask'
+
+
+spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = "oneliner"
+ s.version = "0.2.5"
+ s.author = "Martin Kihlgren"
+ s.email = "zond at troja dot ath dot cx"
+ s.summary = "An online code implementation for ruby."
+ s.files = FileList['lib/**/*.rb', 'tests/*', 'GPL-2'].to_a
+ s.require_path = "lib"
+ s.extra_deps << ['RubyInline', '>= 3.6.2']
+ s.autorequire = "oneliner"
+ s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
+ s.has_rdoc = true
+ s.rdoc_options << '--line-numbers'
+ s.rdoc_options << '--inline-source'
+ s.extra_rdoc_files = ["README"]
+end
+
+
+SOURCE_FILES = FileList.new do |fl|
+ [ "lib", "tests" ].each do |dir|
+ fl.include "#{dir}/**/*"
+ end
+ fl.include "Rakefile"
+end
+
+Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.need_tar = true
+end
+
+task :default => [:units] do
+end
+
+desc "Run all tests"
+Rake::TestTask.new(:units) do |t|
+ t.pattern = 'tests/*_test.rb'
+ t.verbose = true
+ t.warning = true
+end
+
+desc "Run all benchmarks"
+Rake::TestTask.new(:bench) do |t|
+ t.pattern = 'tests/*_benchmark.rb'
+ t.verbose = true
+ t.warning = true
+end
+
+desc "Package a gem from the source"
+task :gem => "pkg/#{spec.name}-#{spec.version}.gem" do
+ puts "generated latest version"
+end
+
Added: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb (rev 0)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-22 20:55:28 UTC (rev 123)
@@ -0,0 +1,655 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'rubygems'
+require 'inline'
+require 'pp'
+
+module Oneliner
+
+ #
+ # Adds a few methods to String, some using the inline gem.
+ #
+ class SuperString < String
+
+ E = [0.1, 0.01]
+ Q = [6, 3]
+ THRESHOLDS = [1024]
+
+ class << self
+ private
+ #
+ # Get an F value for given epsilon value
+ #
+ def get_f(e)
+ Math.log(e ** 2 / 4) / Math.log(1 - (e / 2))
+ end
+ #
+ # Get a p distribution with a given name and epsilon value.
+ #
+ # Will return a C variable definition for this distribution.
+ #
+ def _get_p_distribution(name, e)
+ f = get_f(e)
+ rval = "double #{name}[] = {0.0,"
+ p1 = 1 - ( (1 + (1 / f) ) / (1 + e) )
+ 1.upto(f) do |n|
+ if n == 1
+ rval << "#{p1}"
+ else
+ rval << "#{( ( 1 - p1 ) * f ) / ( ( f - 1 ) * n * ( n - 1 ) )}"
+ end
+ rval << "," unless n + 1 > f
+ end
+ rval << "};\n"
+ return rval
+ end
+ #
+ # Get all the p distributions we want.
+ #
+ # Will return a C variable definition for this distribution.
+ #
+ def get_p_distribution
+ rval = ""
+ 0.upto(E.size - 1) do |n|
+ rval << _get_p_distribution("P#{n}", E[n])
+ end
+ return rval
+ end
+ end
+
+ inline do |builder|
+ #
+ # We need math.h
+ #
+ builder.include("")
+ #
+ # We need sys/time.h
+ #
+ builder.include("")
+ #
+ # We need openssl/aes.h
+ #
+ builder.include("")
+ #
+ # Define the p distribution array so that it is easily accessible.
+ #
+ builder.prefix(get_p_distribution)
+ #
+ # Define a sane random number generator.
+ #
+ builder.prefix("#define RAND (((double)random())/((double)RAND_MAX+1))")
+ builder.prefix("#define RANDOM(n) (random() % (n))")
+ builder.prefix("#define RANDOMNESS_BUFFER_SIZE 16")
+ #
+ # Get a random degree.
+ #
+ # Will define as many get_degree{n} functions as we need.
+ #
+ degree_methods = ""
+ 0.upto(E.size - 1) do |n|
+ degree_methods += < 0.0) {
+ rval ++;
+ d = d - P#{n}[rval];
+ }
+ if (rval > size)
+ return size;
+ else
+ return rval;
+}
+EOC
+ end
+ builder.prefix(degree_methods)
+ #
+ # Get the function to produce random degrees for us.
+ #
+ # Will go through our THRESHOLDS and return the proper degree-method.
+ #
+ get_degree_func = <ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
+}
+
+static void
+set_is_known(VALUE decode_status, long block_number)
+{
+ long byte_in_status = block_number / 8;
+ char bit_in_byte = 1 << (block_number % 8);
+ rb_str_modify(decode_status);
+ RSTRING(decode_status)->ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
+}
+
+static void
+set_value(VALUE aux_blocks, long index, char value, VALUE self, VALUE decode_status)
+{
+ if (index < RSTRING(self)->len) {
+ rb_str_modify(self);
+ RSTRING(self)->ptr[index] = value;
+ set_is_known(decode_status, index);
+ } else {
+ rb_str_modify(aux_blocks);
+ RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len] = value;
+ set_is_known(decode_status, index);
+ }
+}
+
+static char
+get_value(VALUE aux_blocks, long index, VALUE self)
+{
+ if (index < RSTRING(self)->len) {
+ return RSTRING(self)->ptr[index];
+ } else {
+ return RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len];
+ }
+}
+
+static char
+get_check_block(VALUE self, long seed, long index, VALUE aux_blocks, long (*degree_func)(long))
+{
+ long degree;
+ int empty_block = 1;
+ char block;
+ char found_block;
+
+ //printf("creating check block %d:", index);
+
+ // Find [degree] blocks.
+ for (degree = degree_func(RSTRING(self)->len); degree > 0; degree--) {
+ long block_number;
+ char found_block;
+
+ block_number = RANDOM(RSTRING(self)->len + RSTRING(aux_blocks)->len);
+ // Depending on whether the block is in our data or our own, debug about it
+ // and remember what it was.
+ if (block_number < RSTRING(self)->len) {
+ found_block = RSTRING(self)->ptr[block_number];
+ //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
+ } else {
+ found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
+ //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
+ }
+ // Create the block by xoring.
+ if (empty_block) {
+ block = found_block;
+ empty_block = 0;
+ } else {
+ block = block ^ found_block;
+ }
+ }
+ //printf(" => %d\\n", block);
+ return block;
+}
+EOC
+ #
+ # Decode the given chunk until we dont get any new
+ # data from it.
+ #
+ builder.c <ptr )[0];
+ long size = ( (long *) RSTRING(chunk)->ptr )[1];
+ long tmp, tmp2;
+ char got_new_block = 0;
+ long (*degree_func)() = get_degree_func(size);
+
+ // Seed with our seed.
+ srandom(seed);
+
+ // Go through the chunk.
+ for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
+ long degree;
+
+ //printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
+
+ // Get the degree of this chunk.
+ degree = degree_func(size);
+ // If it is degree 1 then we can deduce the data/aux block immediately.
+ if (degree == 1) {
+ long block_nr;
+
+ // This block can be either from ourselves or from our aux blocks.
+ block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
+
+ //printf(" %d", block_nr);
+
+ // If it is not already known, then set it as known. Otherwise just log about its state.
+ if (!get_is_known(decode_status, block_nr)) {
+ set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
+ } else {
+ //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
+ }
+ } else {
+ // If it is NOT degree 1, then we go through all the blocks it is xored from
+ // and see if we have exactly one missing.
+ long missing_blocks;
+ long missing_block;
+ // Create the xor_sum with this block of the chunk.
+ char xor_sum = RSTRING(chunk)->ptr[tmp];
+
+ for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
+ long block_nr;
+
+ block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
+
+ //printf(" %d", block_nr);
+
+ // If the block we are looking at is known, then we decrement missing_blocks
+ // and continue with our xor_sum.
+ if (get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ //printf("!");
+ } else {
+ missing_block = block_nr;
+ //printf("?");
+ }
+ }
+ // If exactly one block is missing, set is as the final xor_sum.
+ if (missing_blocks == 1) {
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", missing_block, xor_sum);
+ }
+ }
+ //printf("\\n");
+ fflush(NULL);
+ }
+
+ return got_new_block ? Qtrue : Qfalse;
+}
+EOC
+ #
+ # Fill our aux blocks with the proper data.
+ #
+ builder.c <len);
+
+ // For each block of our data.
+ for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ //printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
+ // Create q blocks.
+ for (tmp2 = 0; tmp2 < q; tmp2++) {
+ long aux_block_nr = RANDOM(size);
+ //printf(" [%d]", aux_block_nr);
+ // If this aux block is already initialized, just xor to it, otherwise set it.
+ if (initialized_aux_blocks[aux_block_nr]) {
+ aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
+ } else {
+ aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
+ initialized_aux_blocks[aux_block_nr] = 1;
+ }
+ //printf(" => %d", aux_blocks[aux_block_nr]);
+ }
+ //printf("\\n");
+ }
+ rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
+}
+EOC
+ #
+ # Returns a chunk of coded data for a given message.
+ #
+ builder.c <len);
+
+ // Seed with timeofday
+ gettimeofday(&tmp_timeval, NULL);
+ srandom(tmp_timeval.tv_usec);
+ // Get the seed for this chunk.
+ seed = random();
+
+ ( (long *) chunk) [0] = seed;
+ ( (long *) chunk) [1] = RSTRING(self)->len;
+
+ // Seed with our seed and the index of this block in the chunk.
+ srandom(seed);
+
+ // Get the requested number of check blocks and append to this chunk.
+ for (tmp = 8; tmp < chunk_size; tmp++) {
+ chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func);
+ }
+
+ return rb_str_new(chunk, chunk_size);
+}
+EOC
+ #
+ # Create the @_aux_hash so that we know what data blocks each aux block represents.
+ #
+ builder.c <len);
+
+ // Go through all our blocks
+ for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ // And for each block q aux blocks.
+ for (tmp2 = 0; tmp2 < q; tmp2++) {
+ // And build an Array of the data blocks each aux block represents.
+ long aux_block_nr = RANDOM(size);
+ VALUE data_blocks_for_this_aux_block;
+ if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
+ rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
+ rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2NUM(tmp));
+ }
+ }
+
+ // Then go through all our blocks again.
+ for (tmp = 0; tmp < size; tmp++) {
+ // Fetch the data blocks for this aux block.
+ VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
+ // Count them.
+ long number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
+ // Create a String that is 4 times the size.
+ VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
+ // And go through all q blocks per data block, again.
+ for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
+ // And make the String contain the data blocks for this aux block, as longs.
+ rb_str_modify(data_block_string);
+ ( (long *) RSTRING(data_block_string)->ptr )[tmp2] = (long) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
+ get_func,
+ 1,
+ INT2NUM(tmp2)));
+ }
+ rb_funcall(aux_ary, set_func, 2, INT2NUM(tmp), data_block_string);
+ }
+ rb_ivar_set(self, rb_intern("@_aux_hash"), aux_ary);
+}
+EOC
+ #
+ # Returns whether the decoding is done.
+ #
+ builder.c <len - 1); tmp++) {
+ if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != 255) {
+ return Qfalse;
+ }
+ }
+ for (tmp = 0; tmp < (RSTRING(self)->len % 8); tmp++) {
+ if (! ( (unsigned char) RSTRING(self)->ptr[tmp] ) & (1 << tmp)) {
+ return Qfalse;
+ }
+ }
+ return Qtrue;
+}
+EOC
+ #
+ # Try to decode our data and aux blocks until we dont get any more data.
+ #
+ builder.c <len; tmp++) {
+ // Only check those that are actually known.
+ if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
+
+ //printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
+
+ // Fetch the String defining what data blocks this aux block is made out of.
+ VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
+
+ // If it is only one data block, then its easy.
+ if (RSTRING(data_block_string)->len == 4) {
+ long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
+
+ //printf(" %d", block_nr);
+
+ // If it is not already known, then make it known.
+ if (!get_is_known(decode_status, block_nr)) {
+ set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ } else {
+ //printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
+ }
+ } else {
+ // If it is several data blocks, then we just go through them all to see if only
+ // one of them is unknown.
+ long missing_blocks;
+ long missing_block;
+ // Initialize the xor_sum as this aux_block.
+ char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
+
+ for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
+ long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
+
+ //printf(" %d", block_nr);
+
+ // If it is a known data block, decrease missing_blocks and append to the xor_sum.
+ if (get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ //printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
+ } else {
+ missing_block = block_nr;
+ //printf("?");
+ }
+ }
+ // If only one data block was unknown, then just set it to the built up xor_sum.
+ if (missing_blocks == 1) {
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ got_new_block = 1;
+ //printf(" => [%d]=%d", missing_block, xor_sum);
+ }
+ }
+ }
+ }
+ //printf("\\n");
+ fflush(NULL);
+
+ return got_new_block ? Qtrue : Qfalse;
+}
+EOC
+ end
+
+ def oneline_encode(chunk_size)
+ ensure_aux_blocks
+ return _get_chunk(chunk_size, @_aux_blocks)
+ end
+
+ def oneline_decode(chunk)
+
+ needed_size = chunk[4..7].unpack("L").first
+ if size == 0
+ concat("\000" * needed_size)
+ elsif size != needed_size
+ raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
+ end
+
+ @_decode_status ||= "\000" * (((needed_size + get_aux_blocks) / 8) + 1)
+ @_known_chunks ||= []
+ @_aux_blocks ||= "\000" * get_aux_blocks
+
+ found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks)
+ do_decode if found_new_block
+
+ @_known_chunks.unshift(chunk)
+
+ nil while do_decode
+
+ return oneline_done
+ end
+
+ def oneline_done
+ return nil unless @_decode_status
+ return _oneline_done(@_decode_status)
+ end
+
+ def decode_status
+ return nil unless @_decode_status
+ @_decode_status.unpack("b*").first
+ end
+
+ def decode_level
+ ones = 0
+ decode_status[0..(size + @_aux_blocks.size)].split(//).each do |s|
+ ones += 1 if s == "1"
+ end
+ ones.to_f / (size + @_aux_blocks.size).to_f
+ end
+
+ private
+
+ def get_aux_blocks
+ (self.size * (get_q * get_e * 0.55)).ceil
+ end
+
+ def get_q
+ 0.upto(THRESHOLDS.size - 1) do |n|
+ if size < THRESHOLDS[n]
+ return Q[n]
+ end
+ end
+ return Q.last
+ end
+
+ def do_decode
+ found_new_block = false
+ @_known_chunks.each do |known_chunk|
+ found_new_block = _decode_chunk(known_chunk, @_decode_status, @_aux_blocks) || found_new_block
+ end
+ ensure_aux_hash
+ found_new_block = _aux_decode(@_decode_status, @_aux_blocks, @_aux_hash) || found_new_block
+ return found_new_block
+ end
+
+ def get_e
+ 0.upto(THRESHOLDS.size - 1) do |n|
+ if size < THRESHOLDS[n]
+ return E[n]
+ end
+ end
+ return E.last
+ end
+
+ def ensure_aux_blocks
+ _fill_aux_blocks(get_aux_blocks, get_q) unless @_aux_blocks
+ end
+
+ def ensure_aux_hash
+ _fill_aux_hash(get_q, get_aux_blocks) unless @_aux_hash
+ end
+
+ end
+
+end
Added: trunk/oneliner/lib/oneliner.rb
===================================================================
--- trunk/oneliner/lib/oneliner.rb (rev 0)
+++ trunk/oneliner/lib/oneliner.rb 2006-12-22 20:55:28 UTC (rev 123)
@@ -0,0 +1,19 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+$: << File.dirname(File.expand_path(__FILE__))
+
From nobody at rubyforge.org Fri Dec 22 17:57:52 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 17:57:52 -0500 (EST)
Subject: [Archipelago-submits] [124] trunk/oneliner: working! woot!
Message-ID: <20061222225752.509995241A7E@rubyforge.org>
Revision: 124
Author: zond
Date: 2006-12-22 17:57:52 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
working! woot!
Modified Paths:
--------------
trunk/oneliner/Rakefile
trunk/oneliner/lib/oneliner/superstring.rb
Added Paths:
-----------
trunk/oneliner/tests/
trunk/oneliner/tests/superstring_benchmark.rb
trunk/oneliner/tests/superstring_test.rb
trunk/oneliner/tests/test_helper.rb
Modified: trunk/oneliner/Rakefile
===================================================================
--- trunk/oneliner/Rakefile 2006-12-22 20:55:28 UTC (rev 123)
+++ trunk/oneliner/Rakefile 2006-12-22 22:57:52 UTC (rev 124)
@@ -15,7 +15,7 @@
s.summary = "An online code implementation for ruby."
s.files = FileList['lib/**/*.rb', 'tests/*', 'GPL-2'].to_a
s.require_path = "lib"
- s.extra_deps << ['RubyInline', '>= 3.6.2']
+ s.add_dependency('RubyInline', '>= 3.6.2')
s.autorequire = "oneliner"
s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
s.has_rdoc = true
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-22 20:55:28 UTC (rev 123)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-22 22:57:52 UTC (rev 124)
@@ -82,6 +82,10 @@
#
builder.include("")
#
+ # We need limits.h
+ #
+ builder.include("")
+ #
# We need openssl/aes.h
#
builder.include("")
@@ -92,9 +96,15 @@
#
# Define a sane random number generator.
#
- builder.prefix("#define RAND (((double)random())/((double)RAND_MAX+1))")
- builder.prefix("#define RANDOM(n) (random() % (n))")
+ builder.prefix("static long aes_random(char *ctx);");
builder.prefix("#define RANDOMNESS_BUFFER_SIZE 16")
+ builder.prefix("#define RANDOMNESS_MAX ")
+# builder.prefix("#define SEED(ctx, s) srandom(s)")
+# builder.prefix("#define RAND(ctx) (((double)random())/((double)RAND_MAX+1))")
+# builder.prefix("#define RANDOM(ctx, n) (random() % (n))")
+ builder.prefix("#define SEED(ctx, s) aes_seed_context(ctx, s)")
+ builder.prefix("#define RAND(ctx) (((double) ((unsigned long) aes_random(ctx)))/((double)ULONG_MAX))")
+ builder.prefix("#define RANDOM(ctx, n) (( (unsigned long) aes_random(ctx)) % (n))")
#
# Get a random degree.
#
@@ -104,14 +114,16 @@
0.upto(E.size - 1) do |n|
degree_methods += <ptr) - P#{n}[rval];
while (d > 0.0) {
rval ++;
d = d - P#{n}[rval];
}
+ //printf("hehu: %f\\n", d);
+ fflush(NULL);
if (rval > size)
return size;
else
@@ -126,7 +138,7 @@
# Will go through our THRESHOLDS and return the proper degree-method.
#
get_degree_func = <len); degree > 0; degree--) {
+ for (degree = degree_func(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
long block_number;
char found_block;
- block_number = RANDOM(RSTRING(self)->len + RSTRING(aux_blocks)->len);
+ block_number = RANDOM(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len + RSTRING(aux_blocks)->len);
// Depending on whether the block is in our data or our own, debug about it
// and remember what it was.
if (block_number < RSTRING(self)->len) {
@@ -262,6 +280,44 @@
}
EOC
#
+ # A shortcut to the random functions for testing.
+ #
+ builder.c <ptr )[1];
long tmp, tmp2;
char got_new_block = 0;
- long (*degree_func)() = get_degree_func(size);
+ long (*degree_func)(long, VALUE) = get_degree_func(size);
+ VALUE rnd_ctx = get_aes_context();
// Seed with our seed.
- srandom(seed);
+ SEED(RSTRING(rnd_ctx)->ptr, seed);
// Go through the chunk.
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
@@ -285,13 +342,13 @@
//printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
// Get the degree of this chunk.
- degree = degree_func(size);
+ degree = degree_func(size, rnd_ctx);
// If it is degree 1 then we can deduce the data/aux block immediately.
if (degree == 1) {
long block_nr;
// This block can be either from ourselves or from our aux blocks.
- block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
//printf(" %d", block_nr);
@@ -314,7 +371,7 @@
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
long block_nr;
- block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
//printf(" %d", block_nr);
@@ -353,18 +410,19 @@
char aux_blocks[size];
char initialized_aux_blocks[size];
long tmp, tmp2;
+ VALUE rnd_ctx = get_aes_context();
for (tmp = 0; tmp < size; tmp++)
initialized_aux_blocks[tmp] = 0;
- srandom(RSTRING(self)->len);
+ SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
// For each block of our data.
for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
//printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
// Create q blocks.
for (tmp2 = 0; tmp2 < q; tmp2++) {
- long aux_block_nr = RANDOM(size);
+ long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
//printf(" [%d]", aux_block_nr);
// If this aux block is already initialized, just xor to it, otherwise set it.
if (initialized_aux_blocks[aux_block_nr]) {
@@ -391,7 +449,8 @@
long seed;
struct timeval tmp_timeval;
char chunk[chunk_size];
- long (*degree_func)() = get_degree_func(RSTRING(self)->len);
+ long (*degree_func)(long, VALUE) = get_degree_func(RSTRING(self)->len);
+ VALUE rnd_ctx = get_aes_context();
// Seed with timeofday
gettimeofday(&tmp_timeval, NULL);
@@ -403,11 +462,11 @@
( (long *) chunk) [1] = RSTRING(self)->len;
// Seed with our seed and the index of this block in the chunk.
- srandom(seed);
+ SEED(RSTRING(rnd_ctx)->ptr, seed);
// Get the requested number of check blocks and append to this chunk.
for (tmp = 8; tmp < chunk_size; tmp++) {
- chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func);
+ chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func, rnd_ctx);
}
return rb_str_new(chunk, chunk_size);
@@ -426,15 +485,16 @@
VALUE get_func = rb_intern("[]");
VALUE push_func = rb_intern("<<");
VALUE size_func = rb_intern("size");
+ VALUE rnd_ctx = get_aes_context();
- srandom(RSTRING(self)->len);
+ SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
// Go through all our blocks
for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
// And for each block q aux blocks.
for (tmp2 = 0; tmp2 < q; tmp2++) {
// And build an Array of the data blocks each aux block represents.
- long aux_block_nr = RANDOM(size);
+ long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
VALUE data_blocks_for_this_aux_block;
if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
@@ -643,10 +703,12 @@
end
def ensure_aux_blocks
+ @_aux_blocks ||= nil
_fill_aux_blocks(get_aux_blocks, get_q) unless @_aux_blocks
end
def ensure_aux_hash
+ @_aux_hash ||= nil
_fill_aux_hash(get_q, get_aux_blocks) unless @_aux_hash
end
Added: trunk/oneliner/tests/superstring_benchmark.rb
===================================================================
--- trunk/oneliner/tests/superstring_benchmark.rb (rev 0)
+++ trunk/oneliner/tests/superstring_benchmark.rb 2006-12-22 22:57:52 UTC (rev 124)
@@ -0,0 +1,36 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class SuperStringTest < Test::Unit::TestCase
+
+ def test_decoding
+ puts "required for 1024 blocks: #{required(10, 1024)}"
+ puts "required for 2048 blocks: #{required(10, 2048)}"
+ puts "required for 4096 blocks: #{required(10, 4096)}"
+ puts "required for 8096 blocks: #{required(10, 8096)}"
+ end
+
+ private
+
+ def required(n, size)
+ total_req = 0
+ n.times do
+ s = Oneliner::SuperString.new
+ s2 = Oneliner::SuperString.new(" " * 1024)
+ total_req += measure_required(s, s2)
+ end
+ return total_req / n.to_f
+ end
+
+ def measure_required(dest, source)
+ total = source.size.to_f
+ used = source.size.to_f
+ dest.oneline_decode(source.oneline_encode(source.size))
+ while (!dest.oneline_decode(source.oneline_encode(source.size.to_f * 0.1)))
+ used += (source.size.to_f * 0.1)
+ end
+ return used/total
+ end
+
+
+end
Added: trunk/oneliner/tests/superstring_test.rb
===================================================================
--- trunk/oneliner/tests/superstring_test.rb (rev 0)
+++ trunk/oneliner/tests/superstring_test.rb 2006-12-22 22:57:52 UTC (rev 124)
@@ -0,0 +1,28 @@
+
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class SuperStringTest < Test::Unit::TestCase
+
+ def test_randomness
+ s = Oneliner::SuperString.new
+ c = s._get_aes_context
+ 1000.times do
+ r = s._macro_rand(c)
+ assert(r >= 0)
+ assert(r < 1)
+ r2 = s._macro_random(c, 13)
+ assert(r2 >= 0)
+ assert(r2 < 13)
+ end
+ end
+
+ def test_decoding
+ 10.times do
+ s = Oneliner::SuperString.new
+ s2 = Oneliner::SuperString.new(" " * 1024)
+ assert(s.oneline_decode(s2.oneline_encode(2048)))
+ assert_equal(s2, s)
+ end
+ end
+
+end
Added: trunk/oneliner/tests/test_helper.rb
===================================================================
--- trunk/oneliner/tests/test_helper.rb (rev 0)
+++ trunk/oneliner/tests/test_helper.rb 2006-12-22 22:57:52 UTC (rev 124)
@@ -0,0 +1,35 @@
+
+home = File.expand_path(File.dirname(__FILE__))
+$: << File.join(home, "..", "lib")
+
+require 'pp'
+require 'test/unit'
+require 'benchmark'
+require 'oneliner/superstring'
+
+def bm(label = "", options = {})
+ n = options[:n] || 1000
+ width = options[:width] || 50
+ Benchmark.benchmark(" " * width + Benchmark::Tms::CAPTION, width, Benchmark::Tms::FMTSTR, "ms/call") do |b|
+ times = b.report("#{n}x#{label}") do
+ n.times do
+ yield
+ end
+ end
+ [times * 1000 / n.to_f]
+ end
+end
+
+class Test::Unit::TestCase
+
+ def assert_within(timeout, &block)
+ t = Time.new
+ rval = yield
+ while !rval && t > Time.new - timeout
+ rval = yield
+ sleep(0.05)
+ end
+ assert(rval)
+ end
+
+end
From nobody at rubyforge.org Fri Dec 22 18:03:05 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 18:03:05 -0500 (EST)
Subject: [Archipelago-submits] [125] trunk/oneliner/README: more README
Message-ID: <20061222230305.7FAC652409FF@rubyforge.org>
Revision: 125
Author: zond
Date: 2006-12-22 18:03:05 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
more README
Modified Paths:
--------------
trunk/oneliner/README
Modified: trunk/oneliner/README
===================================================================
--- trunk/oneliner/README 2006-12-22 22:57:52 UTC (rev 124)
+++ trunk/oneliner/README 2006-12-22 23:03:05 UTC (rev 125)
@@ -2,8 +2,32 @@
== Dependencies:
+Oneliner::SuperString:: openssl: http://www.openssl.org/
+
== Sub packages:
+Oneliner::SuperString:: A String subclass that has the added power of cryptographically powered randomness and Online Coding.
+
== Usage:
+You create Oneliner::SuperStrings just regular Strings, then you use Oneliner::SuperString#oneline_encode(size_of_chunk) to get Online Coded data from them.
+
+Then you use Oneliner::SuperString#oneline_decode(chunk) to recreate the data from the original String. Only a few extra percent (around 6 - my randomness seems to be suboptimal) is needed to recreate the original data this way.
+
== Examples:
+
+ s = Oneliner::SuperString.new
+ s2 = Oneliner::SuperString.new(" " * 1024)
+ redundant_packages = []
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages << s2.oneline_encode(256)
+ redundant_packages[0..5].each do |p|
+ s.oneline_decode(p)
+ end
+ assert_equal(s2, s)
From nobody at rubyforge.org Fri Dec 22 21:20:26 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 21:20:26 -0500 (EST)
Subject: [Archipelago-submits] [126] trunk/oneliner: now a working Online
Code with mixed c and ruby parts, as a gem,
with tests and benchmarks and everything
Message-ID: <20061223022026.A35585241DCC@rubyforge.org>
Revision: 126
Author: zond
Date: 2006-12-22 21:20:26 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
now a working Online Code with mixed c and ruby parts, as a gem, with tests and benchmarks and everything
Modified Paths:
--------------
trunk/oneliner/Rakefile
trunk/oneliner/lib/oneliner/superstring.rb
trunk/oneliner/lib/oneliner.rb
trunk/oneliner/tests/superstring_benchmark.rb
trunk/oneliner/tests/test_helper.rb
Added Paths:
-----------
trunk/oneliner/ext/
trunk/oneliner/ext/extconf.rb
trunk/oneliner/ext/superstring_ext.c
Property Changed:
----------------
trunk/oneliner/
Property changes on: trunk/oneliner
___________________________________________________________________
Name: svn:ignore
+ pkg
Makefile
superstring_ext.bundle
mkmf.log
Modified: trunk/oneliner/Rakefile
===================================================================
--- trunk/oneliner/Rakefile 2006-12-22 23:03:05 UTC (rev 125)
+++ trunk/oneliner/Rakefile 2006-12-23 02:20:26 UTC (rev 126)
@@ -13,9 +13,10 @@
s.author = "Martin Kihlgren"
s.email = "zond at troja dot ath dot cx"
s.summary = "An online code implementation for ruby."
- s.files = FileList['lib/**/*.rb', 'tests/*', 'GPL-2'].to_a
+ s.files = FileList['lib/**/*.rb', 'tests/*', 'ext/*', 'GPL-2'].to_a
s.require_path = "lib"
s.add_dependency('RubyInline', '>= 3.6.2')
+ s.extensions << 'ext/extconf.rb'
s.autorequire = "oneliner"
s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
s.has_rdoc = true
Added: trunk/oneliner/ext/extconf.rb
===================================================================
--- trunk/oneliner/ext/extconf.rb (rev 0)
+++ trunk/oneliner/ext/extconf.rb 2006-12-23 02:20:26 UTC (rev 126)
@@ -0,0 +1,16 @@
+require 'mkmf'
+
+def crash(s)
+ puts "--------------------------------------------------"
+ puts " extconf failure: #{s}"
+ puts "--------------------------------------------------"
+ exit 1
+end
+
+unless have_library('ssl')
+ crash "libssl needed"
+end
+
+dir_config("superstring_ext")
+
+create_makefile("oneliner/superstring_ext")
Added: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c (rev 0)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 02:20:26 UTC (rev 126)
@@ -0,0 +1,470 @@
+
+#include "ruby.h"
+
+#include
+
+#include
+
+#include
+
+#include
+
+double P0[] = {0.0,0.0831263080421617,0.462395441631886,0.154131813877295,0.0770659069386476,0.0462395441631886,0.0308263627754591,0.0220188305538993,0.0165141229154245,0.0128443178231079,0.0102754542584864,0.00840718984785247,0.00700599153987706,0.00592814668758828,0.00508126858936138,0.00440376611077987,0.00385329534693238,0.0033999664825874,0.00302219242896657,0.00270406691012799,0.00243366021911519,0.00220188305538993,0.0020017118685363,0.00182764996692445,0.00167534580301408,0.00154131813877295,0.00142275520502119,0.00131736593057517,0.00122326836410552,0.00113890502864997,0.00106297802673997,0.000994398799208357,0.000932248874257834,0.000875748942484632,0.000824234298809066,0.000777135196019976,0.000733961018463311,0.000694287449897727,0.000657746005166267,0.000624015440798766,0.000592814668758828,0.000563896880038885,0.000537044647656081,0.000512065826834868,0.000488790107433283,0.000467066102658471,0.000446758880803754,0.000427747864599339,0.0004099250369077,0.000393193402748202,0.000377465666638274,0.000362663091475989,0.000348714511034605,0.000335555472882355,0.000323127492405231,0.000311377401772314,0.000300256780280445,0.00028972145465657,0.000279731059668412,0.000270248650866093,0.00026124036250389,0.000252675104716878,0.000244524294887301,0.000236761618859133,0.000229362818269785,0.000222305500784561,0.000215568970457756,0.000209134075817226,0.000202983073587307,0.000197099506236951,0.000191468091773038,0.000186074624399149,0.000180905884832506,0.000175949559220657,0.000171194165728207,0.000166628987975454,0.000162244014607679,0.000158029884358129,0.000153977836041254,0.000150079662976918,0.000146327671402496,0.000142714642478977,0.000139233797540465,0.00013587876627443,0.00013264355755361,0.000129522532669996,0.000126510380747438,0.000123602096132554,0.000120792957584087,0.000118078509099052,0.000115454542230184,0.000112917079763586,0.000110462360638291,0.000108086826000908,0.000105787106298761,0.000103560009324051,0.0001014025091298,9.93117357456799e-05,9.72849656284212e-05,9.5319612787443e-05,9.34132205316941e-05,9.15634537884923e-05,8.97680919495022e-05,8.80250222029099e-05,8.63322333143924e-05,8.46878098226897e-05,8.3089926618488e-05,8.15368438779555e-05,8.00269023246601e-05,7.85585187957672e-05,7.71301820903896e-05,7.5740449079752e-05,7.43879410604707e-05,7.30713403337367e-05,7.17893869945483e-05,7.05408759163823e-05,6.9324653917824e-05};
+double P1[] = {0.0,0.00943264209782069,0.49551807459988,0.165172691533293,0.0825863457666466,0.049551807459988,0.0330345383066586,0.0235960987904705,0.0176970740928528,0.0137643909611078,0.0110115127688862,0.00900941953817963,0.00750784961514969,0.00635279582820358,0.00544525356703164,0.00471921975809409,0.00412931728833233,0.00364351525441088,0.003238680226143,0.00289776651812795,0.00260798986631516,0.00235960987904705,0.00214509989004277,0.00195856946482166,0.00179535534275319,0.00165172691533293,0.00152467099876886,0.00141173240626746,0.00131089437724836,0.00122048786847261,0.00113912201057444,0.00106563026795673,0.000999028376209435,0.000938481201893711,0.000883276425311728,0.000832803486722487,0.000786536626349015,0.000744021133032852,0.000704862126031123,0.000668715350337219,0.000635279582820358,0.000604290334877902,0.000575514604645621,0.000548746483499313,0.000523803461522071,0.000500523307676646,0.000478761424734183,0.00045838859814975,0.000439289073226844,0.000421358906972687,0.000404504550693779,0.00038864162713716,0.00037369387224727,0.000359592216690769,0.000346273986442963,0.000333682205117764,0.000321764983506415,0.000310474984085138,0.000299768950151167,0.000289607290824009,0.000279953714463209,0.00027077490415294,0.000262040229825425,0.00025372149237065,0.000245792695734067,0.000238229843557634,0.000231010757389221,0.000224114913885065,0.000217523298770799,0.000211218275618022,0.000205183467743221,0.000199403651750455,0.000193864661424053,0.000188553300837093,0.000183457265679333,0.000178565071927885,0.000173865991087677,0.000169349991319166,0.000165007683849444,0.000160830274131736,0.000156809517278443,0.000152937677345642,0.000149207490093309,0.000145612128886241,0.000142145173436569,0.000138800581120414,0.000135572660629242,0.000132456047741213,0.000129445683019822,0.000126536791266568,0.000123724862571755,0.000121005634822925,0.000118375077544166,0.000115829376951819,0.000113364922123056,0.000110978292183624,0.000108666244429798,0.000106425703307534,0.000104253750178809,0.00010214761381156,0.000100104661535329,9.81223910098771e-05,9.61984225587031e-05,9.43304920235826e-05,9.25164441000522e-05,9.07542261171941e-05,8.90418822281904e-05,8.73775479809345e-05,8.57594452405468e-05,8.4185877437968e-05,8.2655225120914e-05,8.11659417854021e-05,7.97165499678056e-05,7.83056375789949e-05,7.69318544635739e-05,7.55939091685552e-05,7.42905659070284e-05,7.30206417034895e-05,7.17830037085151e-05,7.05765666713972e-05,6.94002905602072e-05,6.82531783195426e-05,6.71342737569272e-05,6.60426595494975e-05,6.49774553632153e-05,6.39378160774038e-05,6.29229301079212e-05,6.19320178227571e-05,6.09643300442765e-05,6.00191466327373e-05,5.90957751460799e-05,5.81935495713305e-05,5.73118291232801e-05,5.64499971063886e-05,5.5607459836144e-05,5.47836456163493e-05,5.39780037690501e-05,5.31900037140274e-05,5.24191340949836e-05,5.1664901949732e-05,5.09268319218787e-05,5.02044655116393e-05,4.9497360363588e-05,4.88050895892721e-05,4.81272411227544e-05,4.74634171072682e-05,4.68132333112782e-05,4.61763185723492e-05,4.55523142673175e-05,4.49408738073535e-05,4.43416621565888e-05,4.37543553730578e-05,4.31786401707807e-05,4.26142135018816e-05,4.20607821577013e-05,4.15180623879246e-05,4.09857795367973e-05,4.04636676955642e-05,3.99514693703039e-05,3.94489351643882e-05,3.89558234748333e-05,3.8471900201854e-05,3.79969384709669e-05,3.75307183670287e-05,3.70730266796259e-05,3.66236566592668e-05,3.61824077838539e-05,3.57490855349455e-05,3.5323501183339e-05,3.49054715835362e-05,3.4494818976671e-05,3.40913708015053e-05,3.36949595131157e-05,3.33054224089178e-05,3.29226014616889e-05,3.25463431592696e-05,3.21764983506415e-05,3.18129220980919e-05,3.1455473535192e-05,3.11040157303295e-05,3.07584155555481e-05,3.04185435604592e-05,3.00842738510036e-05,2.97554839728505e-05,2.94320547992326e-05,2.91138704230246e-05,2.88008180528846e-05,2.84927879132816e-05,2.81896731482467e-05,2.78913697286885e-05,2.75977763631233e-05,2.7308794411677e-05,2.70243278032221e-05,2.67442829555203e-05,2.64685686982469e-05,2.61970961987777e-05,2.59297788906269e-05,2.56665324044276e-05,2.54072745013526e-05,2.51519250088767e-05,2.49004057587879e-05,2.46526405273572e-05,2.44085549775814e-05,2.4168076603418e-05,2.39311346759335e-05,2.36976601912903e-05,2.3467585820501e-05,2.32408458608827e-05,2.30173761891434e-05,2.27971142160416e-05,2.25799988425555e-05,2.23659704175075e-05,2.21549706965877e-05,2.1946942802723e-05,2.17418311877443e-05,2.15395815953001e-05,2.13401410249733e-05,2.11434576975542e-05,2.09494810214298e-05,2.07581615600469e-05,2.05694510004101e-05,2.03833021225783e-05,2.01996687701227e-05,2.00185058215117e-05,1.98397691623911e-05,1.96634156587254e-05,1.94894031307721e-05,1.93176903278578e-05,1.91482369039292e-05,1.89810033938512e-05,1.88159511904264e-05,1.8653042522111e-05,1.84922404314032e-05,1.83335087538804e-05,1.81768120978643e-05,1.8022115824691e-05,1.78693860295665e-05,1.77185895229879e-05,1.75696938127107e-05,1.74226670862445e-05,1.72774781938591e-05,1.71340966320844e-05,1.6992492527687e-05,1.68526366221093e-05,1.67145002563543e-05,1.65780553563024e-05,1.64432744184463e-05,1.63101304960297e-05,1.61785971855779e-05,1.60486486138062e-05,1.59202594248957e-05,1.57934047681237e-05,1.5668060285837e-05,1.55442021017592e-05,1.54218068096194e-05,1.53008514620929e-05,1.51813135600453e-05,1.50631710420683e-05,1.49464022743003e-05,1.4830986040522e-05,1.4716901532518e-05,1.46041283406979e-05,1.44926464449674e-05,1.43824362058421e-05,1.42734783557979e-05,1.41657539908485e-05,1.40592445623459e-05,1.39539318689949e-05,1.38497980490771e-05,1.37468255728758e-05,1.36449972352989e-05,1.35442961486915e-05,1.34447057358335e-05,1.33462097231168e-05,1.32487921338969e-05,1.31524372820141e-05,1.30571297654777e-05,1.29628544603118e-05,1.28695965145542e-05,1.27773413424068e-05,1.26860746185325e-05,1.25957822724931e-05,1.25064504833265e-05,1.24180656742571e-05,1.23306145075369e-05,1.22440838794139e-05,1.21584609152222e-05,1.20737329645934e-05,1.19898875967838e-05,1.1906912596114e-05,1.18247959575201e-05,1.17435258822107e-05,1.16630907734284e-05,1.15834792323129e-05,1.15046800538618e-05,1.14266822229881e-05,1.13494749106706e-05,1.12730474701947e-05,1.1197389433482e-05,1.11224905075055e-05,1.10483405707888e-05,1.09749296699863e-05,1.09022480165426e-05,1.08302859834301e-05,1.07590341019602e-05,1.06884830586687e-05,1.06186236922721e-05,1.05494469906938e-05,1.04809440881568e-05,1.04131062623435e-05,1.03459249316187e-05,1.02793916523157e-05,1.02134981160829e-05,1.01482361472901e-05,1.0083597700492e-05,1.00195748579492e-05,9.95615982720272e-06,9.89334493870302e-06,9.83112264349106e-06,9.76948551092998e-06,9.70842622648667e-06,9.64793758956152e-06,9.58801251136548e-06,9.5286440128431e-06,9.46982522264036e-06,9.41154937511642e-06,9.35380980839792e-06,9.29659996247499e-06,9.23991337733795e-06,9.18374369115352e-06,9.12808463847987e-06,9.07293004851926e-06,9.0182738434077e-06,8.96411003654039e-06,8.91043273093236e-06,8.85723611761336e-06,8.80451447405614e-06,8.75226216263741e-06,8.70047362913068e-06,8.6491434012302e-06,8.59826608710532e-06,8.54783637398447e-06,8.49784902676818e-06,8.44829888667041e-06,8.39918086988744e-06,8.35048996629389e-06,8.30222123816503e-06,8.25436981892488e-06,8.20693091191957e-06,8.15989978921516e-06,8.11327179041964e-06,8.06704232152836e-06,8.02120685379241e-06,7.97576092260944e-06,7.93070012643651e-06,7.88602012572419e-06,7.84171664187181e-06,7.79778545620306e-06,7.7542224089617e-06,7.71102339832682e-06,7.66818437944722e-06,7.62570136349461e-06,7.58357041673497e-06,7.54178765961797e-06,7.50034926588381e-06,7.45925146168718e-06,7.41849052473807e-06,7.37806278345885e-06,7.33796461615744e-06,7.29819245021621e-06,7.25874276129612e-06,7.21961207255598e-06,7.18079695388632e-06,7.14229402115771e-06,7.10409993548307e-06,7.06621140249383e-06,7.0286251716295e-06,6.99133803544048e-06,6.95434682890376e-06,6.91764842875123e-06,6.88123975281044e-06,6.84511775935736e-06,6.80927944648115e-06,6.77372185146036e-06,6.73844205015067e-06,6.70343715638365e-06,6.66870432137648e-06,6.63424073315232e-06,6.60004361597112e-06,6.56611022977075e-06,6.53243786961808e-06,6.49902386516991e-06,6.46586558014353e-06,6.43296041179674e-06,6.40030579041707e-06,6.36789917882002e-06,6.33573807185628e-06,6.30381999592753e-06,6.27214250851081e-06,6.24070319769121e-06,6.20949968170275e-06,6.1785296084773e-06,6.1477906552013e-06,6.1172805278802e-06,6.08699696091049e-06,6.05693771665908e-06,6.02710058504993e-06,5.99748338315779e-06,5.96808395480898e-06,5.93890017018888e-06,5.90992992545625e-06,5.88117114236401e-06,5.85262176788651e-06,5.82427977385317e-06,5.79614315658817e-06,5.76820993655642e-06,5.74047815801529e-06,5.71294588867229e-06,5.6856112193485e-06,5.65847226364755e-06,5.63152715763018e-06,5.60477405949417e-06,5.5782111492596e-06,5.55183662845932e-06,5.52564871983451e-06,5.49964566703529e-06,5.4738257343262e-06,5.44818720629657e-06,5.42272838757556e-06,5.3974476025519e-06,5.37234319509817e-06,5.34741352829957e-06,5.32265698418707e-06,5.29807196347489e-06,5.2736568853022e-06,5.24941018697897e-06,5.22533032373594e-06,5.20141576847857e-06,5.17766501154488e-06,5.15407656046723e-06,5.13064893973783e-06,5.10738069057802e-06,5.08427037071115e-06,5.06131655413909e-06,5.03851783092225e-06,5.01587280696305e-06,4.99338010379281e-06,4.97103835836197e-06,4.94884622283357e-06,4.92680236437997e-06,4.90490546498272e-06,4.88315422123557e-06,4.86154734415046e-06,4.84008355896657e-06,4.81876160496231e-06,4.79758023527017e-06,4.77653821669442e-06,4.75563432953165e-06,4.73486736739396e-06,4.71423613703494e-06,4.69373945817827e-06,4.67337616334886e-06,4.65314509770666e-06,4.63304511888287e-06,4.61307509681872e-06,4.5932339136066e-06,4.57352046333361e-06,4.55393365192747e-06,4.5344723970047e-06,4.5151356277211e-06,4.49592228462441e-06,4.47683131950923e-06,4.45786169527403e-06,4.43901238578027e-06,4.42028237571368e-06,4.40167066044752e-06,4.38317624590782e-06,4.36479814844071e-06,4.34653539468154e-06,4.32838702142608e-06,4.31035207550348e-06,4.29242961365107e-06,4.27461870239111e-06,4.25691841790916e-06,4.23932784593433e-06,4.22184608162119e-06,4.20447222943345e-06,4.18720540302921e-06,4.17004472514794e-06,4.15298932749907e-06,4.13603835065214e-06,4.11919094392851e-06,4.10244626529465e-06,4.08580348125694e-06,4.06926176675793e-06,4.05282030507406e-06,4.03647828771489e-06,4.02023491432368e-06,4.00408939257941e-06,3.98804093810013e-06,3.97208877434773e-06,3.95623213253397e-06,3.94047025152786e-06,3.92480237776433e-06,3.90922776515415e-06,3.89374567499512e-06,3.87835537588447e-06,3.86305614363246e-06,3.84784726117722e-06,3.83272801850069e-06,3.81769771254578e-06,3.80275564713464e-06,3.78790113288802e-06,3.77313348714577e-06,3.75845203388839e-06,3.7438561036597e-06,3.72934503349048e-06,3.7149181668232e-06,3.70057485343778e-06,3.68631444937829e-06,3.67213631688068e-06,3.65803982430149e-06,3.64402434604746e-06,3.63008926250617e-06,3.61623395997752e-06,3.60245783060618e-06,3.5887602723149e-06,3.57514068873875e-06,3.56159848916019e-06,3.54813308844503e-06,3.5347439069792e-06,3.5214303706064e-06,3.50819191056653e-06,3.49502796343494e-06,3.48193797106253e-06,3.4689213805165e-06,3.45597764402204e-06,3.44310621890464e-06,3.43030656753324e-06,3.4175781572641e-06,3.40492046038535e-06,3.3923329540623e-06,3.37981512028347e-06,3.36736644580729e-06,3.35498642210947e-06,3.34267454533108e-06,3.33043031622731e-06,3.31825324011678e-06,3.30614282683169e-06,3.29409859066837e-06,3.28212005033866e-06,3.27020672892183e-06,3.25835815381704e-06,3.24657385669654e-06,3.23485337345937e-06,3.22319624418564e-06,3.21160201309145e-06,3.2000702284843e-06,3.18860044271912e-06,3.17719221215483e-06,3.16584509711142e-06,3.1545586618276e-06,3.14333247441896e-06,3.13216610683666e-06,3.1210591348266e-06,3.11001113788916e-06,3.09902169923937e-06,3.08809040576763e-06,3.07721684800084e-06,3.06640062006411e-06,3.05564131964283e-06,3.04493854794531e-06,3.03429190966578e-06,3.02370101294792e-06,3.0131654693488e-06,3.00268489380324e-06,2.99225890458865e-06,2.98188712329024e-06,2.97156917476675e-06,2.96130468711643e-06,2.95109329164362e-06,2.94093462282557e-06,2.93082831827977e-06,2.92077401873164e-06,2.91077136798256e-06,2.90082001287835e-06,2.89091960327808e-06,2.8810697920233e-06,2.87127023490758e-06,2.86152059064643e-06,2.85182052084763e-06,2.84216968998182e-06,2.8325677653535e-06,2.82301441707237e-06,2.81350931802499e-06,2.80405214384676e-06,2.79464257289425e-06,2.78528028621789e-06,2.77596496753489e-06,2.76669630320255e-06,2.75747398219187e-06,2.74829769606145e-06,2.73916713893168e-06,2.73008200745927e-06,2.72104200081205e-06,2.71204682064408e-06,2.703096171071e-06,2.69418975864572e-06,2.68532729233439e-06,2.67650848349257e-06,2.66773304584177e-06,2.65900069544622e-06,2.65031115068986e-06,2.64166413225367e-06,2.63305936309324e-06,2.62449656841651e-06,2.61597547566191e-06,2.60749581447662e-06,2.59905731669515e-06,2.5906597163181e-06,2.58230274949127e-06,2.57398615448486e-06,2.56570967167301e-06,2.55747304351354e-06,2.54927601452792e-06,2.54111833128143e-06,2.5329997423636e-06,2.52491999836882e-06,2.5168788518772e-06,2.50887605743562e-06,2.500911371539e-06,2.49298455261178e-06,2.48509536098959e-06,2.47724355890115e-06,2.46942891045036e-06,2.46165118159855e-06,2.45391014014698e-06,2.44620555571952e-06,2.43853719974547e-06,2.43090484544267e-06,2.42330826780066e-06,2.41574724356416e-06,2.4082215512166e-06,2.40073097096399e-06,2.39327528471876e-06,2.38585427608397e-06,2.37846773033758e-06,2.37111543441691e-06,2.36379717690327e-06,2.35651274800681e-06,2.3492619395514e-06,2.34204454495985e-06,2.33486035923911e-06,2.32770917896579e-06,2.32059080227171e-06,2.31350502882965e-06,2.30645165983932e-06,2.29943049801333e-06,2.29244134756344e-06,2.28548401418692e-06,2.27855830505302e-06,2.27166402878962e-06,2.26480099547001e-06,2.25796901659982e-06,2.25116790510403e-06,2.24439747531425e-06,2.23765754295595e-06,2.23094792513599e-06,2.22426844033019e-06,2.21761890837106e-06,2.21099915043562e-06,2.20440898903343e-06,2.19784824799464e-06,2.19131675245825e-06,2.18481432886045e-06,2.17834080492309e-06,2.17189600964225e-06,2.16547977327699e-06,2.15909192733812e-06,2.15273230457718e-06,2.14640073897548e-06,2.14009706573326e-06,2.13382112125897e-06,2.12757274315865e-06,2.12135177022544e-06,2.11515804242916e-06,2.10899140090604e-06,2.10285168794853e-06,2.09673874699519e-06,2.09065242262075e-06,2.0845925605262e-06,2.07855900752902e-06,2.0725516115535e-06,2.06657022162116e-06,2.06061468784128e-06,2.05468486140145e-06,2.04878059455834e-06,2.04290174062847e-06,2.03704815397911e-06,2.03121969001922e-06,2.0254162051906e-06,2.01963755695895e-06,2.01388360380523e-06,2.00815420521688e-06,2.00244922167933e-06,1.99676851466747e-06,1.99111194663725e-06,1.98547938101734e-06,1.97987068220091e-06,1.97428571553744e-06,1.96872434732466e-06,1.96318644480054e-06,1.95767187613537e-06,1.95218051042391e-06,1.94671221767762e-06,1.94126686881699e-06,1.93584433566387e-06,1.93044449093398e-06,1.92506720822943e-06,1.91971236203129e-06,1.91437982769232e-06,1.90906948142965e-06,1.90378120031766e-06,1.89851486228082e-06,1.89327034608667e-06,1.88804753133884e-06,1.88284629847014e-06,1.8776665287357e-06,1.8725081042062e-06,1.86737090776119e-06,1.8622548230824e-06,1.85715973464715e-06,1.85208552772189e-06,1.84703208835566e-06,1.84199930337376e-06,1.83698706037139e-06,1.83199524770733e-06,1.82702375449782e-06,1.82207247061029e-06,1.81714128665735e-06,1.81223009399071e-06,1.80733878469519e-06,1.8024672515828e-06,1.79761538818689e-06,1.79278308875628e-06,1.78797024824955e-06,1.78317676232931e-06,1.77840252735654e-06,1.773647440385e-06,1.76891139915566e-06,1.76419430209125e-06,1.75949604829074e-06,1.75481653752401e-06,1.75015567022647e-06,1.74551334749377e-06,1.74088947107657e-06,1.73628394337531e-06,1.73169666743508e-06,1.72712754694053e-06,1.72257648621078e-06,1.71804339019444e-06,1.71352816446462e-06,1.70903071521406e-06,1.7045509492502e-06,1.70008877399038e-06,1.69564409745707e-06,1.69121682827311e-06,1.68680687565701e-06,1.68241414941832e-06,1.67803855995299e-06,1.67368001823883e-06,1.66933843583095e-06,1.66501372485729e-06,1.6607057980142e-06,1.65641456856196e-06,1.65213995032051e-06,1.64788185766505e-06,1.64364020552176e-06,1.63941490936361e-06,1.63520588520607e-06,1.63101304960297e-06,1.6268363196424e-06,1.62267561294255e-06,1.61853084764768e-06,1.61440194242409e-06,1.61028881645613e-06,1.60619138944224e-06,1.60210958159106e-06,1.59804331361748e-06,1.59399250673885e-06,1.58995708267116e-06,1.58593696362521e-06,1.58193207230293e-06,1.57794233189359e-06,1.57396766607018e-06,1.57000799898572e-06,1.56606325526968e-06,1.56213336002434e-06,1.55821823882127e-06,1.55431781769781e-06,1.55043202315357e-06,1.54656078214694e-06,1.54270402209171e-06,1.53886167085362e-06,1.53503365674702e-06,1.5312199085315e-06,1.5274203554086e-06,1.52363492701849e-06,1.51986355343676e-06,1.51610616517115e-06,1.51236269315839e-06,1.50863306876096e-06,1.50491722376401e-06,1.50121509037221e-06,1.49752660120668e-06,1.49385168930188e-06,1.49019028810261e-06,1.48654233146099e-06,1.48290775363345e-06,1.47928648927782e-06,1.47567847345031e-06,1.47208364160268e-06,1.46850192957932e-06,1.46493327361436e-06,1.46137761032889e-06,1.4578348767281e-06,1.45430501019849e-06,1.45078794850514e-06,1.44728362978895e-06,1.44379199256388e-06,1.44031297571433e-06,1.43684651849239e-06,1.43339256051525e-06,1.42995104176251e-06,1.42652190257363e-06,1.42310508364531e-06,1.41970052602894e-06,1.41630817112803e-06,1.41292796069574e-06,1.40955983683235e-06,1.40620374198274e-06,1.40285961893403e-06,1.39952741081305e-06,1.39620706108396e-06,1.39289851354584e-06,1.38960171233035e-06,1.38631660189931e-06,1.3830431270424e-06,1.37978123287485e-06,1.3765308648351e-06,1.37329196868255e-06,1.37006449049528e-06,1.36684837666782e-06,1.36364357390893e-06,1.36045002923936e-06,1.35726768998967e-06,1.35409650379811e-06,1.35093641860838e-06,1.34778738266757e-06,1.34464934452399e-06,1.3415222530251e-06,1.3384060573154e-06,1.33530070683439e-06,1.33220615131449e-06,1.32912234077904e-06,1.32604922554025e-06,1.3229867561972e-06,1.31993488363388e-06,1.31689355901721e-06,1.31386273379508e-06,1.3108423596944e-06,1.30783238871921e-06,1.30483277314876e-06,1.30184346553559e-06,1.2988644187037e-06,1.29589558574666e-06,1.29293692002578e-06,1.28998837516825e-06,1.28704990506536e-06,1.28412146387067e-06,1.28120300599824e-06,1.27829448612083e-06,1.27539585916818e-06,1.27250708032521e-06,1.26962810503036e-06,1.2667588889738e-06,1.26389938809575e-06,1.26104955858482e-06,1.2582093568763e-06,1.25537873965048e-06,1.25255766383104e-06,1.24974608658339e-06,1.24694396531302e-06,1.24415125766394e-06,1.24136792151704e-06,1.23859391498851e-06,1.23582919642827e-06,1.2330737244184e-06,1.23032745777159e-06,1.2275903555296e-06,1.22486237696176e-06,1.2221434815634e-06,1.21943362905439e-06,1.21673277937763e-06,1.21404089269759e-06,1.21135792939882e-06,1.20868385008447e-06,1.20601861557491e-06,1.20336218690624e-06,1.20071452532889e-06,1.19807559230619e-06,1.19544534951298e-06,1.19282375883423e-06,1.19021078236362e-06,1.18760638240221e-06,1.18501052145707e-06,1.18242316223991e-06,1.17984426766578e-06,1.17727380085169e-06,1.17471172511534e-06,1.17215800397379e-06,1.16961260114214e-06,1.16707548053229e-06,1.16454660625161e-06,1.16202594260172e-06,1.15951345407717e-06,1.15700910536426e-06,1.15451286133974e-06,1.15202468706962e-06,1.14954454780789e-06,1.1470724089954e-06,1.14460823625857e-06,1.14215199540823e-06,1.13970365243844e-06,1.13726317352529e-06,1.13483052502578e-06,1.13240567347657e-06,1.12998858559295e-06,1.1275792282676e-06,1.12517756856947e-06,1.12278357374273e-06,1.12039721120555e-06,1.11801844854906e-06,1.11564725353624e-06,1.11328359410078e-06,1.11092743834607e-06,1.10857875454407e-06,1.10623751113426e-06,1.10390367672258e-06,1.10157722008039e-06,1.09925811014337e-06,1.09694631601058e-06,1.09464180694333e-06,1.09234455236423e-06,1.09005452185613e-06,1.08777168516114e-06,1.08549601217963e-06,1.08322747296922e-06,1.08096603774382e-06,1.07871167687261e-06,1.07646436087913e-06,1.07422406044025e-06,1.07199074638528e-06,1.06976438969497e-06,1.06754496150058e-06,1.06533243308297e-06,1.06312677587161e-06,1.06092796144375e-06,1.05873596152341e-06,1.05655074798054e-06,1.05437229283006e-06,1.05220056823103e-06,1.0500355464857e-06,1.04787720003866e-06,1.04572550147595e-06,1.0435804235242e-06,1.04144193904977e-06,1.03931002105785e-06,1.03718464269168e-06,1.03506577723164e-06,1.03295339809443e-06,1.03084747883226e-06,1.02874799313199e-06,1.02665491481433e-06,1.024568217833e-06,1.02248787627395e-06,1.02041386435453e-06,1.0183461564227e-06,1.01628472695626e-06,1.01422955056201e-06,1.01218060197502e-06,1.01013785605781e-06,1.00810128779963e-06,1.00607087231564e-06,1.0040465848462e-06,1.00202840075605e-06,1.00001629553365e-06,9.98010244790354e-07,9.96010224259712e-07,9.9401620979673e-07,9.92028177377136e-07,9.90046103096662e-07,9.88069963170322e-07,9.86099733931697e-07,9.84135391832232e-07,9.82176913440526e-07,9.80224275441638e-07,9.78277454636391e-07,9.76336427940684e-07,9.74401172384806e-07,9.72471665112757e-07,9.70547883381574e-07,9.68629804560662e-07,9.66717406131125e-07,9.64810665685107e-07,9.62909560925136e-07,9.61014069663472e-07,9.5912416982146e-07,9.57239839428883e-07,9.55361056623331e-07,9.5348779964956e-07,9.51620046858865e-07,9.49757776708456e-07,9.47900967760835e-07,9.46049598683177e-07,9.44203648246722e-07,9.42363095326163e-07,9.40527918899043e-07,9.38698098045154e-07,9.36873611945941e-07,9.35054439883909e-07,9.3324056124204e-07,9.31431955503199e-07,9.29628602249562e-07,9.27830481162039e-07,9.26037572019697e-07,9.24249854699195e-07,9.22467309174221e-07,9.20689915514926e-07,9.18917653887371e-07,9.17150504552972e-07,9.15388447867951e-07,9.13631464282792e-07,9.11879534341694e-07,9.10132638682036e-07,9.0839075803384e-07,9.06653873219244e-07,9.04921965151968e-07,9.03195014836792e-07,9.01473003369039e-07,8.9975591193405e-07,8.98043721806678e-07,8.96336414350771e-07,8.94633971018671e-07,8.92936373350704e-07,8.91243602974684e-07,8.89555641605414e-07,8.87872471044192e-07,8.86194073178324e-07,8.84520429980632e-07,8.8285152350897e-07,8.81187335905748e-07,8.79527849397451e-07,8.77873046294164e-07,8.76222908989099e-07,8.74577419958134e-07,8.72936561759338e-07,8.71300317032517e-07,8.69668668498748e-07,8.68041598959929e-07,8.66419091298322e-07,8.64801128476103e-07,8.63187693534916e-07,8.61578769595428e-07,8.59974339856889e-07,8.58374387596691e-07,8.56778896169931e-07,8.55187849008984e-07,8.53601229623068e-07,8.52019021597816e-07,8.50441208594857e-07,8.48867774351389e-07,8.4729870267976e-07,8.45733977467054e-07,8.4417358267468e-07,8.42617502337952e-07,8.41065720565691e-07,8.39518221539811e-07,8.37974989514922e-07,8.36436008817925e-07,8.34901263847616e-07,8.33370739074294e-07,8.31844419039359e-07,8.30322288354932e-07,8.2880433170346e-07,8.27290533837335e-07,8.25780879578508e-07,8.2427535381811e-07,8.22773941516073e-07,8.21276627700757e-07,8.19783397468574e-07,8.18294235983618e-07,8.16809128477295e-07,8.15328060247962e-07,8.13851016660556e-07,8.12377983146238e-07,8.10908945202032e-07,8.09443888390465e-07,8.07982798339219e-07,8.06525660740771e-07,8.05072461352049e-07,8.0362318599408e-07,8.02177820551645e-07,8.00736350972935e-07,7.99298763269214e-07,7.97865043514471e-07,7.9643517784509e-07,7.95009152459512e-07,7.93586953617903e-07,7.92168567641821e-07,7.90753980913889e-07,7.89343179877468e-07,7.87936151036332e-07,7.86532880954344e-07,7.85133356255137e-07,7.83737563621794e-07,7.82345489796534e-07,7.80957121580391e-07,7.79572445832908e-07,7.78191449471822e-07,7.76814119472757e-07,7.75440442868915e-07,7.74070406750772e-07,7.72703998265775e-07,7.7134120461804e-07,7.69982013068052e-07,7.68626410932369e-07,7.67274385583323e-07,7.6592592444873e-07,7.64581015011595e-07,7.6323964480982e-07,7.6190180143592e-07,7.60567472536733e-07,7.59236645813134e-07,7.57909309019755e-07,7.56585449964698e-07,7.55265056509263e-07,7.5394811656766e-07,7.5263461810674e-07,7.51324549145719e-07,7.500178977559e-07,7.48714652060408e-07,7.47414800233914e-07,7.46118330502372e-07,7.4482523114275e-07,7.43535490482762e-07,7.42249096900612e-07,7.40966038824725e-07,7.39686304733491e-07,7.38409883155003e-07,7.37136762666805e-07,7.3586693189563e-07,7.34600379517153e-07,7.3333709425573e-07,7.32077064884157e-07,7.30820280223411e-07,7.29566729142411e-07,7.28316400557762e-07,7.27069283433519e-07,7.25825366780938e-07,7.24584639658236e-07,7.23347091170348e-07,7.22112710468693e-07,7.20881486750928e-07,7.19653409260722e-07,7.18428467287513e-07,7.17206650166275e-07,7.15987947277293e-07,7.14772348045922e-07,7.13559841942367e-07,7.12350418481447e-07,7.11144067222376e-07,7.09940777768531e-07,7.08740539767232e-07,7.07543342909517e-07,7.06349176929923e-07,7.05158031606264e-07,7.03969896759412e-07,7.02784762253083e-07,7.01602617993616e-07,7.00423453929762e-07,6.99247260052466e-07,6.98074026394659e-07,6.96903743031047e-07,6.95736400077897e-07,6.94571987692829e-07,6.93410496074614e-07,6.9225191546296e-07,6.91096236138314e-07,6.89943448421653e-07,6.88793542674283e-07,6.8764650929764e-07,6.86502338733085e-07,6.85361021461708e-07,6.84222548004131e-07,6.83086908920307e-07,6.81954094809328e-07,6.80824096309229e-07,6.79696904096797e-07,6.78572508887373e-07,6.77450901434666e-07,6.76332072530563e-07,6.75216013004935e-07,6.74102713725454e-07,6.72992165597406e-07,6.71884359563501e-07,6.70779286603692e-07,6.69676937734993e-07,6.6857730401129e-07,6.67480376523166e-07,6.66386146397719e-07,6.65294604798377e-07,6.6420574292473e-07,6.63119552012343e-07,6.62036023332585e-07,6.6095514819245e-07,6.59876917934387e-07,6.58801323936124e-07,6.57728357610495e-07,6.56658010405271e-07,6.55590273802985e-07,6.54525139320771e-07,6.53462598510185e-07,6.52402642957046e-07,6.51345264281265e-07,6.5029045413668e-07,6.49238204210893e-07,6.48188506225103e-07,6.47141351933948e-07,6.46096733125338e-07,6.45054641620297e-07,6.44015069272802e-07,6.42978007969625e-07,6.41943449630173e-07,6.4091138620633e-07,6.39881809682304e-07,6.38854712074468e-07,6.37830085431205e-07,6.36807921832757e-07,6.35788213391071e-07,6.34770952249646e-07,6.33756130583379e-07,6.32743740598422e-07,6.31733774532024e-07,6.30726224652387e-07,6.29721083258519e-07,6.28718342680082e-07,6.27717995277249e-07,6.26720033440561e-07,6.25724449590774e-07,6.24731236178725e-07,6.23740385685183e-07,6.22751890620705e-07,6.21765743525502e-07,6.20781936969291e-07,6.19800463551158e-07,6.18821315899418e-07,6.17844486671479e-07,6.16869968553701e-07,6.1589775426126e-07,6.14927836538014e-07,6.13960208156365e-07,6.12994861917125e-07,6.12031790649384e-07,6.11070987210374e-07,6.10112444485338e-07,6.09156155387399e-07,6.08202112857426e-07,6.07250309863909e-07,6.06300739402824e-07,6.05353394497507e-07,6.04408268198526e-07,6.03465353583552e-07,6.02524643757233e-07,6.01586131851069e-07,6.00649811023285e-07,5.99715674458708e-07,5.9878371536864e-07,5.97853926990738e-07,5.96926302588891e-07,5.96000835453094e-07,5.95077518899332e-07,5.94156346269457e-07,5.93237310931067e-07,5.92320406277387e-07,5.91405625727151e-07,5.90492962724486e-07,5.89582410738789e-07,5.88673963264615e-07,5.8776761382156e-07,5.86863355954142e-07,5.85961183231691e-07,5.85061089248232e-07,5.84163067622372e-07,5.83267111997184e-07,5.823732160401e-07,5.81481373442795e-07,5.80591577921077e-07,5.79703823214776e-07,5.78818103087633e-07,5.77934411327194e-07,5.77052741744696e-07,5.76173088174964e-07,5.75295444476297e-07,5.74419804530366e-07,5.73546162242107e-07,5.72674511539611e-07,5.71804846374023e-07,5.70937160719435e-07,5.70071448572779e-07,5.69207703953729e-07,5.68345920904594e-07,5.67486093490215e-07,5.66628215797864e-07,5.65772281937142e-07,5.64918286039879e-07,5.6406622226003e-07,5.63216084773579e-07,5.62367867778438e-07,5.61521565494347e-07,5.60677172162777e-07,5.5983468204683e-07,5.58994089431144e-07,5.58155388621795e-07,5.573185739462e-07,5.56483639753022e-07,5.55650580412074e-07,5.54819390314225e-07,5.53990063871304e-07,5.53162595516007e-07,5.52336979701804e-07,5.51513210902845e-07,5.5069128361387e-07,5.49871192350111e-07,5.49052931647209e-07,5.48236496061117e-07,5.47421880168009e-07,5.46609078564196e-07,5.4579808586603e-07,5.44988896709816e-07,5.44181505751728e-07,5.43375907667713e-07,5.42572097153412e-07,5.41770068924065e-07,5.40969817714428e-07,5.40171338278687e-07,5.39374625390371e-07,5.38579673842264e-07,5.37786478446325e-07,5.36995034033601e-07,5.3620533545414e-07,5.35417377576911e-07,5.3463115528972e-07,5.33846663499126e-07,5.33063897130359e-07,5.32282851127238e-07,5.31503520452088e-07,5.30725900085662e-07,5.29949985027058e-07,5.29175770293636e-07,5.28403250920945e-07,5.27632421962635e-07,5.26863278490387e-07,5.26095815593824e-07,5.25330028380441e-07,5.24565911975524e-07,5.23803461522071e-07,5.23042672180718e-07,5.22283539129657e-07,5.21526057564567e-07,5.20770222698531e-07,5.20016029761966e-07,5.19263474002542e-07,5.18512550685112e-07,5.17763255091637e-07,5.17015582521107e-07,5.16269528289475e-07,5.15525087729577e-07,5.14782256191062e-07,5.14041029040318e-07,5.13301401660404e-07,5.12563369450972e-07,5.11826927828197e-07,5.11092072224711e-07,5.10358798089525e-07,5.09627100887963e-07,5.0889697610159e-07,5.08168419228145e-07,5.07441425781467e-07,5.06715991291429e-07,5.0599211130387e-07,5.05269781380524e-07,5.04548997098954e-07,5.03829754052483e-07,5.03112047850129e-07,5.02395874116535e-07,5.01681228491903e-07,5.00968106631928e-07,5.00256504207735e-07,4.99546416905808e-07,4.98837840427927e-07,4.98130770491105e-07,4.9742520282752e-07,4.96721133184452e-07,4.9601855732422e-07,4.95317471024115e-07,4.94617870076341e-07,4.93919750287948e-07,4.93223107480772e-07,4.92527937491369e-07,4.91834236170959e-07,4.91141999385356e-07,4.90451223014913e-07,4.89761902954456e-07,4.89074035113228e-07,4.88387615414823e-07,4.87702639797131e-07,4.87019104212271e-07,4.8633700462654e-07,4.85656337020345e-07,4.84977097388148e-07,4.84299281738409e-07,4.83622886093523e-07,4.82947906489764e-07,4.82274338977226e-07,4.81602179619766e-07,4.80931424494948e-07,4.80262069693981e-07,4.79594111321666e-07,4.78927545496341e-07,4.78262368349818e-07,4.77598576027334e-07,4.7693616468749e-07,4.76275130502199e-07,4.75615469656628e-07,4.74957178349145e-07,4.74300252791263e-07,4.73644689207584e-07,4.72990483835751e-07,4.72337632926384e-07,4.71686132743038e-07,4.71035979562137e-07,4.70387169672933e-07,4.69739699377444e-07,4.69093564990405e-07,4.68448762839215e-07,4.67805289263887e-07,4.67163140616991e-07,4.66522313263607e-07,4.65882803581271e-07,4.65244607959927e-07,4.64607722801871e-07,4.63972144521704e-07,4.63337869546282e-07,4.62704894314661e-07,4.62073215278054e-07,4.61442828899776e-07,4.60813731655195e-07,4.60185920031687e-07,4.5955939052858e-07,4.58934139657113e-07,4.5831016394038e-07,4.57687459913287e-07,4.57066024122502e-07,4.56445853126406e-07,4.55826943495048e-07,4.55209291810096e-07,4.54592894664787e-07,4.53977748663888e-07,4.53363850423639e-07,4.52751196571715e-07,4.52139783747176e-07,4.51529608600418e-07,4.50920667793135e-07,4.50312957998266e-07,4.49706475899951e-07,4.49101218193491e-07,4.48497181585296e-07,4.47894362792842e-07,4.47292758544632e-07,4.46692365580142e-07,4.46093180649786e-07,4.45495200514867e-07,4.44898421947533e-07,4.44302841730736e-07,4.43708456658186e-07,4.43115263534312e-07,4.42523259174213e-07,4.41932440403619e-07,4.41342804058852e-07,4.40754346986773e-07,4.40167066044752e-07,4.39580958100618e-07,4.3899602003262e-07,4.38412248729385e-07,4.37829641089877e-07,4.37248194023357e-07,4.36667904449338e-07,4.36088769297548e-07,4.35510785507889e-07,4.34933950030396e-07,4.34358259825193e-07,4.33783711862462e-07,4.33210303122392e-07,4.3263803059515e-07,4.32066891280833e-07,4.31496882189433e-07,4.30928000340799e-07,4.30360242764592e-07,4.29793606500254e-07,4.29228088596964e-07,4.28663686113602e-07,4.28100396118709e-07,4.27538215690451e-07,4.26977141916579e-07,4.26417171894393e-07,4.25858302730705e-07,4.25300531541797e-07,4.24743855453392e-07,4.24188271600608e-07,4.23633777127927e-07,4.23080369189158e-07,4.22528044947397e-07,4.21976801574993e-07,4.21426636253513e-07,4.20877546173704e-07,4.20329528535457e-07,4.19782580547773e-07,4.19236699428725e-07,4.18691882405426e-07,4.1814812671399e-07,4.17605429599501e-07,4.17063788315973e-07,4.16523200126322e-07,4.15983662302324e-07,4.15445172124587e-07,4.14907726882511e-07,4.1437132387426e-07,4.13835960406722e-07,4.1330163379548e-07,4.12768341364776e-07,4.12236080447478e-07,4.11704848385046e-07,4.11174642527499e-07,4.10645460233384e-07,4.10117298869739e-07,4.09590155812066e-07,4.09064028444292e-07,4.08538914158741e-07,4.080148103561e-07,4.07491714445387e-07,4.0696962384392e-07,4.06448535977282e-07,4.05928448279294e-07,4.05409358191981e-07,4.04891263165537e-07,4.04374160658302e-07,4.03858048136721e-07,4.03342923075322e-07,4.02828782956679e-07,4.02315625271384e-07,4.01803447518015e-07,4.01292247203107e-07,4.00782021841119e-07,4.00272768954409e-07,3.99764486073197e-07,3.99257170735541e-07,3.98750820487303e-07,3.98245432882123e-07,3.97741005481385e-07,3.97237535854194e-07,3.96735021577338e-07,3.96233460235268e-07,3.95732849420063e-07,3.95233186731401e-07,3.94734469776535e-07,3.94236696170259e-07,3.93739863534884e-07,3.93243969500205e-07,3.92749011703477e-07,3.92254987789385e-07,3.91761895410014e-07,3.91269732224826e-07,3.90778495900626e-07,3.90288184111542e-07,3.89798794538988e-07,3.89310324871646e-07,3.88822772805432e-07,3.88336136043473e-07,3.87850412296076e-07,3.87365599280706e-07,3.86881694721955e-07,3.86398696351515e-07,3.85916601908157e-07,3.85435409137698e-07,3.84955115792978e-07,3.84475719633834e-07,3.83997218427071e-07,3.8351960994644e-07,3.8304289197261e-07,3.82567062293141e-07,3.82092118702461e-07,3.81618059001837e-07,3.81144880999355e-07,3.80672582509889e-07,3.80201161355078e-07,3.79730615363302e-07,3.79260942369655e-07,3.78792140215922e-07,3.78324206750554e-07,3.7785713982864e-07,3.77390937311886e-07,3.76925597068592e-07,3.76461116973621e-07,3.75997494908383e-07,3.75534728760803e-07,3.75072816425304e-07,3.74611755802777e-07,3.74151544800563e-07,3.73692181332422e-07,3.73233663318517e-07,3.72775988685386e-07,3.72319155365919e-07,3.71863161299334e-07,3.71408004431159e-07,3.709536827132e-07,3.70500194103527e-07,3.70047536566442e-07,3.69595708072466e-07,3.69144706598308e-07,3.68694530126847e-07,3.68245176647107e-07,3.67796644154236e-07,3.67348930649483e-07,3.66902034140177e-07,3.66455952639703e-07,3.66010684167479e-07,3.6556622674894e-07,3.65122578415507e-07,3.64679737204572e-07,3.64237701159476e-07,3.63796468329482e-07,3.63356036769761e-07,3.62916404541365e-07,3.62477569711206e-07,3.62039530352038e-07,3.61602284542434e-07,3.61165830366765e-07,3.60730165915176e-07,3.60295289283573e-07,3.59861198573592e-07,3.59427891892589e-07,3.58995367353608e-07,3.58563623075372e-07,3.58132657182253e-07,3.57702467804256e-07,3.57273053077e-07,3.56844411141695e-07,3.56416540145122e-07,3.55989438239615e-07,3.55563103583041e-07,3.55137534338776e-07,3.54712728675692e-07,3.5428868476813e-07,3.53865400795886e-07,3.53442874944189e-07,3.53021105403683e-07,3.52600090370405e-07,3.52179828045768e-07,3.51760316636541e-07,3.51341554354831e-07,3.50923539418062e-07,3.50506270048956e-07,3.50089744475517e-07,3.49673960931009e-07,3.49258917653939e-07,3.48844612888039e-07,3.48431044882244e-07,3.48018211890678e-07,3.47606112172631e-07,3.47194743992545e-07,3.46784105619993e-07,3.46374195329662e-07,3.45965011401334e-07,3.45556552119868e-07,3.45148815775184e-07,3.44741800662242e-07,3.44335505081025e-07,3.43929927336524e-07,3.43525065738718e-07,3.43120918602555e-07,3.42717484247937e-07,3.42314760999702e-07,3.41912747187606e-07,3.41511441146306e-07,3.41110841215343e-07,3.40710945739123e-07,3.40311753066904e-07,3.39913261552774e-07,3.39515469555638e-07,3.39118375439198e-07,3.3872197757194e-07,3.38326274327113e-07,3.37931264082715e-07,3.37536945221475e-07,3.37143316130838e-07,3.36750375202946e-07,3.36358120834626e-07,3.35966551427368e-07,3.35575665387313e-07,3.35185461125235e-07,3.34795937056524e-07,3.34407091601174e-07,3.34018923183761e-07,3.33631430233432e-07,3.33244611183886e-07,3.3285846447336e-07,3.32472988544613e-07,3.32088181844908e-07,3.31704042826002e-07,3.31320569944122e-07,3.30937761659958e-07,3.30555616438641e-07,3.30174132749734e-07,3.29793309067208e-07,3.29413143869436e-07,3.29033635639172e-07,3.28654782863536e-07,3.28276584034004e-07,3.27899037646386e-07,3.27522142200815e-07,3.27145896201733e-07,3.26770298157874e-07,3.26395346582248e-07,3.26021039992131e-07,3.25647376909045e-07,3.25274355858748e-07,3.24901975371217e-07,3.24530233980632e-07,3.24159130225366e-07,3.23788662647965e-07,3.2341882979514e-07,3.23049630217749e-07,3.2268106247078e-07,3.22313125113345e-07,3.21945816708658e-07,3.21579135824024e-07,3.21213081030826e-07,3.20847650904511e-07,3.20482844024574e-07,3.20118658974546e-07,3.1975509434198e-07,3.19392148718436e-07,3.1902982069947e-07,3.18668108884618e-07,3.18307011877384e-07,3.17946528285224e-07,3.17586656719536e-07,3.17227395795645e-07,3.16868744132789e-07,3.16510700354108e-07,3.16153263086628e-07,3.15796430961248e-07,3.1544020261273e-07,3.15084576679683e-07,3.14729551804551e-07,3.143751266336e-07,3.14021299816904e-07,3.13668070008337e-07,3.1331543586555e-07,3.12963396049971e-07,3.12611949226782e-07,3.12261094064911e-07,3.1191082923702e-07,3.1156115341949e-07,3.11212065292409e-07,3.10863563539562e-07,3.10515646848415e-07,3.10168313910106e-07,3.0982156341943e-07,3.09475394074827e-07,3.09129804578373e-07,3.08784793635763e-07,3.08440359956303e-07,3.08096502252896e-07,3.07753219242029e-07,3.07410509643764e-07,3.07068372181723e-07,3.06726805583078e-07,3.06385808578539e-07,3.06045379902341e-07,3.05705518292232e-07,3.05366222489466e-07,3.05027491238785e-07,3.04689323288409e-07,3.04351717390029e-07,3.04014672298788e-07,3.03678186773278e-07,3.0334225957552e-07,3.03006889470959e-07,3.02672075228449e-07,3.02337815620246e-07,3.02004109421989e-07,3.01670955412699e-07,3.01338352374757e-07,3.01006299093904e-07,3.00674794359219e-07,3.00343836963116e-07,3.00013425701331e-07,2.99683559372907e-07,2.99354236780189e-07,2.99025456728811e-07,2.98697218027681e-07,2.98369519488979e-07,2.98042359928135e-07,2.97715738163831e-07,2.97389653017978e-07,2.97064103315714e-07,2.9673908788539e-07,2.96414605558561e-07,2.96090655169972e-07,2.95767235557553e-07,2.95444345562403e-07,2.95121984028783e-07,2.94800149804106e-07,2.94478841738924e-07,2.94158058686921e-07,2.938377995049e-07,2.93518063052772e-07,2.93198848193552e-07,2.92880153793342e-07,2.92561978721323e-07,2.92244321849747e-07,2.91927182053926e-07,2.91610558212219e-07,2.91294449206026e-07,2.90978853919779e-07,2.90663771240928e-07,2.90349200059931e-07,2.9003513927025e-07,2.89721587768336e-07,2.89408544453622e-07,2.8909600822851e-07,2.88783977998366e-07,2.88472452671506e-07,2.88161431159192e-07,2.87850912375615e-07,2.87540895237893e-07,2.87231378666054e-07,2.86922361583035e-07,2.86613842914667e-07,2.86305821589664e-07,2.85998296539622e-07,2.85691266698999e-07,2.85384731005116e-07,2.8507868839814e-07,2.84773137821079e-07,2.84468078219771e-07,2.84163508542876e-07,2.83859427741867e-07,2.8355583477102e-07,2.83252728587406e-07,2.82950108150881e-07,2.82647972424078e-07,2.82346320372398e-07,2.82045150964001e-07,2.81744463169796e-07,2.81444255963435e-07,2.81144528321302e-07,2.80845279222503e-07,2.80546507648862e-07,2.80248212584908e-07,2.79950393017868e-07,2.79653047937658e-07,2.79356176336875e-07,2.79059777210788e-07,2.7876384955733e-07,2.78468392377089e-07,2.781734046733e-07,2.77878885451835e-07,2.77584833721198e-07,2.77291248492514e-07,2.7699812877952e-07,2.76705473598559e-07,2.76413281968571e-07,2.76121552911084e-07,2.75830285450207e-07,2.75539478612622e-07,2.75249131427571e-07,2.74959242926858e-07,2.74669812144829e-07,2.74380838118375e-07,2.74092319886915e-07,2.73804256492394e-07,2.73516646979272e-07,2.73229490394517e-07,2.72942785787597e-07,2.72656532210473e-07,2.7237072871759e-07,2.72085374365869e-07,2.71800468214701e-07,2.71516009325936e-07,2.71231996763879e-07,2.70948429595282e-07,2.7066530688933e-07,2.70382627717644e-07,2.70100391154265e-07,2.69818596275648e-07,2.69537242160658e-07,2.69256327890558e-07,2.68975852549005e-07,2.68695815222041e-07,2.68416214998085e-07,2.68137050967926e-07,2.67858322224716e-07,2.67580027863963e-07,2.67302166983523e-07,2.67024738683592e-07,2.667477420667e-07,2.66471176237704e-07,2.66195040303779e-07,2.65919333374412e-07,2.65644054561395e-07,2.65369202978817e-07,2.65094777743058e-07,2.64820777972781e-07,2.64547202788925e-07,2.64274051314698e-07,2.6400132267557e-07,2.63729015999267e-07,2.63457130415763e-07,2.63185665057272e-07,2.62914619058243e-07,2.62643991555352e-07,2.62373781687497e-07,2.62103988595787e-07,2.61834611423541e-07,2.61565649316275e-07,2.61297101421699e-07,2.61028966889712e-07,2.60761244872389e-07,2.60493934523981e-07,2.60227035000903e-07,2.59960545461732e-07,2.59694465067196e-07,2.5942879298017e-07,2.59163528365671e-07,2.58898670390847e-07,2.58634218224973e-07,2.58370171039444e-07,2.58106528007771e-07,2.57843288305571e-07,2.5758045111056e-07,2.57318015602551e-07,2.57055980963445e-07,2.56794346377222e-07,2.56533111029941e-07,2.56272274109728e-07,2.56011834806771e-07,2.55751792313316e-07,2.55492145823657e-07,2.55232894534136e-07,2.54974037643127e-07,2.54715574351041e-07,2.54457503860311e-07,2.54199825375389e-07,2.53942538102742e-07,2.53685641250842e-07,2.53429134030164e-07,2.53173015653175e-07,2.52917285334334e-07,2.52661942290079e-07,2.52406985738827e-07,2.52152414900967e-07,2.51898228998849e-07,2.51644427256785e-07,2.51391008901038e-07,2.51137973159819e-07,2.50885319263279e-07,2.50633046443508e-07,2.50381153934519e-07,2.50129640972254e-07,2.49878506794571e-07,2.4962775064124e-07,2.49377371753937e-07,2.49127369376239e-07,2.48877742753617e-07,2.48628491133433e-07,2.48379613764931e-07,2.48131109899234e-07,2.47882978789334e-07,2.47635219690095e-07,2.47387831858237e-07,2.47140814552337e-07,2.46894167032824e-07,2.46647888561968e-07,2.4640197840388e-07,2.46156435824504e-07,2.45911260091611e-07,2.45666450474795e-07,2.45422006245467e-07,2.45177926676849e-07,2.4493421104397e-07,2.44690858623658e-07,2.44447868694538e-07,2.44205240537025e-07,2.43962973433317e-07,2.43721066667394e-07,2.43479519525008e-07,2.43238331293681e-07,2.42997501262697e-07,2.427570287231e-07,2.42516912967687e-07,2.42277153291001e-07,2.4203774898933e-07,2.41798699360699e-07,2.41560003704864e-07,2.4132166132331e-07,2.41083671519243e-07,2.40846033597588e-07,2.4060874686498e-07,2.40371810629761e-07,2.40135224201976e-07,2.39898986893366e-07,2.39663098017364e-07,2.39427556889092e-07,2.3919236282535e-07,2.38957515144618e-07,2.38723013167047e-07,2.38488856214456e-07,2.38255043610324e-07,2.3802157467979e-07,2.37788448749643e-07,2.37555665148322e-07,2.37323223205906e-07,2.37091122254116e-07,2.36859361626301e-07,2.36627940657443e-07,2.36396858684145e-07,2.36166115044629e-07,2.35935709078732e-07,2.35705640127899e-07,2.35475907535182e-07,2.35246510645231e-07,2.35017448804291e-07,2.34788721360199e-07,2.34560327662378e-07,2.34332267061831e-07,2.34104538911139e-07,2.33877142564455e-07,2.33650077377499e-07,2.33423342707555e-07,2.33196937913465e-07,2.32970862355623e-07,2.32745115395976e-07,2.32519696398014e-07,2.32294604726767e-07,2.32069839748802e-07,2.31845400832217e-07,2.31621287346638e-07,2.31397498663211e-07,2.31174034154603e-07,2.30950893194994e-07,2.30728075160074e-07,2.30505579427036e-07,2.30283405374577e-07,2.30061552382886e-07,2.29840019833649e-07,2.29618807110036e-07,2.29397913596703e-07,2.29177338679783e-07,2.28957081746886e-07,2.2873714218709e-07,2.28517519390943e-07,2.28298212750453e-07,2.28079221659086e-07,2.27860545511761e-07,2.2764218370485e-07,2.27424135636167e-07,2.2720640070497e-07,2.26988978311951e-07,2.26771867859237e-07,2.26555068750385e-07,2.26338580390375e-07,2.26122402185609e-07,2.25906533543904e-07,2.25690973874492e-07,2.25475722588012e-07,2.25260779096507e-07,2.25046142813424e-07,2.24831813153601e-07,2.24617789533274e-07,2.24404071370065e-07,2.24190658082979e-07,2.23977549092406e-07,2.23764743820109e-07,2.23552241689226e-07,2.23340042124262e-07,2.2312814455109e-07,2.2291654839694e-07,2.22705253090402e-07,2.2249425806142e-07,2.22283562741286e-07,2.22073166562639e-07,2.21863068959457e-07};
+
+
+static long aes_random(char *ctx);
+
+#define RANDOMNESS_BUFFER_SIZE 16
+
+#define RANDOMNESS_MAX
+
+#define SEED(ctx, s) aes_seed_context(ctx, s)
+
+#define RAND(ctx) (((double) ((unsigned long) aes_random(ctx)))/((double)ULONG_MAX))
+
+#define RANDOM(ctx, n) (( (unsigned long) aes_random(ctx)) % (n))
+
+static long
+get_degree0(long size, VALUE rnd_ctx)
+{
+ long rval = 1;
+ double d = RAND(RSTRING(rnd_ctx)->ptr) - P0[rval];
+ while (d > 0.0) {
+ rval ++;
+ d = d - P0[rval];
+ }
+ //printf("hehu: %f\n", d);
+ fflush(NULL);
+ if (rval > size)
+ return size;
+ else
+ return rval;
+}
+static long
+get_degree1(long size, VALUE rnd_ctx)
+{
+ long rval = 1;
+ double d = RAND(RSTRING(rnd_ctx)->ptr) - P1[rval];
+ while (d > 0.0) {
+ rval ++;
+ d = d - P1[rval];
+ }
+ //printf("hehu: %f\n", d);
+ fflush(NULL);
+ if (rval > size)
+ return size;
+ else
+ return rval;
+}
+
+
+long (*get_degree_func(long size))(long, VALUE)
+{
+ if (size < 1024)
+ return &get_degree0;
+ return &get_degree1;
+}
+
+
+static void
+aes_randomize_context(char *ctx)
+{
+ AES_KEY key;
+
+ AES_set_encrypt_key((unsigned char *) "0123456789012345", 128, &key);
+
+ AES_encrypt((unsigned char *) ctx + 4, (unsigned char *) ctx + 4, &key);
+ ( (long *) ctx )[0] = 0;
+}
+
+static void
+aes_seed_context(char *ctx, long seed)
+{
+ long tmp;
+
+ for (tmp = 1; tmp < ( (RANDOMNESS_BUFFER_SIZE / 4) + 1 ); tmp++) {
+ ( (long *) ctx )[tmp] = seed;
+ }
+ aes_randomize_context(ctx);
+}
+
+static long
+aes_random(char *ctx)
+{
+ long *long_ctx = (long *) ctx;
+ if (long_ctx[0] < (RANDOMNESS_BUFFER_SIZE / 4)) {
+ long return_value = long_ctx[long_ctx[0] + 1];
+ long_ctx[0]++;
+ return return_value;
+ } else {
+ aes_randomize_context(ctx);
+ return aes_random(ctx);
+ }
+
+}
+
+static VALUE
+get_aes_context()
+{
+ return rb_str_new(0, RANDOMNESS_BUFFER_SIZE + 4);
+}
+
+static char
+get_is_known(VALUE decode_status, long block_number)
+{
+ long byte_in_status = block_number / 8;
+ char bit_in_byte = 1 << (block_number % 8);
+ return ((RSTRING(decode_status)->ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
+}
+
+static void
+set_is_known(VALUE decode_status, long block_number)
+{
+ long byte_in_status = block_number / 8;
+ char bit_in_byte = 1 << (block_number % 8);
+ rb_str_modify(decode_status);
+ RSTRING(decode_status)->ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
+}
+
+static void
+set_value(VALUE aux_blocks, long index, char value, VALUE self, VALUE decode_status)
+{
+ if (index < RSTRING(self)->len) {
+ rb_str_modify(self);
+ RSTRING(self)->ptr[index] = value;
+ set_is_known(decode_status, index);
+ } else {
+ rb_str_modify(aux_blocks);
+ RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len] = value;
+ set_is_known(decode_status, index);
+ }
+}
+
+static char
+get_value(VALUE aux_blocks, long index, VALUE self)
+{
+ if (index < RSTRING(self)->len) {
+ return RSTRING(self)->ptr[index];
+ } else {
+ return RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len];
+ }
+}
+
+static char
+get_check_block(VALUE self, long seed, long index, VALUE aux_blocks, long (*degree_func)(long, VALUE), VALUE rnd_ctx)
+{
+ long degree;
+ int empty_block = 1;
+ char block;
+ char found_block;
+
+ //printf("creating check block %d:", index);
+
+ // Find [degree] blocks.
+ for (degree = degree_func(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
+ long block_number;
+ char found_block;
+
+ block_number = RANDOM(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len + RSTRING(aux_blocks)->len);
+ // Depending on whether the block is in our data or our own, debug about it
+ // and remember what it was.
+ if (block_number < RSTRING(self)->len) {
+ found_block = RSTRING(self)->ptr[block_number];
+ //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
+ } else {
+ found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
+ //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
+ }
+ // Create the block by xoring.
+ if (empty_block) {
+ block = found_block;
+ empty_block = 0;
+ } else {
+ block = block ^ found_block;
+ }
+ }
+ //printf(" => %d\n", block);
+ return block;
+}
+
+
+# line 286 "./lib/oneliner/superstring.rb"
+static VALUE _get_aes_context(VALUE self) {
+
+ return (get_aes_context());
+}
+
+
+# line 293 "./lib/oneliner/superstring.rb"
+static VALUE _aes_seed_context(VALUE self, VALUE _ctx, VALUE _s) {
+ char * ctx = STR2CSTR(_ctx);
+ long s = NUM2INT(_s);
+
+ aes_seed_context(ctx, s);
+return Qnil;
+}
+
+# line 300 "./lib/oneliner/superstring.rb"
+static VALUE _aes_random(VALUE self, VALUE _ctx) {
+ char * ctx = STR2CSTR(_ctx);
+
+ return INT2NUM(aes_random(ctx));
+}
+
+
+# line 307 "./lib/oneliner/superstring.rb"
+static VALUE _macro_rand(VALUE self, VALUE _ctx) {
+ char * ctx = STR2CSTR(_ctx);
+
+ return rb_float_new(RAND(ctx));
+}
+
+
+# line 314 "./lib/oneliner/superstring.rb"
+static VALUE _macro_random(VALUE self, VALUE _ctx, VALUE _lim) {
+ char * ctx = STR2CSTR(_ctx);
+ long lim = NUM2INT(_lim);
+
+ return INT2NUM(RANDOM(ctx, lim));
+}
+
+
+# line 325 "./lib/oneliner/superstring.rb"
+static VALUE _decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks) {
+ VALUE chunk = (_chunk);
+ VALUE decode_status = (_decode_status);
+ VALUE aux_blocks = (_aux_blocks);
+
+ long seed = ( (long *) RSTRING(chunk)->ptr )[0];
+ long size = ( (long *) RSTRING(chunk)->ptr )[1];
+ long tmp, tmp2;
+ char got_new_block = 0;
+ long (*degree_func)(long, VALUE) = get_degree_func(size);
+ VALUE rnd_ctx = get_aes_context();
+ SEED(RSTRING(rnd_ctx)->ptr, seed);
+ for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
+ long degree;
+ degree = degree_func(size, rnd_ctx);
+ if (degree == 1) {
+ long block_nr;
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
+ if (!get_is_known(decode_status, block_nr)) {
+ set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
+ got_new_block = 1;
+ } else {
+ }
+ } else {
+ long missing_blocks;
+ long missing_block;
+ char xor_sum = RSTRING(chunk)->ptr[tmp];
+
+ for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
+ long block_nr;
+
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
+ if (get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ } else {
+ missing_block = block_nr;
+ }
+ }
+ if (missing_blocks == 1) {
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ got_new_block = 1;
+ }
+ }
+ fflush(NULL);
+ }
+
+ return (got_new_block ? Qtrue : Qfalse);
+}
+
+
+# line 407 "./lib/oneliner/superstring.rb"
+static VALUE _fill_aux_blocks(VALUE self, VALUE _size, VALUE _q) {
+ long size = NUM2INT(_size);
+ long q = NUM2INT(_q);
+
+ char aux_blocks[size];
+ char initialized_aux_blocks[size];
+ long tmp, tmp2;
+ VALUE rnd_ctx = get_aes_context();
+
+ for (tmp = 0; tmp < size; tmp++)
+ initialized_aux_blocks[tmp] = 0;
+
+ SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
+ for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ for (tmp2 = 0; tmp2 < q; tmp2++) {
+ long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
+ if (initialized_aux_blocks[aux_block_nr]) {
+ aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
+ } else {
+ aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
+ initialized_aux_blocks[aux_block_nr] = 1;
+ }
+ }
+ }
+ rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
+return Qnil;
+}
+
+# line 445 "./lib/oneliner/superstring.rb"
+static VALUE _get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks) {
+ long chunk_size = NUM2INT(_chunk_size);
+ VALUE aux_blocks = (_aux_blocks);
+
+ unsigned long tmp;
+ long seed;
+ struct timeval tmp_timeval;
+ char chunk[chunk_size];
+ long (*degree_func)(long, VALUE) = get_degree_func(RSTRING(self)->len);
+ VALUE rnd_ctx = get_aes_context();
+ gettimeofday(&tmp_timeval, NULL);
+ srandom(tmp_timeval.tv_usec);
+ seed = random();
+
+ ( (long *) chunk) [0] = seed;
+ ( (long *) chunk) [1] = RSTRING(self)->len;
+ SEED(RSTRING(rnd_ctx)->ptr, seed);
+ for (tmp = 8; tmp < chunk_size; tmp++) {
+ chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func, rnd_ctx);
+ }
+
+ return (rb_str_new(chunk, chunk_size));
+}
+
+
+# line 479 "./lib/oneliner/superstring.rb"
+static VALUE _fill_aux_hash(VALUE self, VALUE _q, VALUE _size) {
+ long q = NUM2INT(_q);
+ long size = NUM2INT(_size);
+
+ long tmp, tmp2;
+ VALUE aux_ary = rb_ary_new();
+ VALUE set_func = rb_intern("[]=");
+ VALUE get_func = rb_intern("[]");
+ VALUE push_func = rb_intern("<<");
+ VALUE size_func = rb_intern("size");
+ VALUE rnd_ctx = get_aes_context();
+
+ SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
+ for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ for (tmp2 = 0; tmp2 < q; tmp2++) {
+ long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
+ VALUE data_blocks_for_this_aux_block;
+ if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
+ rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
+ rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2NUM(tmp));
+ }
+ }
+ for (tmp = 0; tmp < size; tmp++) {
+ VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
+ long number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
+ VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
+ for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
+ rb_str_modify(data_block_string);
+ ( (long *) RSTRING(data_block_string)->ptr )[tmp2] = (long) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
+ get_func,
+ 1,
+ INT2NUM(tmp2)));
+ }
+ rb_funcall(aux_ary, set_func, 2, INT2NUM(tmp), data_block_string);
+ }
+ rb_ivar_set(self, rb_intern("@_aux_hash"), aux_ary);
+return Qnil;
+}
+
+# line 531 "./lib/oneliner/superstring.rb"
+static VALUE _oneline_done(VALUE self, VALUE _decode_status) {
+ VALUE decode_status = (_decode_status);
+
+ long tmp;
+ if (decode_status == Qnil)
+ return (Qfalse);
+ for (tmp = 0; tmp < (RSTRING(decode_status)->len - 1); tmp++) {
+ if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != 255) {
+ return (Qfalse);
+ }
+ }
+ for (tmp = 0; tmp < (RSTRING(self)->len % 8); tmp++) {
+ if (! ( (unsigned char) RSTRING(self)->ptr[tmp] ) & (1 << tmp)) {
+ return (Qfalse);
+ }
+ }
+ return (Qtrue);
+}
+
+
+# line 554 "./lib/oneliner/superstring.rb"
+static VALUE _aux_decode(VALUE self, VALUE _decode_status, VALUE _aux_blocks, VALUE _aux_hash) {
+ VALUE decode_status = (_decode_status);
+ VALUE aux_blocks = (_aux_blocks);
+ VALUE aux_hash = (_aux_hash);
+
+ long tmp, tmp2;
+ char got_new_block = 0;
+ VALUE get_func = rb_intern("[]");
+ for (tmp = 0; tmp < RSTRING(aux_blocks)->len; tmp++) {
+ if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
+ VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
+ if (RSTRING(data_block_string)->len == 4) {
+ long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
+ if (!get_is_known(decode_status, block_nr)) {
+ set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
+ got_new_block = 1;
+ } else {
+ }
+ } else {
+ long missing_blocks;
+ long missing_block;
+ char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
+
+ for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
+ long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
+ if (get_is_known(decode_status, block_nr)) {
+ missing_blocks--;
+ xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ } else {
+ missing_block = block_nr;
+ }
+ }
+ if (missing_blocks == 1) {
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ got_new_block = 1;
+ }
+ }
+ }
+ }
+ fflush(NULL);
+
+ return (got_new_block ? Qtrue : Qfalse);
+}
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void Init_superstring_ext() {
+ VALUE c = rb_cObject;
+ c = rb_const_get_at(c,rb_intern("Oneliner"));
+ c = rb_const_get_at(c,rb_intern("SuperString"));
+ rb_define_method(c, "_aes_random", (VALUE(*)(ANYARGS))_aes_random, 1);
+ rb_define_method(c, "_aes_seed_context", (VALUE(*)(ANYARGS))_aes_seed_context, 2);
+ rb_define_method(c, "_aux_decode", (VALUE(*)(ANYARGS))_aux_decode, 3);
+ rb_define_method(c, "_decode_chunk", (VALUE(*)(ANYARGS))_decode_chunk, 3);
+ rb_define_method(c, "_fill_aux_blocks", (VALUE(*)(ANYARGS))_fill_aux_blocks, 2);
+ rb_define_method(c, "_fill_aux_hash", (VALUE(*)(ANYARGS))_fill_aux_hash, 2);
+ rb_define_method(c, "_get_aes_context", (VALUE(*)(ANYARGS))_get_aes_context, 0);
+ rb_define_method(c, "_get_chunk", (VALUE(*)(ANYARGS))_get_chunk, 2);
+ rb_define_method(c, "_macro_rand", (VALUE(*)(ANYARGS))_macro_rand, 1);
+ rb_define_method(c, "_macro_random", (VALUE(*)(ANYARGS))_macro_random, 2);
+ rb_define_method(c, "_oneline_done", (VALUE(*)(ANYARGS))_oneline_done, 1);
+
+ }
+#ifdef __cplusplus
+}
+#endif
+
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-22 23:03:05 UTC (rev 125)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-23 02:20:26 UTC (rev 126)
@@ -15,10 +15,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-require 'rubygems'
-require 'inline'
-require 'pp'
-
module Oneliner
#
@@ -26,607 +22,28 @@
#
class SuperString < String
- E = [0.1, 0.01]
- Q = [6, 3]
+ E = [0.05, 0.01]
+ Q = [3, 3]
THRESHOLDS = [1024]
- class << self
- private
- #
- # Get an F value for given epsilon value
- #
- def get_f(e)
- Math.log(e ** 2 / 4) / Math.log(1 - (e / 2))
- end
- #
- # Get a p distribution with a given name and epsilon value.
- #
- # Will return a C variable definition for this distribution.
- #
- def _get_p_distribution(name, e)
- f = get_f(e)
- rval = "double #{name}[] = {0.0,"
- p1 = 1 - ( (1 + (1 / f) ) / (1 + e) )
- 1.upto(f) do |n|
- if n == 1
- rval << "#{p1}"
- else
- rval << "#{( ( 1 - p1 ) * f ) / ( ( f - 1 ) * n * ( n - 1 ) )}"
- end
- rval << "," unless n + 1 > f
- end
- rval << "};\n"
- return rval
- end
- #
- # Get all the p distributions we want.
- #
- # Will return a C variable definition for this distribution.
- #
- def get_p_distribution
- rval = ""
- 0.upto(E.size - 1) do |n|
- rval << _get_p_distribution("P#{n}", E[n])
- end
- return rval
- end
- end
-
- inline do |builder|
- #
- # We need math.h
- #
- builder.include("")
- #
- # We need sys/time.h
- #
- builder.include("")
- #
- # We need limits.h
- #
- builder.include("")
- #
- # We need openssl/aes.h
- #
- builder.include("")
- #
- # Define the p distribution array so that it is easily accessible.
- #
- builder.prefix(get_p_distribution)
- #
- # Define a sane random number generator.
- #
- builder.prefix("static long aes_random(char *ctx);");
- builder.prefix("#define RANDOMNESS_BUFFER_SIZE 16")
- builder.prefix("#define RANDOMNESS_MAX ")
-# builder.prefix("#define SEED(ctx, s) srandom(s)")
-# builder.prefix("#define RAND(ctx) (((double)random())/((double)RAND_MAX+1))")
-# builder.prefix("#define RANDOM(ctx, n) (random() % (n))")
- builder.prefix("#define SEED(ctx, s) aes_seed_context(ctx, s)")
- builder.prefix("#define RAND(ctx) (((double) ((unsigned long) aes_random(ctx)))/((double)ULONG_MAX))")
- builder.prefix("#define RANDOM(ctx, n) (( (unsigned long) aes_random(ctx)) % (n))")
- #
- # Get a random degree.
- #
- # Will define as many get_degree{n} functions as we need.
- #
- degree_methods = ""
- 0.upto(E.size - 1) do |n|
- degree_methods += <ptr) - P#{n}[rval];
- while (d > 0.0) {
- rval ++;
- d = d - P#{n}[rval];
- }
- //printf("hehu: %f\\n", d);
- fflush(NULL);
- if (rval > size)
- return size;
- else
- return rval;
-}
-EOC
- end
- builder.prefix(degree_methods)
- #
- # Get the function to produce random degrees for us.
- #
- # Will go through our THRESHOLDS and return the proper degree-method.
- #
- get_degree_func = <ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
-}
-
-static void
-set_is_known(VALUE decode_status, long block_number)
-{
- long byte_in_status = block_number / 8;
- char bit_in_byte = 1 << (block_number % 8);
- rb_str_modify(decode_status);
- RSTRING(decode_status)->ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
-}
-
-static void
-set_value(VALUE aux_blocks, long index, char value, VALUE self, VALUE decode_status)
-{
- if (index < RSTRING(self)->len) {
- rb_str_modify(self);
- RSTRING(self)->ptr[index] = value;
- set_is_known(decode_status, index);
- } else {
- rb_str_modify(aux_blocks);
- RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len] = value;
- set_is_known(decode_status, index);
- }
-}
-
-static char
-get_value(VALUE aux_blocks, long index, VALUE self)
-{
- if (index < RSTRING(self)->len) {
- return RSTRING(self)->ptr[index];
- } else {
- return RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len];
- }
-}
-
-static char
-get_check_block(VALUE self, long seed, long index, VALUE aux_blocks, long (*degree_func)(long, VALUE), VALUE rnd_ctx)
-{
- long degree;
- int empty_block = 1;
- char block;
- char found_block;
-
- //printf("creating check block %d:", index);
-
- // Find [degree] blocks.
- for (degree = degree_func(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
- long block_number;
- char found_block;
-
- block_number = RANDOM(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len + RSTRING(aux_blocks)->len);
- // Depending on whether the block is in our data or our own, debug about it
- // and remember what it was.
- if (block_number < RSTRING(self)->len) {
- found_block = RSTRING(self)->ptr[block_number];
- //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
- } else {
- found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
- //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
- }
- // Create the block by xoring.
- if (empty_block) {
- block = found_block;
- empty_block = 0;
- } else {
- block = block ^ found_block;
- }
- }
- //printf(" => %d\\n", block);
- return block;
-}
-EOC
- #
- # A shortcut to the random functions for testing.
- #
- builder.c <ptr )[0];
- long size = ( (long *) RSTRING(chunk)->ptr )[1];
- long tmp, tmp2;
- char got_new_block = 0;
- long (*degree_func)(long, VALUE) = get_degree_func(size);
- VALUE rnd_ctx = get_aes_context();
-
- // Seed with our seed.
- SEED(RSTRING(rnd_ctx)->ptr, seed);
-
- // Go through the chunk.
- for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
- long degree;
-
- //printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
-
- // Get the degree of this chunk.
- degree = degree_func(size, rnd_ctx);
- // If it is degree 1 then we can deduce the data/aux block immediately.
- if (degree == 1) {
- long block_nr;
-
- // This block can be either from ourselves or from our aux blocks.
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
-
- //printf(" %d", block_nr);
-
- // If it is not already known, then set it as known. Otherwise just log about its state.
- if (!get_is_known(decode_status, block_nr)) {
- set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
- } else {
- //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
- }
- } else {
- // If it is NOT degree 1, then we go through all the blocks it is xored from
- // and see if we have exactly one missing.
- long missing_blocks;
- long missing_block;
- // Create the xor_sum with this block of the chunk.
- char xor_sum = RSTRING(chunk)->ptr[tmp];
-
- for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
- long block_nr;
-
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
-
- //printf(" %d", block_nr);
-
- // If the block we are looking at is known, then we decrement missing_blocks
- // and continue with our xor_sum.
- if (get_is_known(decode_status, block_nr)) {
- missing_blocks--;
- xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- //printf("!");
- } else {
- missing_block = block_nr;
- //printf("?");
- }
- }
- // If exactly one block is missing, set is as the final xor_sum.
- if (missing_blocks == 1) {
- set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", missing_block, xor_sum);
- }
- }
- //printf("\\n");
- fflush(NULL);
- }
-
- return got_new_block ? Qtrue : Qfalse;
-}
-EOC
- #
- # Fill our aux blocks with the proper data.
- #
- builder.c <ptr, RSTRING(self)->len);
-
- // For each block of our data.
- for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
- //printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
- // Create q blocks.
- for (tmp2 = 0; tmp2 < q; tmp2++) {
- long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
- //printf(" [%d]", aux_block_nr);
- // If this aux block is already initialized, just xor to it, otherwise set it.
- if (initialized_aux_blocks[aux_block_nr]) {
- aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
- } else {
- aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
- initialized_aux_blocks[aux_block_nr] = 1;
- }
- //printf(" => %d", aux_blocks[aux_block_nr]);
- }
- //printf("\\n");
- }
- rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
-}
-EOC
- #
- # Returns a chunk of coded data for a given message.
- #
- builder.c <len);
- VALUE rnd_ctx = get_aes_context();
-
- // Seed with timeofday
- gettimeofday(&tmp_timeval, NULL);
- srandom(tmp_timeval.tv_usec);
- // Get the seed for this chunk.
- seed = random();
-
- ( (long *) chunk) [0] = seed;
- ( (long *) chunk) [1] = RSTRING(self)->len;
-
- // Seed with our seed and the index of this block in the chunk.
- SEED(RSTRING(rnd_ctx)->ptr, seed);
-
- // Get the requested number of check blocks and append to this chunk.
- for (tmp = 8; tmp < chunk_size; tmp++) {
- chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func, rnd_ctx);
- }
-
- return rb_str_new(chunk, chunk_size);
-}
-EOC
- #
- # Create the @_aux_hash so that we know what data blocks each aux block represents.
- #
- builder.c <ptr, RSTRING(self)->len);
-
- // Go through all our blocks
- for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
- // And for each block q aux blocks.
- for (tmp2 = 0; tmp2 < q; tmp2++) {
- // And build an Array of the data blocks each aux block represents.
- long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
- VALUE data_blocks_for_this_aux_block;
- if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
- rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
- rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2NUM(tmp));
- }
- }
-
- // Then go through all our blocks again.
- for (tmp = 0; tmp < size; tmp++) {
- // Fetch the data blocks for this aux block.
- VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
- // Count them.
- long number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
- // Create a String that is 4 times the size.
- VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
- // And go through all q blocks per data block, again.
- for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
- // And make the String contain the data blocks for this aux block, as longs.
- rb_str_modify(data_block_string);
- ( (long *) RSTRING(data_block_string)->ptr )[tmp2] = (long) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
- get_func,
- 1,
- INT2NUM(tmp2)));
- }
- rb_funcall(aux_ary, set_func, 2, INT2NUM(tmp), data_block_string);
- }
- rb_ivar_set(self, rb_intern("@_aux_hash"), aux_ary);
-}
-EOC
- #
- # Returns whether the decoding is done.
- #
- builder.c <len - 1); tmp++) {
- if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != 255) {
- return Qfalse;
- }
- }
- for (tmp = 0; tmp < (RSTRING(self)->len % 8); tmp++) {
- if (! ( (unsigned char) RSTRING(self)->ptr[tmp] ) & (1 << tmp)) {
- return Qfalse;
- }
- }
- return Qtrue;
-}
-EOC
- #
- # Try to decode our data and aux blocks until we dont get any more data.
- #
- builder.c <len; tmp++) {
- // Only check those that are actually known.
- if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
-
- //printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
-
- // Fetch the String defining what data blocks this aux block is made out of.
- VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
-
- // If it is only one data block, then its easy.
- if (RSTRING(data_block_string)->len == 4) {
- long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
-
- //printf(" %d", block_nr);
-
- // If it is not already known, then make it known.
- if (!get_is_known(decode_status, block_nr)) {
- set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
- } else {
- //printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
- }
- } else {
- // If it is several data blocks, then we just go through them all to see if only
- // one of them is unknown.
- long missing_blocks;
- long missing_block;
- // Initialize the xor_sum as this aux_block.
- char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
-
- for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
- long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
-
- //printf(" %d", block_nr);
-
- // If it is a known data block, decrease missing_blocks and append to the xor_sum.
- if (get_is_known(decode_status, block_nr)) {
- missing_blocks--;
- xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- //printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
- } else {
- missing_block = block_nr;
- //printf("?");
- }
- }
- // If only one data block was unknown, then just set it to the built up xor_sum.
- if (missing_blocks == 1) {
- set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", missing_block, xor_sum);
- }
- }
- }
- }
- //printf("\\n");
- fflush(NULL);
-
- return got_new_block ? Qtrue : Qfalse;
-}
-EOC
- end
-
+ #
+ # Will return a chunk of check blocks for this SuperString.
+ #
+ # The chunk will have size +chunk_size+. Be aware that the first
+ # 8 bytes are used for metadata, so smaller chunks than that will
+ # result in errors.
+ #
def oneline_encode(chunk_size)
ensure_aux_blocks
return _get_chunk(chunk_size, @_aux_blocks)
end
+ #
+ # Will try to restore this SuperString from the given +chunk+.
+ #
+ # Will also remember the chunk for future reference if it was not
+ # enough to decode the entire SuperString.
+ #
def oneline_decode(chunk)
needed_size = chunk[4..7].unpack("L").first
@@ -650,16 +67,25 @@
return oneline_done
end
+ #
+ # Returns whether the decoding is done.
+ #
def oneline_done
return nil unless @_decode_status
return _oneline_done(@_decode_status)
end
+ #
+ # Returns the decode status of all bytes in this String.
+ #
def decode_status
return nil unless @_decode_status
@_decode_status.unpack("b*").first
end
+ #
+ # Returns the relative decode status of this entire String.
+ #
def decode_level
ones = 0
decode_status[0..(size + @_aux_blocks.size)].split(//).each do |s|
Modified: trunk/oneliner/lib/oneliner.rb
===================================================================
--- trunk/oneliner/lib/oneliner.rb 2006-12-22 23:03:05 UTC (rev 125)
+++ trunk/oneliner/lib/oneliner.rb 2006-12-23 02:20:26 UTC (rev 126)
@@ -17,3 +17,5 @@
$: << File.dirname(File.expand_path(__FILE__))
+require 'oneliner/superstring'
+require 'superstring_ext'
Modified: trunk/oneliner/tests/superstring_benchmark.rb
===================================================================
--- trunk/oneliner/tests/superstring_benchmark.rb 2006-12-22 23:03:05 UTC (rev 125)
+++ trunk/oneliner/tests/superstring_benchmark.rb 2006-12-23 02:20:26 UTC (rev 126)
@@ -4,10 +4,16 @@
class SuperStringTest < Test::Unit::TestCase
def test_decoding
- puts "required for 1024 blocks: #{required(10, 1024)}"
- puts "required for 2048 blocks: #{required(10, 2048)}"
- puts "required for 4096 blocks: #{required(10, 4096)}"
- puts "required for 8096 blocks: #{required(10, 8096)}"
+ puts "required for 16 blocks: #{required(100, 16)}"
+ puts "required for 32 blocks: #{required(100, 32)}"
+ puts "required for 64 blocks: #{required(100, 64)}"
+ puts "required for 128 blocks: #{required(100, 128)}"
+ puts "required for 256 blocks: #{required(100, 256)}"
+ puts "required for 512 blocks: #{required(100, 512)}"
+ puts "required for 1024 blocks: #{required(100, 1024)}"
+ puts "required for 2048 blocks: #{required(100, 2048)}"
+ puts "required for 4096 blocks: #{required(100, 4096)}"
+ puts "required for 8096 blocks: #{required(100, 8096)}"
end
private
@@ -16,7 +22,7 @@
total_req = 0
n.times do
s = Oneliner::SuperString.new
- s2 = Oneliner::SuperString.new(" " * 1024)
+ s2 = Oneliner::SuperString.new(" " * size)
total_req += measure_required(s, s2)
end
return total_req / n.to_f
@@ -26,7 +32,7 @@
total = source.size.to_f
used = source.size.to_f
dest.oneline_decode(source.oneline_encode(source.size))
- while (!dest.oneline_decode(source.oneline_encode(source.size.to_f * 0.1)))
+ while (!dest.oneline_decode(source.oneline_encode((source.size.to_f * 0.1) + 8)))
used += (source.size.to_f * 0.1)
end
return used/total
Modified: trunk/oneliner/tests/test_helper.rb
===================================================================
--- trunk/oneliner/tests/test_helper.rb 2006-12-22 23:03:05 UTC (rev 125)
+++ trunk/oneliner/tests/test_helper.rb 2006-12-23 02:20:26 UTC (rev 126)
@@ -5,7 +5,7 @@
require 'pp'
require 'test/unit'
require 'benchmark'
-require 'oneliner/superstring'
+require 'oneliner'
def bm(label = "", options = {})
n = options[:n] || 1000
From nobody at rubyforge.org Fri Dec 22 21:21:52 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 21:21:52 -0500 (EST)
Subject: [Archipelago-submits] [127] trunk/oneliner/ext: added license
Message-ID: <20061223022152.D08B75241DD0@rubyforge.org>
Revision: 127
Author: zond
Date: 2006-12-22 21:21:52 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
added license
Modified Paths:
--------------
trunk/oneliner/ext/extconf.rb
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/extconf.rb
===================================================================
--- trunk/oneliner/ext/extconf.rb 2006-12-23 02:20:26 UTC (rev 126)
+++ trunk/oneliner/ext/extconf.rb 2006-12-23 02:21:52 UTC (rev 127)
@@ -1,3 +1,20 @@
+# Archipelago - a distributed computing toolkit for ruby
+# Copyright (C) 2006 Martin Kihlgren
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
require 'mkmf'
def crash(s)
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 02:20:26 UTC (rev 126)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 02:21:52 UTC (rev 127)
@@ -1,3 +1,19 @@
+// Archipelago - a distributed computing toolkit for ruby
+// Copyright (C) 2006 Martin Kihlgren
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "ruby.h"
From nobody at rubyforge.org Fri Dec 22 21:23:23 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 21:23:23 -0500 (EST)
Subject: [Archipelago-submits] [128] trunk/oneliner: added a link
Message-ID: <20061223022323.537F15241DD0@rubyforge.org>
Revision: 128
Author: zond
Date: 2006-12-22 21:23:22 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
added a link
Modified Paths:
--------------
trunk/oneliner/README
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/README
===================================================================
--- trunk/oneliner/README 2006-12-23 02:21:52 UTC (rev 127)
+++ trunk/oneliner/README 2006-12-23 02:23:22 UTC (rev 128)
@@ -1,5 +1,7 @@
= This is Oneliner, an online code implementation for Ruby.
+See http://en.wikipedia.org/wiki/Online_codes
+
== Dependencies:
Oneliner::SuperString:: openssl: http://www.openssl.org/
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-23 02:21:52 UTC (rev 127)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-23 02:23:22 UTC (rev 128)
@@ -18,7 +18,7 @@
module Oneliner
#
- # Adds a few methods to String, some using the inline gem.
+ # A String subclass providing Online Code functionality.
#
class SuperString < String
From nobody at rubyforge.org Fri Dec 22 21:25:41 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 21:25:41 -0500 (EST)
Subject: [Archipelago-submits] [129]
trunk/archipelago/lib/archipelago/oneline.rb: removed oneline
since it got its own gem now
Message-ID: <20061223022541.7EDC25241CBF@rubyforge.org>
Revision: 129
Author: zond
Date: 2006-12-22 21:25:39 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
removed oneline since it got its own gem now
Removed Paths:
-------------
trunk/archipelago/lib/archipelago/oneline.rb
Deleted: trunk/archipelago/lib/archipelago/oneline.rb
===================================================================
--- trunk/archipelago/lib/archipelago/oneline.rb 2006-12-23 02:23:22 UTC (rev 128)
+++ trunk/archipelago/lib/archipelago/oneline.rb 2006-12-23 02:25:39 UTC (rev 129)
@@ -1,641 +0,0 @@
-# Archipelago - a distributed computing toolkit for ruby
-# Copyright (C) 2006 Martin Kihlgren
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'rubygems'
-require 'inline'
-require 'pp'
-
-#
-# Adds a few methods to String, some using the inline gem.
-#
-class String
-
- E = [0.1, 0.01]
- Q = [6, 3]
- THRESHOLDS = [1024]
-
- class << self
- private
- #
- # Get an F value for given epsilon value
- #
- def get_f(e)
- Math.log(e ** 2 / 4) / Math.log(1 - (e / 2))
- end
- #
- # Get a p distribution with a given name and epsilon value.
- #
- # Will return a C variable definition for this distribution.
- #
- def _get_p_distribution(name, e)
- f = get_f(e)
- rval = "double #{name}[] = {0.0,"
- p1 = 1 - ( (1 + (1 / f) ) / (1 + e) )
- 1.upto(f) do |n|
- if n == 1
- rval << "#{p1}"
- else
- rval << "#{( ( 1 - p1 ) * f ) / ( ( f - 1 ) * n * ( n - 1 ) )}"
- end
- rval << "," unless n + 1 > f
- end
- rval << "};\n"
- return rval
- end
- #
- # Get all the p distributions we want.
- #
- # Will return a C variable definition for this distribution.
- #
- def get_p_distribution
- rval = ""
- 0.upto(E.size - 1) do |n|
- rval << _get_p_distribution("P#{n}", E[n])
- end
- return rval
- end
- end
-
- inline do |builder|
- #
- # We need math.h
- #
- builder.include("")
- #
- # We need sys/time.h
- #
- builder.include("")
- #
- # Define the p distribution array so that it is easily accessible.
- #
- builder.prefix(get_p_distribution)
- #
- # Define a sane random number generator.
- #
- builder.prefix("#define RAND (((double)random())/((double)RAND_MAX+1))")
- builder.prefix("#define RANDOM(n) (random() % (n))")
- #
- # Get a random degree.
- #
- # Will define as many get_degree{n} functions as we need.
- #
- degree_methods = ""
- 0.upto(E.size - 1) do |n|
- degree_methods += < 0.0) {
- rval ++;
- d = d - P#{n}[rval];
- }
- if (rval > size)
- return size;
- else
- return rval;
-}
-EOC
- end
- builder.prefix(degree_methods)
- #
- # Get the function to produce random degrees for us.
- #
- # Will go through our THRESHOLDS and return the proper degree-method.
- #
- get_degree_func = <ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
-}
-EOC
- #
- # Set that a certain block is known.
- #
- builder.prefix <ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
-}
-EOC
- #
- # Returns whether this String is decoded enough.
- #
- # Will first go through our decode_status one byte a time
- # and then check the relevant bits of the last byte.
- #
- builder.c <len - 1); tmp++) {
- if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != 255) {
- return Qfalse;
- }
- }
- for (tmp = 0; tmp < (RSTRING(self)->len % 8); tmp++) {
- if (! ( (unsigned char) RSTRING(self)->ptr[tmp] ) & (1 << tmp)) {
- return Qfalse;
- }
- }
- return Qtrue;
-}
-EOC
- #
- # Set a data or aux block with a known value.
- #
- # Will both update ourselves or our aux_blocks depending on index,
- # then set the decode_status so that this byte is officially known.
- #
- builder.prefix <len) {
- rb_str_modify(self);
- RSTRING(self)->ptr[index] = value;
- set_is_known(decode_status, index);
- } else {
- rb_str_modify(aux_blocks);
- RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len] = value;
- set_is_known(decode_status, index);
- }
-}
-EOC
- #
- # Get a data or aux block.
- #
- # Gets from ourselves or our aux_blocks depending on the index.
- #
- builder.prefix <len) {
- return RSTRING(self)->ptr[index];
- } else {
- return RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len];
- }
-}
-EOC
- #
- # Decode the given chunk until we dont get any new
- # data from it.
- #
- builder.c <ptr )[0];
- long size = ( (long *) RSTRING(chunk)->ptr )[1];
- long tmp, tmp2;
- char got_new_block = 0;
- long (*degree_func)() = get_degree_func(size);
-
- // Go through the chunk.
- for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
- long degree;
-
- // Seed with our seed and the index in the chunk.
- srandom(seed + tmp);
-
- //printf("looking at check block %d(%d):", tmp, RSTRING(chunk)->ptr[tmp]);
-
- // Get the degree of this chunk.
- degree = degree_func(size);
- // If it is degree 1 then we can deduce the data/aux block immediately.
- if (degree == 1) {
- long block_nr;
-
- // Seed with our seed, the chunk index and the degree.
- srandom(seed + tmp + degree);
-
- // This block can be either from ourselves or from our aux blocks.
- block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
-
- //printf(" %d", block_nr);
-
- // If it is not already known, then set it as known. Otherwise just log about its state.
- if (!get_is_known(decode_status, block_nr)) {
- set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
- } else {
- //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
- }
- } else {
- // If it is NOT degree 1, then we go through all the blocks it is xored from
- // and see if we have exactly one missing.
- long missing_blocks;
- long missing_block;
- // Create the xor_sum with this block of the chunk.
- char xor_sum = RSTRING(chunk)->ptr[tmp];
-
- for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
- long block_nr;
-
- srandom(seed + tmp + tmp2);
-
- block_nr = RANDOM(size + RSTRING(aux_blocks)->len);
-
- //printf(" %d", block_nr);
-
- // If the block we are looking at is known, then we decrement missing_blocks
- // and continue with our xor_sum.
- if (get_is_known(decode_status, block_nr)) {
- missing_blocks--;
- xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- //printf("!");
- } else {
- missing_block = block_nr;
- //printf("?");
- }
- }
- // If exactly one block is missing, set is as the final xor_sum.
- if (missing_blocks == 1) {
- set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", missing_block, xor_sum);
- }
- }
- //printf("\\n");
- fflush(NULL);
- }
-
- return got_new_block ? Qtrue : Qfalse;
-}
-EOC
- #
- # Get a check block from a message.
- #
- builder.prefix <len); degree > 0; degree--) {
- long block_number;
- char found_block;
-
- // Seed with our seed, the index in the chunk, and the degree.
- srandom(seed + index + degree);
-
- block_number = RANDOM(RSTRING(self)->len + RSTRING(aux_blocks)->len);
- // Depending on whether the block is in our data or our own, debug about it
- // and remember what it was.
- if (block_number < RSTRING(self)->len) {
- found_block = RSTRING(self)->ptr[block_number];
- //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
- } else {
- found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
- //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
- }
- // Create the block by xoring.
- if (empty_block) {
- block = found_block;
- empty_block = 0;
- } else {
- block = block ^ found_block;
- }
- }
- //printf(" => %d\\n", block);
- return block;
-}
-EOC
- #
- # Fill our aux blocks with the proper data.
- #
- builder.c <len);
-
- // For each block of our data.
- for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
- //printf("creating aux blocks for d[%d](%d):", tmp, RSTRING(self)->ptr[tmp]);
- // Create q blocks.
- for (tmp2 = 0; tmp2 < q; tmp2++) {
- long aux_block_nr = RANDOM(size);
- //printf(" [%d]", aux_block_nr);
- // If this aux block is already initialized, just xor to it, otherwise set it.
- if (initialized_aux_blocks[aux_block_nr]) {
- aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
- } else {
- aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
- initialized_aux_blocks[aux_block_nr] = 1;
- }
- //printf(" => %d", aux_blocks[aux_block_nr]);
- }
- //printf("\\n");
- }
- rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
-}
-EOC
- #
- # Returns a chunk of coded data for a given message.
- #
- builder.c <len);
-
- // Seed with timeofday
- gettimeofday(&tmp_timeval, NULL);
- srandom(tmp_timeval.tv_usec);
- // Get the seed for this chunk.
- seed = random();
-
- ( (long *) chunk) [0] = seed;
- ( (long *) chunk) [1] = RSTRING(self)->len;
-
- // Get the requested number of check blocks and append to this chunk.
- for (tmp = 8; tmp < chunk_size; tmp++) {
- chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func);
- }
-
- return rb_str_new(chunk, chunk_size);
-}
-EOC
- #
- # Create the @_aux_hash so that we know what data blocks each aux block represents.
- #
- builder.c <len);
-
- // Go through all our blocks
- for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
- // And for each block q aux blocks.
- for (tmp2 = 0; tmp2 < q; tmp2++) {
- // And build an Array of the data blocks each aux block represents.
- long aux_block_nr = RANDOM(size);
- VALUE data_blocks_for_this_aux_block;
- if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
- rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
- rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2NUM(tmp));
- }
- }
-
- // Then go through all our blocks again.
- for (tmp = 0; tmp < size; tmp++) {
- // Fetch the data blocks for this aux block.
- VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
- // Count them.
- long number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
- // Create a String that is 4 times the size.
- VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
- // And go through all q blocks per data block, again.
- for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
- // And make the String contain the data blocks for this aux block, as longs.
- rb_str_modify(data_block_string);
- ( (long *) RSTRING(data_block_string)->ptr )[tmp2] = (long) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
- get_func,
- 1,
- INT2NUM(tmp2)));
- }
- rb_funcall(aux_ary, set_func, 2, INT2NUM(tmp), data_block_string);
- }
- rb_ivar_set(self, rb_intern("@_aux_hash"), aux_ary);
-}
-EOC
- #
- # Try to decode our data and aux blocks until we dont get any more data.
- #
- builder.c <len; tmp++) {
- // Only check those that are actually known.
- if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
-
- //printf("looking at aux block %d(%d): ", tmp, RSTRING(aux_blocks)->ptr[tmp]);
-
- // Fetch the String defining what data blocks this aux block is made out of.
- VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
-
- // If it is only one data block, then its easy.
- if (RSTRING(data_block_string)->len == 4) {
- long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
-
- //printf(" %d", block_nr);
-
- // If it is not already known, then make it known.
- if (!get_is_known(decode_status, block_nr)) {
- set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
- } else {
- //printf(" [%d]=%d", block_nr, RSTRING(aux_blocks)->ptr[tmp]);
- }
- } else {
- // If it is several data blocks, then we just go through them all to see if only
- // one of them is unknown.
- long missing_blocks;
- long missing_block;
- // Initialize the xor_sum as this aux_block.
- char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
-
- for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
- long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
-
- //printf(" %d", block_nr);
-
- // If it is a known data block, decrease missing_blocks and append to the xor_sum.
- if (get_is_known(decode_status, block_nr)) {
- missing_blocks--;
- xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
- //printf("!(%d)->(%d)", get_value(aux_blocks, block_nr, self), xor_sum);
- } else {
- missing_block = block_nr;
- //printf("?");
- }
- }
- // If only one data block was unknown, then just set it to the built up xor_sum.
- if (missing_blocks == 1) {
- set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
- got_new_block = 1;
- //printf(" => [%d]=%d", missing_block, xor_sum);
- }
- }
- }
- }
- //printf("\\n");
- fflush(NULL);
-
- return got_new_block ? Qtrue : Qfalse;
-}
-EOC
- end
-
- def oneline_encode(chunk_size)
- ensure_aux_blocks
- return _get_chunk(chunk_size, @_aux_blocks)
- end
-
- def oneline_decode(chunk)
-
- needed_size = chunk[4..7].unpack("L").first
- if size == 0
- concat("\000" * needed_size)
- elsif size != needed_size
- raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
- end
-
- @_decode_status ||= "\000" * (((needed_size + get_aux_blocks) / 8) + 1)
- @_known_chunks ||= []
- @_aux_blocks ||= "\000" * get_aux_blocks
-
- found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks)
- do_decode if found_new_block
-
- @_known_chunks.unshift(chunk)
-
- nil while do_decode
-
- return oneline_done
- end
-
- def oneline_done
- return nil unless @_decode_status
- return _oneline_done(@_decode_status)
- end
-
- def decode_status
- return nil unless @_decode_status
- @_decode_status.unpack("b*").first
- end
-
- def decode_level
- ones = 0
- decode_status[0..(size + @_aux_blocks.size)].split(//).each do |s|
- ones += 1 if s == "1"
- end
- ones.to_f / (size + @_aux_blocks.size).to_f
- end
-
- private
-
- def get_aux_blocks
- (self.size * (get_q * get_e * 0.55)).ceil
- end
-
- def get_q
- 0.upto(THRESHOLDS.size - 1) do |n|
- if size < THRESHOLDS[n]
- return Q[n]
- end
- end
- return Q.last
- end
-
- def do_decode
- found_new_block = false
- @_known_chunks.each do |known_chunk|
- found_new_block = _decode_chunk(known_chunk, @_decode_status, @_aux_blocks) || found_new_block
- end
- ensure_aux_hash
- found_new_block = _aux_decode(@_decode_status, @_aux_blocks, @_aux_hash) || found_new_block
- return found_new_block
- end
-
- def get_e
- 0.upto(THRESHOLDS.size - 1) do |n|
- if size < THRESHOLDS[n]
- return E[n]
- end
- end
- return E.last
- end
-
- def ensure_aux_blocks
- _fill_aux_blocks(get_aux_blocks, get_q) unless @_aux_blocks
- end
-
- def ensure_aux_hash
- _fill_aux_hash(get_q, get_aux_blocks) unless @_aux_hash
- end
-
-end
From nobody at rubyforge.org Fri Dec 22 21:31:29 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 21:31:29 -0500 (EST)
Subject: [Archipelago-submits] [130] trunk/hyperactive: removed a lot of
unnecessary requires
Message-ID: <20061223023129.76BA65241DCF@rubyforge.org>
Revision: 130
Author: zond
Date: 2006-12-22 21:31:29 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
removed a lot of unnecessary requires
Modified Paths:
--------------
trunk/hyperactive/lib/hyperactive/hash.rb
trunk/hyperactive/lib/hyperactive/index.rb
trunk/hyperactive/lib/hyperactive/list.rb
trunk/hyperactive/lib/hyperactive/record.rb
trunk/hyperactive/lib/hyperactive.rb
trunk/hyperactive/tests/test_helper.rb
Modified: trunk/hyperactive/lib/hyperactive/hash.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-23 02:25:39 UTC (rev 129)
+++ trunk/hyperactive/lib/hyperactive/hash.rb 2006-12-23 02:31:29 UTC (rev 130)
@@ -17,7 +17,9 @@
require 'rubygems'
-require 'archipelago'
+require 'archipelago/pirate'
+require 'hyperactive/list'
+require 'hyperactive/cleaner'
require 'digest/sha1'
module Hyperactive
Modified: trunk/hyperactive/lib/hyperactive/index.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/index.rb 2006-12-23 02:25:39 UTC (rev 129)
+++ trunk/hyperactive/lib/hyperactive/index.rb 2006-12-23 02:31:29 UTC (rev 130)
@@ -15,6 +15,9 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+require 'hyperactive/hash'
+require 'hyperactive/hooker'
+
module Hyperactive
#
Modified: trunk/hyperactive/lib/hyperactive/list.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/list.rb 2006-12-23 02:25:39 UTC (rev 129)
+++ trunk/hyperactive/lib/hyperactive/list.rb 2006-12-23 02:31:29 UTC (rev 130)
@@ -15,10 +15,9 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+require 'hyperactive/record'
+require 'archipelago/current'
-require 'rubygems'
-require 'archipelago'
-
module Hyperactive
#
Modified: trunk/hyperactive/lib/hyperactive/record.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive/record.rb 2006-12-23 02:25:39 UTC (rev 129)
+++ trunk/hyperactive/lib/hyperactive/record.rb 2006-12-23 02:31:29 UTC (rev 130)
@@ -15,9 +15,17 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+module Hyperactive
+ module Record
+ class Bass
+ end
+ end
+end
require 'rubygems'
-require 'archipelago'
+require 'archipelago/pirate'
+require 'hyperactive/index'
+require 'hyperactive/transactions'
#
# A utility module to provide the functionality required for example
Modified: trunk/hyperactive/lib/hyperactive.rb
===================================================================
--- trunk/hyperactive/lib/hyperactive.rb 2006-12-23 02:25:39 UTC (rev 129)
+++ trunk/hyperactive/lib/hyperactive.rb 2006-12-23 02:31:29 UTC (rev 130)
@@ -17,10 +17,3 @@
$: << File.dirname(__FILE__)
-require 'hyperactive/hooker'
-require 'hyperactive/index'
-require 'hyperactive/transactions'
-require 'hyperactive/cleaner'
-require 'hyperactive/record'
-require 'hyperactive/hash'
-require 'hyperactive/list'
Modified: trunk/hyperactive/tests/test_helper.rb
===================================================================
--- trunk/hyperactive/tests/test_helper.rb 2006-12-23 02:25:39 UTC (rev 129)
+++ trunk/hyperactive/tests/test_helper.rb 2006-12-23 02:31:29 UTC (rev 130)
@@ -3,6 +3,7 @@
$: << File.join(home, "..", "lib")
require 'hyperactive'
+require 'hyperactive/record'
require 'pp'
require 'test/unit'
require 'benchmark'
From nobody at rubyforge.org Fri Dec 22 21:34:28 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 21:34:28 -0500 (EST)
Subject: [Archipelago-submits] [131] trunk/oneliner/Rakefile: removed a bad
dependency
Message-ID: <20061223023428.3920D5241DDD@rubyforge.org>
Revision: 131
Author: zond
Date: 2006-12-22 21:34:28 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
removed a bad dependency
Modified Paths:
--------------
trunk/oneliner/Rakefile
Modified: trunk/oneliner/Rakefile
===================================================================
--- trunk/oneliner/Rakefile 2006-12-23 02:31:29 UTC (rev 130)
+++ trunk/oneliner/Rakefile 2006-12-23 02:34:28 UTC (rev 131)
@@ -15,7 +15,6 @@
s.summary = "An online code implementation for ruby."
s.files = FileList['lib/**/*.rb', 'tests/*', 'ext/*', 'GPL-2'].to_a
s.require_path = "lib"
- s.add_dependency('RubyInline', '>= 3.6.2')
s.extensions << 'ext/extconf.rb'
s.autorequire = "oneliner"
s.test_files = Dir.glob('tests/*_test.rb') + Dir.glob('tests/test_helper.rb')
From nobody at rubyforge.org Fri Dec 22 22:07:04 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Fri, 22 Dec 2006 22:07:04 -0500 (EST)
Subject: [Archipelago-submits] [132] trunk/oneliner/ext: trying to make it
work on linux
Message-ID: <20061223030704.2619F5241DDC@rubyforge.org>
Revision: 132
Author: zond
Date: 2006-12-22 22:07:03 -0500 (Fri, 22 Dec 2006)
Log Message:
-----------
trying to make it work on linux
Modified Paths:
--------------
trunk/oneliner/ext/extconf.rb
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/extconf.rb
===================================================================
--- trunk/oneliner/ext/extconf.rb 2006-12-23 02:34:28 UTC (rev 131)
+++ trunk/oneliner/ext/extconf.rb 2006-12-23 03:07:03 UTC (rev 132)
@@ -30,4 +30,4 @@
dir_config("superstring_ext")
-create_makefile("oneliner/superstring_ext")
+create_makefile("superstring_ext")
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 02:34:28 UTC (rev 131)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 03:07:03 UTC (rev 132)
@@ -50,8 +50,6 @@
rval ++;
d = d - P0[rval];
}
- //printf("hehu: %f\n", d);
- fflush(NULL);
if (rval > size)
return size;
else
@@ -66,8 +64,6 @@
rval ++;
d = d - P1[rval];
}
- //printf("hehu: %f\n", d);
- fflush(NULL);
if (rval > size)
return size;
else
@@ -172,8 +168,7 @@
{
long degree;
int empty_block = 1;
- char block;
- char found_block;
+ char block = 0;
//printf("creating check block %d:", index);
@@ -205,14 +200,12 @@
}
-# line 286 "./lib/oneliner/superstring.rb"
static VALUE _get_aes_context(VALUE self) {
return (get_aes_context());
}
-# line 293 "./lib/oneliner/superstring.rb"
static VALUE _aes_seed_context(VALUE self, VALUE _ctx, VALUE _s) {
char * ctx = STR2CSTR(_ctx);
long s = NUM2INT(_s);
@@ -221,7 +214,6 @@
return Qnil;
}
-# line 300 "./lib/oneliner/superstring.rb"
static VALUE _aes_random(VALUE self, VALUE _ctx) {
char * ctx = STR2CSTR(_ctx);
@@ -229,7 +221,6 @@
}
-# line 307 "./lib/oneliner/superstring.rb"
static VALUE _macro_rand(VALUE self, VALUE _ctx) {
char * ctx = STR2CSTR(_ctx);
@@ -237,7 +228,6 @@
}
-# line 314 "./lib/oneliner/superstring.rb"
static VALUE _macro_random(VALUE self, VALUE _ctx, VALUE _lim) {
char * ctx = STR2CSTR(_ctx);
long lim = NUM2INT(_lim);
@@ -245,60 +235,66 @@
return INT2NUM(RANDOM(ctx, lim));
}
-
-# line 325 "./lib/oneliner/superstring.rb"
static VALUE _decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks) {
VALUE chunk = (_chunk);
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
-
long seed = ( (long *) RSTRING(chunk)->ptr )[0];
long size = ( (long *) RSTRING(chunk)->ptr )[1];
long tmp, tmp2;
char got_new_block = 0;
long (*degree_func)(long, VALUE) = get_degree_func(size);
VALUE rnd_ctx = get_aes_context();
+
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
long degree;
+
+ //printf("looking at check block %d:", tmp);
+
degree = degree_func(size, rnd_ctx);
if (degree == 1) {
long block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
+ //printf(" %d", block_nr);
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
got_new_block = 1;
+ //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
} else {
+ //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
}
} else {
long missing_blocks;
- long missing_block;
+ long missing_block = 0;
char xor_sum = RSTRING(chunk)->ptr[tmp];
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
long block_nr;
-
+ //printf(" %d", block_nr);
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
if (get_is_known(decode_status, block_nr)) {
missing_blocks--;
xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ //printf("!");
} else {
missing_block = block_nr;
+ //printf("?");
}
}
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
got_new_block = 1;
+ //printf(" => [%d]=%d", missing_block, xor_sum);
}
}
+ //printf("\n");
fflush(NULL);
}
return (got_new_block ? Qtrue : Qfalse);
}
-
-# line 407 "./lib/oneliner/superstring.rb"
static VALUE _fill_aux_blocks(VALUE self, VALUE _size, VALUE _q) {
long size = NUM2INT(_size);
long q = NUM2INT(_q);
@@ -327,7 +323,6 @@
return Qnil;
}
-# line 445 "./lib/oneliner/superstring.rb"
static VALUE _get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks) {
long chunk_size = NUM2INT(_chunk_size);
VALUE aux_blocks = (_aux_blocks);
@@ -353,7 +348,6 @@
}
-# line 479 "./lib/oneliner/superstring.rb"
static VALUE _fill_aux_hash(VALUE self, VALUE _q, VALUE _size) {
long q = NUM2INT(_q);
long size = NUM2INT(_size);
@@ -393,7 +387,6 @@
return Qnil;
}
-# line 531 "./lib/oneliner/superstring.rb"
static VALUE _oneline_done(VALUE self, VALUE _decode_status) {
VALUE decode_status = (_decode_status);
@@ -414,7 +407,6 @@
}
-# line 554 "./lib/oneliner/superstring.rb"
static VALUE _aux_decode(VALUE self, VALUE _decode_status, VALUE _aux_blocks, VALUE _aux_hash) {
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
@@ -435,7 +427,7 @@
}
} else {
long missing_blocks;
- long missing_block;
+ long missing_block = 0;
char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
From nobody at rubyforge.org Sat Dec 23 08:21:17 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 23 Dec 2006 08:21:17 -0500 (EST)
Subject: [Archipelago-submits] [133] trunk/oneliner/ext/superstring_ext.c:
changed from long to int to support 64 bit architecture
Message-ID: <20061223132117.4949A5240CBD@rubyforge.org>
Revision: 133
Author: zond
Date: 2006-12-23 08:21:16 -0500 (Sat, 23 Dec 2006)
Log Message:
-----------
changed from long to int to support 64 bit architecture
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 03:07:03 UTC (rev 132)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 13:21:16 UTC (rev 133)
@@ -29,7 +29,7 @@
double P1[] = {0.0,0.00943264209782069,0.49551807459988,0.165172691533293,0.0825863457666466,0.049551807459988,0.0330345383066586,0.0235960987904705,0.0176970740928528,0.0137643909611078,0.0110115127688862,0.00900941953817963,0.00750784961514969,0.00635279582820358,0.00544525356703164,0.00471921975809409,0.00412931728833233,0.00364351525441088,0.003238680226143,0.00289776651812795,0.00260798986631516,0.00235960987904705,0.00214509989004277,0.00195856946482166,0.00179535534275319,0.00165172691533293,0.00152467099876886,0.00141173240626746,0.00131089437724836,0.00122048786847261,0.00113912201057444,0.00106563026795673,0.000999028376209435,0.000938481201893711,0.000883276425311728,0.000832803486722487,0.000786536626349015,0.000744021133032852,0.000704862126031123,0.000668715350337219,0.000635279582820358,0.000604290334877902,0.000575514604645621,0.000548746483499313,0.000523803461522071,0.000500523307676646,0.000478761424734183,0.00045838859814975,0.000439289073226844,0.000421358906972687,0.000404504550693779,0.00038864162713716,0.00037369387224727,0.000359592216690769,0.000346273986442963,0.000333682205117764,0.000321764983506415,0.000310474984085138,0.000299768950151167,0.000289607290824009,0.000279953714463209,0.00027077490415294,0.000262040229825425,0.00025372149237065,0.000245792695734067,0.000238229843557634,0.000231010757389221,0.000224114913885065,0.000217523298770799,0.000211218275618022,0.000205183467743221,0.000199403651750455,0.000193864661424053,0.000188553300837093,0.000183457265679333,0.000178565071927885,0.000173865991087677,0.000169349991319166,0.000165007683849444,0.000160830274131736,0.000156809517278443,0.000152937677345642,0.000149207490093309,0.000145612128886241,0.000142145173436569,0.000138800581120414,0.000135572660629242,0.000132456047741213,0.000129445683019822,0.000126536791266568,0.000123724862571755,0.000121005634822925,0.000118375077544166,0.000115829376951819,0.000113364922123056,0.000110978292183624,0.000108666244429798,0.000106425703307534,0.000104253750178809,0.00010214761381156,0.000100104661535329,9.81223910098771e-05,9.61984225587031e-05,9.43304920235826e-05,9.25164441000522e-05,9.07542261171941e-05,8.90418822281904e-05,8.73775479809345e-05,8.57594452405468e-05,8.4185877437968e-05,8.2655225120914e-05,8.11659417854021e-05,7.97165499678056e-05,7.83056375789949e-05,7.69318544635739e-05,7.55939091685552e-05,7.42905659070284e-05,7.30206417034895e-05,7.17830037085151e-05,7.05765666713972e-05,6.94002905602072e-05,6.82531783195426e-05,6.71342737569272e-05,6.60426595494975e-05,6.49774553632153e-05,6.39378160774038e-05,6.29229301079212e-05,6.19320178227571e-05,6.09643300442765e-05,6.00191466327373e-05,5.90957751460799e-05,5.81935495713305e-05,5.73118291232801e-05,5.64499971063886e-05,5.5607459836144e-05,5.47836456163493e-05,5.39780037690501e-05,5.31900037140274e-05,5.24191340949836e-05,5.1664901949732e-05,5.09268319218787e-05,5.02044655116393e-05,4.9497360363588e-05,4.88050895892721e-05,4.81272411227544e-05,4.74634171072682e-05,4.68132333112782e-05,4.61763185723492e-05,4.55523142673175e-05,4.49408738073535e-05,4.43416621565888e-05,4.37543553730578e-05,4.31786401707807e-05,4.26142135018816e-05,4.20607821577013e-05,4.15180623879246e-05,4.09857795367973e-05,4.04636676955642e-05,3.99514693703039e-05,3.94489351643882e-05,3.89558234748333e-05,3.8471900201854e-05,3.79969384709669e-05,3.75307183670287e-05,3.70730266796259e-05,3.66236566592668e-05,3.61824077838539e-05,3.57490855349455e-05,3.5323501183339e-05,3.49054715835362e-05,3.4494818976671e-05,3.40913708015053e-05,3.36949595131157e-05,3.33054224089178e-05,3.29226014616889e-05,3.25463431592696e-05,3.21764983506415e-05,3.18129220980919e-05,3.1455473535192e-05,3.11040157303295e-05,3.07584155555481e-05,3.04185435604592e-05,3.00842738510036e-05,2.97554839728505e-05,2.94320547992326e-05,2.91138704230246e-05,2.88008180528846e-05,2.84927879132816e-05,2.81896731482467e-05,2.78913697286885e-05,2.75977763631233e-05,2.7308794411677e-05,2.70243278032221e-05,2.67442829555203e-05,2.64685686982469e-05,2.61970961987777e-05,2.59297788906269e-05,2.56665324044276e-05,2.54072745013526e-05,2.51519250088767e-05,2.49004057587879e-05,2.46526405273572e-05,2.44085549775814e-05,2.4168076603418e-05,2.39311346759335e-05,2.36976601912903e-05,2.3467585820501e-05,2.32408458608827e-05,2.30173761891434e-05,2.27971142160416e-05,2.25799988425555e-05,2.23659704175075e-05,2.21549706965877e-05,2.1946942802723e-05,2.17418311877443e-05,2.15395815953001e-05,2.13401410249733e-05,2.11434576975542e-05,2.09494810214298e-05,2.07581615600469e-05,2.05694510004101e-05,2.03833021225783e-05,2.01996687701227e-05,2.00185058215117e-05,1.98397691623911e-05,1.96634156587254e-05,1.94894031307721e-05,1.93176903278578e-05,1.91482369039292e-05,1.89810033938512e-05,1.88159511904264e-05,1.8653042522111e-05,1.84922404314032e-05,1.83335087538804e-05,1.81768120978643e-05,1.8022115824691e-05,1.78693860295665e-05,1.77185895229879e-05,1.75696938127107e-05,1.74226670862445e-05,1.72774781938591e-05,1.71340966320844e-05,1.6992492527687e-05,1.68526366221093e-05,1.67145002563543e-05,1.65780553563024e-05,1.64432744184463e-05,1.63101304960297e-05,1.61785971855779e-05,1.60486486138062e-05,1.59202594248957e-05,1.57934047681237e-05,1.5668060285837e-05,1.55442021017592e-05,1.54218068096194e-05,1.53008514620929e-05,1.51813135600453e-05,1.50631710420683e-05,1.49464022743003e-05,1.4830986040522e-05,1.4716901532518e-05,1.46041283406979e-05,1.44926464449674e-05,1.43824362058421e-05,1.42734783557979e-05,1.41657539908485e-05,1.40592445623459e-05,1.39539318689949e-05,1.38497980490771e-05,1.37468255728758e-05,1.36449972352989e-05,1.35442961486915e-05,1.34447057358335e-05,1.33462097231168e-05,1.32487921338969e-05,1.31524372820141e-05,1.30571297654777e-05,1.29628544603118e-05,1.28695965145542e-05,1.27773413424068e-05,1.26860746185325e-05,1.25957822724931e-05,1.25064504833265e-05,1.24180656742571e-05,1.23306145075369e-05,1.22440838794139e-05,1.21584609152222e-05,1.20737329645934e-05,1.19898875967838e-05,1.1906912596114e-05,1.18247959575201e-05,1.17435258822107e-05,1.16630907734284e-05,1.15834792323129e-05,1.15046800538618e-05,1.14266822229881e-05,1.13494749106706e-05,1.12730474701947e-05,1.1197389433482e-05,1.11224905075055e-05,1.10483405707888e-05,1.09749296699863e-05,1.09022480165426e-05,1.08302859834301e-05,1.07590341019602e-05,1.06884830586687e-05,1.06186236922721e-05,1.05494469906938e-05,1.04809440881568e-05,1.04131062623435e-05,1.03459249316187e-05,1.02793916523157e-05,1.02134981160829e-05,1.01482361472901e-05,1.0083597700492e-05,1.00195748579492e-05,9.95615982720272e-06,9.89334493870302e-06,9.83112264349106e-06,9.76948551092998e-06,9.70842622648667e-06,9.64793758956152e-06,9.58801251136548e-06,9.5286440128431e-06,9.46982522264036e-06,9.41154937511642e-06,9.35380980839792e-06,9.29659996247499e-06,9.23991337733795e-06,9.18374369115352e-06,9.12808463847987e-06,9.07293004851926e-06,9.0182738434077e-06,8.96411003654039e-06,8.91043273093236e-06,8.85723611761336e-06,8.80451447405614e-06,8.75226216263741e-06,8.70047362913068e-06,8.6491434012302e-06,8.59826608710532e-06,8.54783637398447e-06,8.49784902676818e-06,8.44829888667041e-06,8.39918086988744e-06,8.35048996629389e-06,8.30222123816503e-06,8.25436981892488e-06,8.20693091191957e-06,8.15989978921516e-06,8.11327179041964e-06,8.06704232152836e-06,8.02120685379241e-06,7.97576092260944e-06,7.93070012643651e-06,7.88602012572419e-06,7.84171664187181e-06,7.79778545620306e-06,7.7542224089617e-06,7.71102339832682e-06,7.66818437944722e-06,7.62570136349461e-06,7.58357041673497e-06,7.54178765961797e-06,7.50034926588381e-06,7.45925146168718e-06,7.41849052473807e-06,7.37806278345885e-06,7.33796461615744e-06,7.29819245021621e-06,7.25874276129612e-06,7.21961207255598e-06,7.18079695388632e-06,7.14229402115771e-06,7.10409993548307e-06,7.06621140249383e-06,7.0286251716295e-06,6.99133803544048e-06,6.95434682890376e-06,6.91764842875123e-06,6.88123975281044e-06,6.84511775935736e-06,6.80927944648115e-06,6.77372185146036e-06,6.73844205015067e-06,6.70343715638365e-06,6.66870432137648e-06,6.63424073315232e-06,6.60004361597112e-06,6.56611022977075e-06,6.53243786961808e-06,6.49902386516991e-06,6.46586558014353e-06,6.43296041179674e-06,6.40030579041707e-06,6.36789917882002e-06,6.33573807185628e-06,6.30381999592753e-06,6.27214250851081e-06,6.24070319769121e-06,6.20949968170275e-06,6.1785296084773e-06,6.1477906552013e-06,6.1172805278802e-06,6.08699696091049e-06,6.05693771665908e-06,6.02710058504993e-06,5.99748338315779e-06,5.96808395480898e-06,5.93890017018888e-06,5.90992992545625e-06,5.88117114236401e-06,5.85262176788651e-06,5.82427977385317e-06,5.79614315658817e-06,5.76820993655642e-06,5.74047815801529e-06,5.71294588867229e-06,5.6856112193485e-06,5.65847226364755e-06,5.63152715763018e-06,5.60477405949417e-06,5.5782111492596e-06,5.55183662845932e-06,5.52564871983451e-06,5.49964566703529e-06,5.4738257343262e-06,5.44818720629657e-06,5.42272838757556e-06,5.3974476025519e-06,5.37234319509817e-06,5.34741352829957e-06,5.32265698418707e-06,5.29807196347489e-06,5.2736568853022e-06,5.24941018697897e-06,5.22533032373594e-06,5.20141576847857e-06,5.17766501154488e-06,5.15407656046723e-06,5.13064893973783e-06,5.10738069057802e-06,5.08427037071115e-06,5.06131655413909e-06,5.03851783092225e-06,5.01587280696305e-06,4.99338010379281e-06,4.97103835836197e-06,4.94884622283357e-06,4.92680236437997e-06,4.90490546498272e-06,4.88315422123557e-06,4.86154734415046e-06,4.84008355896657e-06,4.81876160496231e-06,4.79758023527017e-06,4.77653821669442e-06,4.75563432953165e-06,4.73486736739396e-06,4.71423613703494e-06,4.69373945817827e-06,4.67337616334886e-06,4.65314509770666e-06,4.63304511888287e-06,4.61307509681872e-06,4.5932339136066e-06,4.57352046333361e-06,4.55393365192747e-06,4.5344723970047e-06,4.5151356277211e-06,4.49592228462441e-06,4.47683131950923e-06,4.45786169527403e-06,4.43901238578027e-06,4.42028237571368e-06,4.40167066044752e-06,4.38317624590782e-06,4.36479814844071e-06,4.34653539468154e-06,4.32838702142608e-06,4.31035207550348e-06,4.29242961365107e-06,4.27461870239111e-06,4.25691841790916e-06,4.23932784593433e-06,4.22184608162119e-06,4.20447222943345e-06,4.18720540302921e-06,4.17004472514794e-06,4.15298932749907e-06,4.13603835065214e-06,4.11919094392851e-06,4.10244626529465e-06,4.08580348125694e-06,4.06926176675793e-06,4.05282030507406e-06,4.03647828771489e-06,4.02023491432368e-06,4.00408939257941e-06,3.98804093810013e-06,3.97208877434773e-06,3.95623213253397e-06,3.94047025152786e-06,3.92480237776433e-06,3.90922776515415e-06,3.89374567499512e-06,3.87835537588447e-06,3.86305614363246e-06,3.84784726117722e-06,3.83272801850069e-06,3.81769771254578e-06,3.80275564713464e-06,3.78790113288802e-06,3.77313348714577e-06,3.75845203388839e-06,3.7438561036597e-06,3.72934503349048e-06,3.7149181668232e-06,3.70057485343778e-06,3.68631444937829e-06,3.67213631688068e-06,3.65803982430149e-06,3.64402434604746e-06,3.63008926250617e-06,3.61623395997752e-06,3.60245783060618e-06,3.5887602723149e-06,3.57514068873875e-06,3.56159848916019e-06,3.54813308844503e-06,3.5347439069792e-06,3.5214303706064e-06,3.50819191056653e-06,3.49502796343494e-06,3.48193797106253e-06,3.4689213805165e-06,3.45597764402204e-06,3.44310621890464e-06,3.43030656753324e-06,3.4175781572641e-06,3.40492046038535e-06,3.3923329540623e-06,3.37981512028347e-06,3.36736644580729e-06,3.35498642210947e-06,3.34267454533108e-06,3.33043031622731e-06,3.31825324011678e-06,3.30614282683169e-06,3.29409859066837e-06,3.28212005033866e-06,3.27020672892183e-06,3.25835815381704e-06,3.24657385669654e-06,3.23485337345937e-06,3.22319624418564e-06,3.21160201309145e-06,3.2000702284843e-06,3.18860044271912e-06,3.17719221215483e-06,3.16584509711142e-06,3.1545586618276e-06,3.14333247441896e-06,3.13216610683666e-06,3.1210591348266e-06,3.11001113788916e-06,3.09902169923937e-06,3.08809040576763e-06,3.07721684800084e-06,3.06640062006411e-06,3.05564131964283e-06,3.04493854794531e-06,3.03429190966578e-06,3.02370101294792e-06,3.0131654693488e-06,3.00268489380324e-06,2.99225890458865e-06,2.98188712329024e-06,2.97156917476675e-06,2.96130468711643e-06,2.95109329164362e-06,2.94093462282557e-06,2.93082831827977e-06,2.92077401873164e-06,2.91077136798256e-06,2.90082001287835e-06,2.89091960327808e-06,2.8810697920233e-06,2.87127023490758e-06,2.86152059064643e-06,2.85182052084763e-06,2.84216968998182e-06,2.8325677653535e-06,2.82301441707237e-06,2.81350931802499e-06,2.80405214384676e-06,2.79464257289425e-06,2.78528028621789e-06,2.77596496753489e-06,2.76669630320255e-06,2.75747398219187e-06,2.74829769606145e-06,2.73916713893168e-06,2.73008200745927e-06,2.72104200081205e-06,2.71204682064408e-06,2.703096171071e-06,2.69418975864572e-06,2.68532729233439e-06,2.67650848349257e-06,2.66773304584177e-06,2.65900069544622e-06,2.65031115068986e-06,2.64166413225367e-06,2.63305936309324e-06,2.62449656841651e-06,2.61597547566191e-06,2.60749581447662e-06,2.59905731669515e-06,2.5906597163181e-06,2.58230274949127e-06,2.57398615448486e-06,2.56570967167301e-06,2.55747304351354e-06,2.54927601452792e-06,2.54111833128143e-06,2.5329997423636e-06,2.52491999836882e-06,2.5168788518772e-06,2.50887605743562e-06,2.500911371539e-06,2.49298455261178e-06,2.48509536098959e-06,2.47724355890115e-06,2.46942891045036e-06,2.46165118159855e-06,2.45391014014698e-06,2.44620555571952e-06,2.43853719974547e-06,2.43090484544267e-06,2.42330826780066e-06,2.41574724356416e-06,2.4082215512166e-06,2.40073097096399e-06,2.39327528471876e-06,2.38585427608397e-06,2.37846773033758e-06,2.37111543441691e-06,2.36379717690327e-06,2.35651274800681e-06,2.3492619395514e-06,2.34204454495985e-06,2.33486035923911e-06,2.32770917896579e-06,2.32059080227171e-06,2.31350502882965e-06,2.30645165983932e-06,2.29943049801333e-06,2.29244134756344e-06,2.28548401418692e-06,2.27855830505302e-06,2.27166402878962e-06,2.26480099547001e-06,2.25796901659982e-06,2.25116790510403e-06,2.24439747531425e-06,2.23765754295595e-06,2.23094792513599e-06,2.22426844033019e-06,2.21761890837106e-06,2.21099915043562e-06,2.20440898903343e-06,2.19784824799464e-06,2.19131675245825e-06,2.18481432886045e-06,2.17834080492309e-06,2.17189600964225e-06,2.16547977327699e-06,2.15909192733812e-06,2.15273230457718e-06,2.14640073897548e-06,2.14009706573326e-06,2.13382112125897e-06,2.12757274315865e-06,2.12135177022544e-06,2.11515804242916e-06,2.10899140090604e-06,2.10285168794853e-06,2.09673874699519e-06,2.09065242262075e-06,2.0845925605262e-06,2.07855900752902e-06,2.0725516115535e-06,2.06657022162116e-06,2.06061468784128e-06,2.05468486140145e-06,2.04878059455834e-06,2.04290174062847e-06,2.03704815397911e-06,2.03121969001922e-06,2.0254162051906e-06,2.01963755695895e-06,2.01388360380523e-06,2.00815420521688e-06,2.00244922167933e-06,1.99676851466747e-06,1.99111194663725e-06,1.98547938101734e-06,1.97987068220091e-06,1.97428571553744e-06,1.96872434732466e-06,1.96318644480054e-06,1.95767187613537e-06,1.95218051042391e-06,1.94671221767762e-06,1.94126686881699e-06,1.93584433566387e-06,1.93044449093398e-06,1.92506720822943e-06,1.91971236203129e-06,1.91437982769232e-06,1.90906948142965e-06,1.90378120031766e-06,1.89851486228082e-06,1.89327034608667e-06,1.88804753133884e-06,1.88284629847014e-06,1.8776665287357e-06,1.8725081042062e-06,1.86737090776119e-06,1.8622548230824e-06,1.85715973464715e-06,1.85208552772189e-06,1.84703208835566e-06,1.84199930337376e-06,1.83698706037139e-06,1.83199524770733e-06,1.82702375449782e-06,1.82207247061029e-06,1.81714128665735e-06,1.81223009399071e-06,1.80733878469519e-06,1.8024672515828e-06,1.79761538818689e-06,1.79278308875628e-06,1.78797024824955e-06,1.78317676232931e-06,1.77840252735654e-06,1.773647440385e-06,1.76891139915566e-06,1.76419430209125e-06,1.75949604829074e-06,1.75481653752401e-06,1.75015567022647e-06,1.74551334749377e-06,1.74088947107657e-06,1.73628394337531e-06,1.73169666743508e-06,1.72712754694053e-06,1.72257648621078e-06,1.71804339019444e-06,1.71352816446462e-06,1.70903071521406e-06,1.7045509492502e-06,1.70008877399038e-06,1.69564409745707e-06,1.69121682827311e-06,1.68680687565701e-06,1.68241414941832e-06,1.67803855995299e-06,1.67368001823883e-06,1.66933843583095e-06,1.66501372485729e-06,1.6607057980142e-06,1.65641456856196e-06,1.65213995032051e-06,1.64788185766505e-06,1.64364020552176e-06,1.63941490936361e-06,1.63520588520607e-06,1.63101304960297e-06,1.6268363196424e-06,1.62267561294255e-06,1.61853084764768e-06,1.61440194242409e-06,1.61028881645613e-06,1.60619138944224e-06,1.60210958159106e-06,1.59804331361748e-06,1.59399250673885e-06,1.58995708267116e-06,1.58593696362521e-06,1.58193207230293e-06,1.57794233189359e-06,1.57396766607018e-06,1.57000799898572e-06,1.56606325526968e-06,1.56213336002434e-06,1.55821823882127e-06,1.55431781769781e-06,1.55043202315357e-06,1.54656078214694e-06,1.54270402209171e-06,1.53886167085362e-06,1.53503365674702e-06,1.5312199085315e-06,1.5274203554086e-06,1.52363492701849e-06,1.51986355343676e-06,1.51610616517115e-06,1.51236269315839e-06,1.50863306876096e-06,1.50491722376401e-06,1.50121509037221e-06,1.49752660120668e-06,1.49385168930188e-06,1.49019028810261e-06,1.48654233146099e-06,1.48290775363345e-06,1.47928648927782e-06,1.47567847345031e-06,1.47208364160268e-06,1.46850192957932e-06,1.46493327361436e-06,1.46137761032889e-06,1.4578348767281e-06,1.45430501019849e-06,1.45078794850514e-06,1.44728362978895e-06,1.44379199256388e-06,1.44031297571433e-06,1.43684651849239e-06,1.43339256051525e-06,1.42995104176251e-06,1.42652190257363e-06,1.42310508364531e-06,1.41970052602894e-06,1.41630817112803e-06,1.41292796069574e-06,1.40955983683235e-06,1.40620374198274e-06,1.40285961893403e-06,1.39952741081305e-06,1.39620706108396e-06,1.39289851354584e-06,1.38960171233035e-06,1.38631660189931e-06,1.3830431270424e-06,1.37978123287485e-06,1.3765308648351e-06,1.37329196868255e-06,1.37006449049528e-06,1.36684837666782e-06,1.36364357390893e-06,1.36045002923936e-06,1.35726768998967e-06,1.35409650379811e-06,1.35093641860838e-06,1.34778738266757e-06,1.34464934452399e-06,1.3415222530251e-06,1.3384060573154e-06,1.33530070683439e-06,1.33220615131449e-06,1.32912234077904e-06,1.32604922554025e-06,1.3229867561972e-06,1.31993488363388e-06,1.31689355901721e-06,1.31386273379508e-06,1.3108423596944e-06,1.30783238871921e-06,1.30483277314876e-06,1.30184346553559e-06,1.2988644187037e-06,1.29589558574666e-06,1.29293692002578e-06,1.28998837516825e-06,1.28704990506536e-06,1.28412146387067e-06,1.28120300599824e-06,1.27829448612083e-06,1.27539585916818e-06,1.27250708032521e-06,1.26962810503036e-06,1.2667588889738e-06,1.26389938809575e-06,1.26104955858482e-06,1.2582093568763e-06,1.25537873965048e-06,1.25255766383104e-06,1.24974608658339e-06,1.24694396531302e-06,1.24415125766394e-06,1.24136792151704e-06,1.23859391498851e-06,1.23582919642827e-06,1.2330737244184e-06,1.23032745777159e-06,1.2275903555296e-06,1.22486237696176e-06,1.2221434815634e-06,1.21943362905439e-06,1.21673277937763e-06,1.21404089269759e-06,1.21135792939882e-06,1.20868385008447e-06,1.20601861557491e-06,1.20336218690624e-06,1.20071452532889e-06,1.19807559230619e-06,1.19544534951298e-06,1.19282375883423e-06,1.19021078236362e-06,1.18760638240221e-06,1.18501052145707e-06,1.18242316223991e-06,1.17984426766578e-06,1.17727380085169e-06,1.17471172511534e-06,1.17215800397379e-06,1.16961260114214e-06,1.16707548053229e-06,1.16454660625161e-06,1.16202594260172e-06,1.15951345407717e-06,1.15700910536426e-06,1.15451286133974e-06,1.15202468706962e-06,1.14954454780789e-06,1.1470724089954e-06,1.14460823625857e-06,1.14215199540823e-06,1.13970365243844e-06,1.13726317352529e-06,1.13483052502578e-06,1.13240567347657e-06,1.12998858559295e-06,1.1275792282676e-06,1.12517756856947e-06,1.12278357374273e-06,1.12039721120555e-06,1.11801844854906e-06,1.11564725353624e-06,1.11328359410078e-06,1.11092743834607e-06,1.10857875454407e-06,1.10623751113426e-06,1.10390367672258e-06,1.10157722008039e-06,1.09925811014337e-06,1.09694631601058e-06,1.09464180694333e-06,1.09234455236423e-06,1.09005452185613e-06,1.08777168516114e-06,1.08549601217963e-06,1.08322747296922e-06,1.08096603774382e-06,1.07871167687261e-06,1.07646436087913e-06,1.07422406044025e-06,1.07199074638528e-06,1.06976438969497e-06,1.06754496150058e-06,1.06533243308297e-06,1.06312677587161e-06,1.06092796144375e-06,1.05873596152341e-06,1.05655074798054e-06,1.05437229283006e-06,1.05220056823103e-06,1.0500355464857e-06,1.04787720003866e-06,1.04572550147595e-06,1.0435804235242e-06,1.04144193904977e-06,1.03931002105785e-06,1.03718464269168e-06,1.03506577723164e-06,1.03295339809443e-06,1.03084747883226e-06,1.02874799313199e-06,1.02665491481433e-06,1.024568217833e-06,1.02248787627395e-06,1.02041386435453e-06,1.0183461564227e-06,1.01628472695626e-06,1.01422955056201e-06,1.01218060197502e-06,1.01013785605781e-06,1.00810128779963e-06,1.00607087231564e-06,1.0040465848462e-06,1.00202840075605e-06,1.00001629553365e-06,9.98010244790354e-07,9.96010224259712e-07,9.9401620979673e-07,9.92028177377136e-07,9.90046103096662e-07,9.88069963170322e-07,9.86099733931697e-07,9.84135391832232e-07,9.82176913440526e-07,9.80224275441638e-07,9.78277454636391e-07,9.76336427940684e-07,9.74401172384806e-07,9.72471665112757e-07,9.70547883381574e-07,9.68629804560662e-07,9.66717406131125e-07,9.64810665685107e-07,9.62909560925136e-07,9.61014069663472e-07,9.5912416982146e-07,9.57239839428883e-07,9.55361056623331e-07,9.5348779964956e-07,9.51620046858865e-07,9.49757776708456e-07,9.47900967760835e-07,9.46049598683177e-07,9.44203648246722e-07,9.42363095326163e-07,9.40527918899043e-07,9.38698098045154e-07,9.36873611945941e-07,9.35054439883909e-07,9.3324056124204e-07,9.31431955503199e-07,9.29628602249562e-07,9.27830481162039e-07,9.26037572019697e-07,9.24249854699195e-07,9.22467309174221e-07,9.20689915514926e-07,9.18917653887371e-07,9.17150504552972e-07,9.15388447867951e-07,9.13631464282792e-07,9.11879534341694e-07,9.10132638682036e-07,9.0839075803384e-07,9.06653873219244e-07,9.04921965151968e-07,9.03195014836792e-07,9.01473003369039e-07,8.9975591193405e-07,8.98043721806678e-07,8.96336414350771e-07,8.94633971018671e-07,8.92936373350704e-07,8.91243602974684e-07,8.89555641605414e-07,8.87872471044192e-07,8.86194073178324e-07,8.84520429980632e-07,8.8285152350897e-07,8.81187335905748e-07,8.79527849397451e-07,8.77873046294164e-07,8.76222908989099e-07,8.74577419958134e-07,8.72936561759338e-07,8.71300317032517e-07,8.69668668498748e-07,8.68041598959929e-07,8.66419091298322e-07,8.64801128476103e-07,8.63187693534916e-07,8.61578769595428e-07,8.59974339856889e-07,8.58374387596691e-07,8.56778896169931e-07,8.55187849008984e-07,8.53601229623068e-07,8.52019021597816e-07,8.50441208594857e-07,8.48867774351389e-07,8.4729870267976e-07,8.45733977467054e-07,8.4417358267468e-07,8.42617502337952e-07,8.41065720565691e-07,8.39518221539811e-07,8.37974989514922e-07,8.36436008817925e-07,8.34901263847616e-07,8.33370739074294e-07,8.31844419039359e-07,8.30322288354932e-07,8.2880433170346e-07,8.27290533837335e-07,8.25780879578508e-07,8.2427535381811e-07,8.22773941516073e-07,8.21276627700757e-07,8.19783397468574e-07,8.18294235983618e-07,8.16809128477295e-07,8.15328060247962e-07,8.13851016660556e-07,8.12377983146238e-07,8.10908945202032e-07,8.09443888390465e-07,8.07982798339219e-07,8.06525660740771e-07,8.05072461352049e-07,8.0362318599408e-07,8.02177820551645e-07,8.00736350972935e-07,7.99298763269214e-07,7.97865043514471e-07,7.9643517784509e-07,7.95009152459512e-07,7.93586953617903e-07,7.92168567641821e-07,7.90753980913889e-07,7.89343179877468e-07,7.87936151036332e-07,7.86532880954344e-07,7.85133356255137e-07,7.83737563621794e-07,7.82345489796534e-07,7.80957121580391e-07,7.79572445832908e-07,7.78191449471822e-07,7.76814119472757e-07,7.75440442868915e-07,7.74070406750772e-07,7.72703998265775e-07,7.7134120461804e-07,7.69982013068052e-07,7.68626410932369e-07,7.67274385583323e-07,7.6592592444873e-07,7.64581015011595e-07,7.6323964480982e-07,7.6190180143592e-07,7.60567472536733e-07,7.59236645813134e-07,7.57909309019755e-07,7.56585449964698e-07,7.55265056509263e-07,7.5394811656766e-07,7.5263461810674e-07,7.51324549145719e-07,7.500178977559e-07,7.48714652060408e-07,7.47414800233914e-07,7.46118330502372e-07,7.4482523114275e-07,7.43535490482762e-07,7.42249096900612e-07,7.40966038824725e-07,7.39686304733491e-07,7.38409883155003e-07,7.37136762666805e-07,7.3586693189563e-07,7.34600379517153e-07,7.3333709425573e-07,7.32077064884157e-07,7.30820280223411e-07,7.29566729142411e-07,7.28316400557762e-07,7.27069283433519e-07,7.25825366780938e-07,7.24584639658236e-07,7.23347091170348e-07,7.22112710468693e-07,7.20881486750928e-07,7.19653409260722e-07,7.18428467287513e-07,7.17206650166275e-07,7.15987947277293e-07,7.14772348045922e-07,7.13559841942367e-07,7.12350418481447e-07,7.11144067222376e-07,7.09940777768531e-07,7.08740539767232e-07,7.07543342909517e-07,7.06349176929923e-07,7.05158031606264e-07,7.03969896759412e-07,7.02784762253083e-07,7.01602617993616e-07,7.00423453929762e-07,6.99247260052466e-07,6.98074026394659e-07,6.96903743031047e-07,6.95736400077897e-07,6.94571987692829e-07,6.93410496074614e-07,6.9225191546296e-07,6.91096236138314e-07,6.89943448421653e-07,6.88793542674283e-07,6.8764650929764e-07,6.86502338733085e-07,6.85361021461708e-07,6.84222548004131e-07,6.83086908920307e-07,6.81954094809328e-07,6.80824096309229e-07,6.79696904096797e-07,6.78572508887373e-07,6.77450901434666e-07,6.76332072530563e-07,6.75216013004935e-07,6.74102713725454e-07,6.72992165597406e-07,6.71884359563501e-07,6.70779286603692e-07,6.69676937734993e-07,6.6857730401129e-07,6.67480376523166e-07,6.66386146397719e-07,6.65294604798377e-07,6.6420574292473e-07,6.63119552012343e-07,6.62036023332585e-07,6.6095514819245e-07,6.59876917934387e-07,6.58801323936124e-07,6.57728357610495e-07,6.56658010405271e-07,6.55590273802985e-07,6.54525139320771e-07,6.53462598510185e-07,6.52402642957046e-07,6.51345264281265e-07,6.5029045413668e-07,6.49238204210893e-07,6.48188506225103e-07,6.47141351933948e-07,6.46096733125338e-07,6.45054641620297e-07,6.44015069272802e-07,6.42978007969625e-07,6.41943449630173e-07,6.4091138620633e-07,6.39881809682304e-07,6.38854712074468e-07,6.37830085431205e-07,6.36807921832757e-07,6.35788213391071e-07,6.34770952249646e-07,6.33756130583379e-07,6.32743740598422e-07,6.31733774532024e-07,6.30726224652387e-07,6.29721083258519e-07,6.28718342680082e-07,6.27717995277249e-07,6.26720033440561e-07,6.25724449590774e-07,6.24731236178725e-07,6.23740385685183e-07,6.22751890620705e-07,6.21765743525502e-07,6.20781936969291e-07,6.19800463551158e-07,6.18821315899418e-07,6.17844486671479e-07,6.16869968553701e-07,6.1589775426126e-07,6.14927836538014e-07,6.13960208156365e-07,6.12994861917125e-07,6.12031790649384e-07,6.11070987210374e-07,6.10112444485338e-07,6.09156155387399e-07,6.08202112857426e-07,6.07250309863909e-07,6.06300739402824e-07,6.05353394497507e-07,6.04408268198526e-07,6.03465353583552e-07,6.02524643757233e-07,6.01586131851069e-07,6.00649811023285e-07,5.99715674458708e-07,5.9878371536864e-07,5.97853926990738e-07,5.96926302588891e-07,5.96000835453094e-07,5.95077518899332e-07,5.94156346269457e-07,5.93237310931067e-07,5.92320406277387e-07,5.91405625727151e-07,5.90492962724486e-07,5.89582410738789e-07,5.88673963264615e-07,5.8776761382156e-07,5.86863355954142e-07,5.85961183231691e-07,5.85061089248232e-07,5.84163067622372e-07,5.83267111997184e-07,5.823732160401e-07,5.81481373442795e-07,5.80591577921077e-07,5.79703823214776e-07,5.78818103087633e-07,5.77934411327194e-07,5.77052741744696e-07,5.76173088174964e-07,5.75295444476297e-07,5.74419804530366e-07,5.73546162242107e-07,5.72674511539611e-07,5.71804846374023e-07,5.70937160719435e-07,5.70071448572779e-07,5.69207703953729e-07,5.68345920904594e-07,5.67486093490215e-07,5.66628215797864e-07,5.65772281937142e-07,5.64918286039879e-07,5.6406622226003e-07,5.63216084773579e-07,5.62367867778438e-07,5.61521565494347e-07,5.60677172162777e-07,5.5983468204683e-07,5.58994089431144e-07,5.58155388621795e-07,5.573185739462e-07,5.56483639753022e-07,5.55650580412074e-07,5.54819390314225e-07,5.53990063871304e-07,5.53162595516007e-07,5.52336979701804e-07,5.51513210902845e-07,5.5069128361387e-07,5.49871192350111e-07,5.49052931647209e-07,5.48236496061117e-07,5.47421880168009e-07,5.46609078564196e-07,5.4579808586603e-07,5.44988896709816e-07,5.44181505751728e-07,5.43375907667713e-07,5.42572097153412e-07,5.41770068924065e-07,5.40969817714428e-07,5.40171338278687e-07,5.39374625390371e-07,5.38579673842264e-07,5.37786478446325e-07,5.36995034033601e-07,5.3620533545414e-07,5.35417377576911e-07,5.3463115528972e-07,5.33846663499126e-07,5.33063897130359e-07,5.32282851127238e-07,5.31503520452088e-07,5.30725900085662e-07,5.29949985027058e-07,5.29175770293636e-07,5.28403250920945e-07,5.27632421962635e-07,5.26863278490387e-07,5.26095815593824e-07,5.25330028380441e-07,5.24565911975524e-07,5.23803461522071e-07,5.23042672180718e-07,5.22283539129657e-07,5.21526057564567e-07,5.20770222698531e-07,5.20016029761966e-07,5.19263474002542e-07,5.18512550685112e-07,5.17763255091637e-07,5.17015582521107e-07,5.16269528289475e-07,5.15525087729577e-07,5.14782256191062e-07,5.14041029040318e-07,5.13301401660404e-07,5.12563369450972e-07,5.11826927828197e-07,5.11092072224711e-07,5.10358798089525e-07,5.09627100887963e-07,5.0889697610159e-07,5.08168419228145e-07,5.07441425781467e-07,5.06715991291429e-07,5.0599211130387e-07,5.05269781380524e-07,5.04548997098954e-07,5.03829754052483e-07,5.03112047850129e-07,5.02395874116535e-07,5.01681228491903e-07,5.00968106631928e-07,5.00256504207735e-07,4.99546416905808e-07,4.98837840427927e-07,4.98130770491105e-07,4.9742520282752e-07,4.96721133184452e-07,4.9601855732422e-07,4.95317471024115e-07,4.94617870076341e-07,4.93919750287948e-07,4.93223107480772e-07,4.92527937491369e-07,4.91834236170959e-07,4.91141999385356e-07,4.90451223014913e-07,4.89761902954456e-07,4.89074035113228e-07,4.88387615414823e-07,4.87702639797131e-07,4.87019104212271e-07,4.8633700462654e-07,4.85656337020345e-07,4.84977097388148e-07,4.84299281738409e-07,4.83622886093523e-07,4.82947906489764e-07,4.82274338977226e-07,4.81602179619766e-07,4.80931424494948e-07,4.80262069693981e-07,4.79594111321666e-07,4.78927545496341e-07,4.78262368349818e-07,4.77598576027334e-07,4.7693616468749e-07,4.76275130502199e-07,4.75615469656628e-07,4.74957178349145e-07,4.74300252791263e-07,4.73644689207584e-07,4.72990483835751e-07,4.72337632926384e-07,4.71686132743038e-07,4.71035979562137e-07,4.70387169672933e-07,4.69739699377444e-07,4.69093564990405e-07,4.68448762839215e-07,4.67805289263887e-07,4.67163140616991e-07,4.66522313263607e-07,4.65882803581271e-07,4.65244607959927e-07,4.64607722801871e-07,4.63972144521704e-07,4.63337869546282e-07,4.62704894314661e-07,4.62073215278054e-07,4.61442828899776e-07,4.60813731655195e-07,4.60185920031687e-07,4.5955939052858e-07,4.58934139657113e-07,4.5831016394038e-07,4.57687459913287e-07,4.57066024122502e-07,4.56445853126406e-07,4.55826943495048e-07,4.55209291810096e-07,4.54592894664787e-07,4.53977748663888e-07,4.53363850423639e-07,4.52751196571715e-07,4.52139783747176e-07,4.51529608600418e-07,4.50920667793135e-07,4.50312957998266e-07,4.49706475899951e-07,4.49101218193491e-07,4.48497181585296e-07,4.47894362792842e-07,4.47292758544632e-07,4.46692365580142e-07,4.46093180649786e-07,4.45495200514867e-07,4.44898421947533e-07,4.44302841730736e-07,4.43708456658186e-07,4.43115263534312e-07,4.42523259174213e-07,4.41932440403619e-07,4.41342804058852e-07,4.40754346986773e-07,4.40167066044752e-07,4.39580958100618e-07,4.3899602003262e-07,4.38412248729385e-07,4.37829641089877e-07,4.37248194023357e-07,4.36667904449338e-07,4.36088769297548e-07,4.35510785507889e-07,4.34933950030396e-07,4.34358259825193e-07,4.33783711862462e-07,4.33210303122392e-07,4.3263803059515e-07,4.32066891280833e-07,4.31496882189433e-07,4.30928000340799e-07,4.30360242764592e-07,4.29793606500254e-07,4.29228088596964e-07,4.28663686113602e-07,4.28100396118709e-07,4.27538215690451e-07,4.26977141916579e-07,4.26417171894393e-07,4.25858302730705e-07,4.25300531541797e-07,4.24743855453392e-07,4.24188271600608e-07,4.23633777127927e-07,4.23080369189158e-07,4.22528044947397e-07,4.21976801574993e-07,4.21426636253513e-07,4.20877546173704e-07,4.20329528535457e-07,4.19782580547773e-07,4.19236699428725e-07,4.18691882405426e-07,4.1814812671399e-07,4.17605429599501e-07,4.17063788315973e-07,4.16523200126322e-07,4.15983662302324e-07,4.15445172124587e-07,4.14907726882511e-07,4.1437132387426e-07,4.13835960406722e-07,4.1330163379548e-07,4.12768341364776e-07,4.12236080447478e-07,4.11704848385046e-07,4.11174642527499e-07,4.10645460233384e-07,4.10117298869739e-07,4.09590155812066e-07,4.09064028444292e-07,4.08538914158741e-07,4.080148103561e-07,4.07491714445387e-07,4.0696962384392e-07,4.06448535977282e-07,4.05928448279294e-07,4.05409358191981e-07,4.04891263165537e-07,4.04374160658302e-07,4.03858048136721e-07,4.03342923075322e-07,4.02828782956679e-07,4.02315625271384e-07,4.01803447518015e-07,4.01292247203107e-07,4.00782021841119e-07,4.00272768954409e-07,3.99764486073197e-07,3.99257170735541e-07,3.98750820487303e-07,3.98245432882123e-07,3.97741005481385e-07,3.97237535854194e-07,3.96735021577338e-07,3.96233460235268e-07,3.95732849420063e-07,3.95233186731401e-07,3.94734469776535e-07,3.94236696170259e-07,3.93739863534884e-07,3.93243969500205e-07,3.92749011703477e-07,3.92254987789385e-07,3.91761895410014e-07,3.91269732224826e-07,3.90778495900626e-07,3.90288184111542e-07,3.89798794538988e-07,3.89310324871646e-07,3.88822772805432e-07,3.88336136043473e-07,3.87850412296076e-07,3.87365599280706e-07,3.86881694721955e-07,3.86398696351515e-07,3.85916601908157e-07,3.85435409137698e-07,3.84955115792978e-07,3.84475719633834e-07,3.83997218427071e-07,3.8351960994644e-07,3.8304289197261e-07,3.82567062293141e-07,3.82092118702461e-07,3.81618059001837e-07,3.81144880999355e-07,3.80672582509889e-07,3.80201161355078e-07,3.79730615363302e-07,3.79260942369655e-07,3.78792140215922e-07,3.78324206750554e-07,3.7785713982864e-07,3.77390937311886e-07,3.76925597068592e-07,3.76461116973621e-07,3.75997494908383e-07,3.75534728760803e-07,3.75072816425304e-07,3.74611755802777e-07,3.74151544800563e-07,3.73692181332422e-07,3.73233663318517e-07,3.72775988685386e-07,3.72319155365919e-07,3.71863161299334e-07,3.71408004431159e-07,3.709536827132e-07,3.70500194103527e-07,3.70047536566442e-07,3.69595708072466e-07,3.69144706598308e-07,3.68694530126847e-07,3.68245176647107e-07,3.67796644154236e-07,3.67348930649483e-07,3.66902034140177e-07,3.66455952639703e-07,3.66010684167479e-07,3.6556622674894e-07,3.65122578415507e-07,3.64679737204572e-07,3.64237701159476e-07,3.63796468329482e-07,3.63356036769761e-07,3.62916404541365e-07,3.62477569711206e-07,3.62039530352038e-07,3.61602284542434e-07,3.61165830366765e-07,3.60730165915176e-07,3.60295289283573e-07,3.59861198573592e-07,3.59427891892589e-07,3.58995367353608e-07,3.58563623075372e-07,3.58132657182253e-07,3.57702467804256e-07,3.57273053077e-07,3.56844411141695e-07,3.56416540145122e-07,3.55989438239615e-07,3.55563103583041e-07,3.55137534338776e-07,3.54712728675692e-07,3.5428868476813e-07,3.53865400795886e-07,3.53442874944189e-07,3.53021105403683e-07,3.52600090370405e-07,3.52179828045768e-07,3.51760316636541e-07,3.51341554354831e-07,3.50923539418062e-07,3.50506270048956e-07,3.50089744475517e-07,3.49673960931009e-07,3.49258917653939e-07,3.48844612888039e-07,3.48431044882244e-07,3.48018211890678e-07,3.47606112172631e-07,3.47194743992545e-07,3.46784105619993e-07,3.46374195329662e-07,3.45965011401334e-07,3.45556552119868e-07,3.45148815775184e-07,3.44741800662242e-07,3.44335505081025e-07,3.43929927336524e-07,3.43525065738718e-07,3.43120918602555e-07,3.42717484247937e-07,3.42314760999702e-07,3.41912747187606e-07,3.41511441146306e-07,3.41110841215343e-07,3.40710945739123e-07,3.40311753066904e-07,3.39913261552774e-07,3.39515469555638e-07,3.39118375439198e-07,3.3872197757194e-07,3.38326274327113e-07,3.37931264082715e-07,3.37536945221475e-07,3.37143316130838e-07,3.36750375202946e-07,3.36358120834626e-07,3.35966551427368e-07,3.35575665387313e-07,3.35185461125235e-07,3.34795937056524e-07,3.34407091601174e-07,3.34018923183761e-07,3.33631430233432e-07,3.33244611183886e-07,3.3285846447336e-07,3.32472988544613e-07,3.32088181844908e-07,3.31704042826002e-07,3.31320569944122e-07,3.30937761659958e-07,3.30555616438641e-07,3.30174132749734e-07,3.29793309067208e-07,3.29413143869436e-07,3.29033635639172e-07,3.28654782863536e-07,3.28276584034004e-07,3.27899037646386e-07,3.27522142200815e-07,3.27145896201733e-07,3.26770298157874e-07,3.26395346582248e-07,3.26021039992131e-07,3.25647376909045e-07,3.25274355858748e-07,3.24901975371217e-07,3.24530233980632e-07,3.24159130225366e-07,3.23788662647965e-07,3.2341882979514e-07,3.23049630217749e-07,3.2268106247078e-07,3.22313125113345e-07,3.21945816708658e-07,3.21579135824024e-07,3.21213081030826e-07,3.20847650904511e-07,3.20482844024574e-07,3.20118658974546e-07,3.1975509434198e-07,3.19392148718436e-07,3.1902982069947e-07,3.18668108884618e-07,3.18307011877384e-07,3.17946528285224e-07,3.17586656719536e-07,3.17227395795645e-07,3.16868744132789e-07,3.16510700354108e-07,3.16153263086628e-07,3.15796430961248e-07,3.1544020261273e-07,3.15084576679683e-07,3.14729551804551e-07,3.143751266336e-07,3.14021299816904e-07,3.13668070008337e-07,3.1331543586555e-07,3.12963396049971e-07,3.12611949226782e-07,3.12261094064911e-07,3.1191082923702e-07,3.1156115341949e-07,3.11212065292409e-07,3.10863563539562e-07,3.10515646848415e-07,3.10168313910106e-07,3.0982156341943e-07,3.09475394074827e-07,3.09129804578373e-07,3.08784793635763e-07,3.08440359956303e-07,3.08096502252896e-07,3.07753219242029e-07,3.07410509643764e-07,3.07068372181723e-07,3.06726805583078e-07,3.06385808578539e-07,3.06045379902341e-07,3.05705518292232e-07,3.05366222489466e-07,3.05027491238785e-07,3.04689323288409e-07,3.04351717390029e-07,3.04014672298788e-07,3.03678186773278e-07,3.0334225957552e-07,3.03006889470959e-07,3.02672075228449e-07,3.02337815620246e-07,3.02004109421989e-07,3.01670955412699e-07,3.01338352374757e-07,3.01006299093904e-07,3.00674794359219e-07,3.00343836963116e-07,3.00013425701331e-07,2.99683559372907e-07,2.99354236780189e-07,2.99025456728811e-07,2.98697218027681e-07,2.98369519488979e-07,2.98042359928135e-07,2.97715738163831e-07,2.97389653017978e-07,2.97064103315714e-07,2.9673908788539e-07,2.96414605558561e-07,2.96090655169972e-07,2.95767235557553e-07,2.95444345562403e-07,2.95121984028783e-07,2.94800149804106e-07,2.94478841738924e-07,2.94158058686921e-07,2.938377995049e-07,2.93518063052772e-07,2.93198848193552e-07,2.92880153793342e-07,2.92561978721323e-07,2.92244321849747e-07,2.91927182053926e-07,2.91610558212219e-07,2.91294449206026e-07,2.90978853919779e-07,2.90663771240928e-07,2.90349200059931e-07,2.9003513927025e-07,2.89721587768336e-07,2.89408544453622e-07,2.8909600822851e-07,2.88783977998366e-07,2.88472452671506e-07,2.88161431159192e-07,2.87850912375615e-07,2.87540895237893e-07,2.87231378666054e-07,2.86922361583035e-07,2.86613842914667e-07,2.86305821589664e-07,2.85998296539622e-07,2.85691266698999e-07,2.85384731005116e-07,2.8507868839814e-07,2.84773137821079e-07,2.84468078219771e-07,2.84163508542876e-07,2.83859427741867e-07,2.8355583477102e-07,2.83252728587406e-07,2.82950108150881e-07,2.82647972424078e-07,2.82346320372398e-07,2.82045150964001e-07,2.81744463169796e-07,2.81444255963435e-07,2.81144528321302e-07,2.80845279222503e-07,2.80546507648862e-07,2.80248212584908e-07,2.79950393017868e-07,2.79653047937658e-07,2.79356176336875e-07,2.79059777210788e-07,2.7876384955733e-07,2.78468392377089e-07,2.781734046733e-07,2.77878885451835e-07,2.77584833721198e-07,2.77291248492514e-07,2.7699812877952e-07,2.76705473598559e-07,2.76413281968571e-07,2.76121552911084e-07,2.75830285450207e-07,2.75539478612622e-07,2.75249131427571e-07,2.74959242926858e-07,2.74669812144829e-07,2.74380838118375e-07,2.74092319886915e-07,2.73804256492394e-07,2.73516646979272e-07,2.73229490394517e-07,2.72942785787597e-07,2.72656532210473e-07,2.7237072871759e-07,2.72085374365869e-07,2.71800468214701e-07,2.71516009325936e-07,2.71231996763879e-07,2.70948429595282e-07,2.7066530688933e-07,2.70382627717644e-07,2.70100391154265e-07,2.69818596275648e-07,2.69537242160658e-07,2.69256327890558e-07,2.68975852549005e-07,2.68695815222041e-07,2.68416214998085e-07,2.68137050967926e-07,2.67858322224716e-07,2.67580027863963e-07,2.67302166983523e-07,2.67024738683592e-07,2.667477420667e-07,2.66471176237704e-07,2.66195040303779e-07,2.65919333374412e-07,2.65644054561395e-07,2.65369202978817e-07,2.65094777743058e-07,2.64820777972781e-07,2.64547202788925e-07,2.64274051314698e-07,2.6400132267557e-07,2.63729015999267e-07,2.63457130415763e-07,2.63185665057272e-07,2.62914619058243e-07,2.62643991555352e-07,2.62373781687497e-07,2.62103988595787e-07,2.61834611423541e-07,2.61565649316275e-07,2.61297101421699e-07,2.61028966889712e-07,2.60761244872389e-07,2.60493934523981e-07,2.60227035000903e-07,2.59960545461732e-07,2.59694465067196e-07,2.5942879298017e-07,2.59163528365671e-07,2.58898670390847e-07,2.58634218224973e-07,2.58370171039444e-07,2.58106528007771e-07,2.57843288305571e-07,2.5758045111056e-07,2.57318015602551e-07,2.57055980963445e-07,2.56794346377222e-07,2.56533111029941e-07,2.56272274109728e-07,2.56011834806771e-07,2.55751792313316e-07,2.55492145823657e-07,2.55232894534136e-07,2.54974037643127e-07,2.54715574351041e-07,2.54457503860311e-07,2.54199825375389e-07,2.53942538102742e-07,2.53685641250842e-07,2.53429134030164e-07,2.53173015653175e-07,2.52917285334334e-07,2.52661942290079e-07,2.52406985738827e-07,2.52152414900967e-07,2.51898228998849e-07,2.51644427256785e-07,2.51391008901038e-07,2.51137973159819e-07,2.50885319263279e-07,2.50633046443508e-07,2.50381153934519e-07,2.50129640972254e-07,2.49878506794571e-07,2.4962775064124e-07,2.49377371753937e-07,2.49127369376239e-07,2.48877742753617e-07,2.48628491133433e-07,2.48379613764931e-07,2.48131109899234e-07,2.47882978789334e-07,2.47635219690095e-07,2.47387831858237e-07,2.47140814552337e-07,2.46894167032824e-07,2.46647888561968e-07,2.4640197840388e-07,2.46156435824504e-07,2.45911260091611e-07,2.45666450474795e-07,2.45422006245467e-07,2.45177926676849e-07,2.4493421104397e-07,2.44690858623658e-07,2.44447868694538e-07,2.44205240537025e-07,2.43962973433317e-07,2.43721066667394e-07,2.43479519525008e-07,2.43238331293681e-07,2.42997501262697e-07,2.427570287231e-07,2.42516912967687e-07,2.42277153291001e-07,2.4203774898933e-07,2.41798699360699e-07,2.41560003704864e-07,2.4132166132331e-07,2.41083671519243e-07,2.40846033597588e-07,2.4060874686498e-07,2.40371810629761e-07,2.40135224201976e-07,2.39898986893366e-07,2.39663098017364e-07,2.39427556889092e-07,2.3919236282535e-07,2.38957515144618e-07,2.38723013167047e-07,2.38488856214456e-07,2.38255043610324e-07,2.3802157467979e-07,2.37788448749643e-07,2.37555665148322e-07,2.37323223205906e-07,2.37091122254116e-07,2.36859361626301e-07,2.36627940657443e-07,2.36396858684145e-07,2.36166115044629e-07,2.35935709078732e-07,2.35705640127899e-07,2.35475907535182e-07,2.35246510645231e-07,2.35017448804291e-07,2.34788721360199e-07,2.34560327662378e-07,2.34332267061831e-07,2.34104538911139e-07,2.33877142564455e-07,2.33650077377499e-07,2.33423342707555e-07,2.33196937913465e-07,2.32970862355623e-07,2.32745115395976e-07,2.32519696398014e-07,2.32294604726767e-07,2.32069839748802e-07,2.31845400832217e-07,2.31621287346638e-07,2.31397498663211e-07,2.31174034154603e-07,2.30950893194994e-07,2.30728075160074e-07,2.30505579427036e-07,2.30283405374577e-07,2.30061552382886e-07,2.29840019833649e-07,2.29618807110036e-07,2.29397913596703e-07,2.29177338679783e-07,2.28957081746886e-07,2.2873714218709e-07,2.28517519390943e-07,2.28298212750453e-07,2.28079221659086e-07,2.27860545511761e-07,2.2764218370485e-07,2.27424135636167e-07,2.2720640070497e-07,2.26988978311951e-07,2.26771867859237e-07,2.26555068750385e-07,2.26338580390375e-07,2.26122402185609e-07,2.25906533543904e-07,2.25690973874492e-07,2.25475722588012e-07,2.25260779096507e-07,2.25046142813424e-07,2.24831813153601e-07,2.24617789533274e-07,2.24404071370065e-07,2.24190658082979e-07,2.23977549092406e-07,2.23764743820109e-07,2.23552241689226e-07,2.23340042124262e-07,2.2312814455109e-07,2.2291654839694e-07,2.22705253090402e-07,2.2249425806142e-07,2.22283562741286e-07,2.22073166562639e-07,2.21863068959457e-07};
-static long aes_random(char *ctx);
+static int aes_random(char *ctx);
#define RANDOMNESS_BUFFER_SIZE 16
@@ -37,14 +37,14 @@
#define SEED(ctx, s) aes_seed_context(ctx, s)
-#define RAND(ctx) (((double) ((unsigned long) aes_random(ctx)))/((double)ULONG_MAX))
+#define RAND(ctx) (((double) ((unsigned int) aes_random(ctx)))/((double)UINT_MAX))
-#define RANDOM(ctx, n) (( (unsigned long) aes_random(ctx)) % (n))
+#define RANDOM(ctx, n) (( (unsigned int) aes_random(ctx)) % (n))
-static long
-get_degree0(long size, VALUE rnd_ctx)
+static int
+get_degree0(int size, VALUE rnd_ctx)
{
- long rval = 1;
+ int rval = 1;
double d = RAND(RSTRING(rnd_ctx)->ptr) - P0[rval];
while (d > 0.0) {
rval ++;
@@ -55,10 +55,10 @@
else
return rval;
}
-static long
-get_degree1(long size, VALUE rnd_ctx)
+static int
+get_degree1(int size, VALUE rnd_ctx)
{
- long rval = 1;
+ int rval = 1;
double d = RAND(RSTRING(rnd_ctx)->ptr) - P1[rval];
while (d > 0.0) {
rval ++;
@@ -71,7 +71,7 @@
}
-long (*get_degree_func(long size))(long, VALUE)
+int (*get_degree_func(int size))(int, VALUE)
{
if (size < 1024)
return &get_degree0;
@@ -87,27 +87,27 @@
AES_set_encrypt_key((unsigned char *) "0123456789012345", 128, &key);
AES_encrypt((unsigned char *) ctx + 4, (unsigned char *) ctx + 4, &key);
- ( (long *) ctx )[0] = 0;
+ ( (int *) ctx )[0] = 0;
}
static void
-aes_seed_context(char *ctx, long seed)
+aes_seed_context(char *ctx, int seed)
{
- long tmp;
+ int tmp;
for (tmp = 1; tmp < ( (RANDOMNESS_BUFFER_SIZE / 4) + 1 ); tmp++) {
- ( (long *) ctx )[tmp] = seed;
+ ( (int *) ctx )[tmp] = seed;
}
aes_randomize_context(ctx);
}
-static long
+static int
aes_random(char *ctx)
{
- long *long_ctx = (long *) ctx;
- if (long_ctx[0] < (RANDOMNESS_BUFFER_SIZE / 4)) {
- long return_value = long_ctx[long_ctx[0] + 1];
- long_ctx[0]++;
+ int *int_ctx = (int *) ctx;
+ if (int_ctx[0] < (RANDOMNESS_BUFFER_SIZE / 4)) {
+ int return_value = int_ctx[int_ctx[0] + 1];
+ int_ctx[0]++;
return return_value;
} else {
aes_randomize_context(ctx);
@@ -123,24 +123,24 @@
}
static char
-get_is_known(VALUE decode_status, long block_number)
+get_is_known(VALUE decode_status, int block_number)
{
- long byte_in_status = block_number / 8;
+ int byte_in_status = block_number / 8;
char bit_in_byte = 1 << (block_number % 8);
return ((RSTRING(decode_status)->ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
}
static void
-set_is_known(VALUE decode_status, long block_number)
+set_is_known(VALUE decode_status, int block_number)
{
- long byte_in_status = block_number / 8;
+ int byte_in_status = block_number / 8;
char bit_in_byte = 1 << (block_number % 8);
rb_str_modify(decode_status);
RSTRING(decode_status)->ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
}
static void
-set_value(VALUE aux_blocks, long index, char value, VALUE self, VALUE decode_status)
+set_value(VALUE aux_blocks, int index, char value, VALUE self, VALUE decode_status)
{
if (index < RSTRING(self)->len) {
rb_str_modify(self);
@@ -154,7 +154,7 @@
}
static char
-get_value(VALUE aux_blocks, long index, VALUE self)
+get_value(VALUE aux_blocks, int index, VALUE self)
{
if (index < RSTRING(self)->len) {
return RSTRING(self)->ptr[index];
@@ -164,9 +164,9 @@
}
static char
-get_check_block(VALUE self, long seed, long index, VALUE aux_blocks, long (*degree_func)(long, VALUE), VALUE rnd_ctx)
+get_check_block(VALUE self, int seed, int index, VALUE aux_blocks, int (*degree_func)(int, VALUE), VALUE rnd_ctx)
{
- long degree;
+ int degree;
int empty_block = 1;
char block = 0;
@@ -174,7 +174,7 @@
// Find [degree] blocks.
for (degree = degree_func(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
- long block_number;
+ int block_number;
char found_block;
block_number = RANDOM(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len + RSTRING(aux_blocks)->len);
@@ -208,7 +208,7 @@
static VALUE _aes_seed_context(VALUE self, VALUE _ctx, VALUE _s) {
char * ctx = STR2CSTR(_ctx);
- long s = NUM2INT(_s);
+ int s = NUM2INT(_s);
aes_seed_context(ctx, s);
return Qnil;
@@ -230,7 +230,7 @@
static VALUE _macro_random(VALUE self, VALUE _ctx, VALUE _lim) {
char * ctx = STR2CSTR(_ctx);
- long lim = NUM2INT(_lim);
+ int lim = NUM2INT(_lim);
return INT2NUM(RANDOM(ctx, lim));
}
@@ -239,22 +239,22 @@
VALUE chunk = (_chunk);
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
- long seed = ( (long *) RSTRING(chunk)->ptr )[0];
- long size = ( (long *) RSTRING(chunk)->ptr )[1];
- long tmp, tmp2;
+ int seed = ( (int *) RSTRING(chunk)->ptr )[0];
+ int size = ( (int *) RSTRING(chunk)->ptr )[1];
+ int tmp, tmp2;
char got_new_block = 0;
- long (*degree_func)(long, VALUE) = get_degree_func(size);
+ int (*degree_func)(int, VALUE) = get_degree_func(size);
VALUE rnd_ctx = get_aes_context();
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
- long degree;
+ int degree;
//printf("looking at check block %d:", tmp);
degree = degree_func(size, rnd_ctx);
if (degree == 1) {
- long block_nr;
+ int block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
//printf(" %d", block_nr);
if (!get_is_known(decode_status, block_nr)) {
@@ -265,12 +265,12 @@
//printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
}
} else {
- long missing_blocks;
- long missing_block = 0;
+ int missing_blocks;
+ int missing_block = 0;
char xor_sum = RSTRING(chunk)->ptr[tmp];
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
- long block_nr;
+ int block_nr;
//printf(" %d", block_nr);
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
if (get_is_known(decode_status, block_nr)) {
@@ -296,12 +296,12 @@
}
static VALUE _fill_aux_blocks(VALUE self, VALUE _size, VALUE _q) {
- long size = NUM2INT(_size);
- long q = NUM2INT(_q);
+ int size = NUM2INT(_size);
+ int q = NUM2INT(_q);
char aux_blocks[size];
char initialized_aux_blocks[size];
- long tmp, tmp2;
+ int tmp, tmp2;
VALUE rnd_ctx = get_aes_context();
for (tmp = 0; tmp < size; tmp++)
@@ -310,7 +310,7 @@
SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
for (tmp2 = 0; tmp2 < q; tmp2++) {
- long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
+ int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
if (initialized_aux_blocks[aux_block_nr]) {
aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
} else {
@@ -324,21 +324,21 @@
}
static VALUE _get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks) {
- long chunk_size = NUM2INT(_chunk_size);
+ int chunk_size = NUM2INT(_chunk_size);
VALUE aux_blocks = (_aux_blocks);
- unsigned long tmp;
- long seed;
+ unsigned int tmp;
+ int seed;
struct timeval tmp_timeval;
char chunk[chunk_size];
- long (*degree_func)(long, VALUE) = get_degree_func(RSTRING(self)->len);
+ int (*degree_func)(int, VALUE) = get_degree_func(RSTRING(self)->len);
VALUE rnd_ctx = get_aes_context();
gettimeofday(&tmp_timeval, NULL);
srandom(tmp_timeval.tv_usec);
seed = random();
- ( (long *) chunk) [0] = seed;
- ( (long *) chunk) [1] = RSTRING(self)->len;
+ ( (int *) chunk) [0] = seed;
+ ( (int *) chunk) [1] = RSTRING(self)->len;
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < chunk_size; tmp++) {
chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func, rnd_ctx);
@@ -349,10 +349,10 @@
static VALUE _fill_aux_hash(VALUE self, VALUE _q, VALUE _size) {
- long q = NUM2INT(_q);
- long size = NUM2INT(_size);
+ int q = NUM2INT(_q);
+ int size = NUM2INT(_size);
- long tmp, tmp2;
+ int tmp, tmp2;
VALUE aux_ary = rb_ary_new();
VALUE set_func = rb_intern("[]=");
VALUE get_func = rb_intern("[]");
@@ -363,7 +363,7 @@
SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
for (tmp2 = 0; tmp2 < q; tmp2++) {
- long aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
+ int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
VALUE data_blocks_for_this_aux_block;
if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
@@ -372,11 +372,11 @@
}
for (tmp = 0; tmp < size; tmp++) {
VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
- long number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
+ int number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
rb_str_modify(data_block_string);
- ( (long *) RSTRING(data_block_string)->ptr )[tmp2] = (long) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
+ ( (int *) RSTRING(data_block_string)->ptr )[tmp2] = (int) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
get_func,
1,
INT2NUM(tmp2)));
@@ -390,7 +390,7 @@
static VALUE _oneline_done(VALUE self, VALUE _decode_status) {
VALUE decode_status = (_decode_status);
- long tmp;
+ int tmp;
if (decode_status == Qnil)
return (Qfalse);
for (tmp = 0; tmp < (RSTRING(decode_status)->len - 1); tmp++) {
@@ -412,26 +412,26 @@
VALUE aux_blocks = (_aux_blocks);
VALUE aux_hash = (_aux_hash);
- long tmp, tmp2;
+ int tmp, tmp2;
char got_new_block = 0;
VALUE get_func = rb_intern("[]");
for (tmp = 0; tmp < RSTRING(aux_blocks)->len; tmp++) {
if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
if (RSTRING(data_block_string)->len == 4) {
- long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[0];
+ int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[0];
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
got_new_block = 1;
} else {
}
} else {
- long missing_blocks;
- long missing_block = 0;
+ int missing_blocks;
+ int missing_block = 0;
char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
- long block_nr = ( (long *) RSTRING(data_block_string)->ptr )[tmp2];
+ int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[tmp2];
if (get_is_known(decode_status, block_nr)) {
missing_blocks--;
xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
From nobody at rubyforge.org Sat Dec 23 12:09:39 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 23 Dec 2006 12:09:39 -0500 (EST)
Subject: [Archipelago-submits] [134] trunk/oneliner: removed the special
cases for tiny messages to simplify.
Message-ID: <20061223170939.95B2F5241018@rubyforge.org>
Revision: 134
Author: zond
Date: 2006-12-23 12:09:39 -0500 (Sat, 23 Dec 2006)
Log Message:
-----------
removed the special cases for tiny messages to simplify. added lots of comments. general preparation for introducing variable block sizes.
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 13:21:16 UTC (rev 133)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 17:09:39 UTC (rev 134)
@@ -16,91 +16,40 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "ruby.h"
-
#include
-
#include
-
#include
-
#include
-double P0[] = {0.0,0.0831263080421617,0.462395441631886,0.154131813877295,0.0770659069386476,0.0462395441631886,0.0308263627754591,0.0220188305538993,0.0165141229154245,0.0128443178231079,0.0102754542584864,0.00840718984785247,0.00700599153987706,0.00592814668758828,0.00508126858936138,0.00440376611077987,0.00385329534693238,0.0033999664825874,0.00302219242896657,0.00270406691012799,0.00243366021911519,0.00220188305538993,0.0020017118685363,0.00182764996692445,0.00167534580301408,0.00154131813877295,0.00142275520502119,0.00131736593057517,0.00122326836410552,0.00113890502864997,0.00106297802673997,0.000994398799208357,0.000932248874257834,0.000875748942484632,0.000824234298809066,0.000777135196019976,0.000733961018463311,0.000694287449897727,0.000657746005166267,0.000624015440798766,0.000592814668758828,0.000563896880038885,0.000537044647656081,0.000512065826834868,0.000488790107433283,0.000467066102658471,0.000446758880803754,0.000427747864599339,0.0004099250369077,0.000393193402748202,0.000377465666638274,0.000362663091475989,0.000348714511034605,0.000335555472882355,0.000323127492405231,0.000311377401772314,0.000300256780280445,0.00028972145465657,0.000279731059668412,0.000270248650866093,0.00026124036250389,0.000252675104716878,0.000244524294887301,0.000236761618859133,0.000229362818269785,0.000222305500784561,0.000215568970457756,0.000209134075817226,0.000202983073587307,0.000197099506236951,0.000191468091773038,0.000186074624399149,0.000180905884832506,0.000175949559220657,0.000171194165728207,0.000166628987975454,0.000162244014607679,0.000158029884358129,0.000153977836041254,0.000150079662976918,0.000146327671402496,0.000142714642478977,0.000139233797540465,0.00013587876627443,0.00013264355755361,0.000129522532669996,0.000126510380747438,0.000123602096132554,0.000120792957584087,0.000118078509099052,0.000115454542230184,0.000112917079763586,0.000110462360638291,0.000108086826000908,0.000105787106298761,0.000103560009324051,0.0001014025091298,9.93117357456799e-05,9.72849656284212e-05,9.5319612787443e-05,9.34132205316941e-05,9.15634537884923e-05,8.97680919495022e-05,8.80250222029099e-05,8.63322333143924e-05,8.46878098226897e-05,8.3089926618488e-05,8.15368438779555e-05,8.00269023246601e-05,7.85585187957672e-05,7.71301820903896e-05,7.5740449079752e-05,7.43879410604707e-05,7.30713403337367e-05,7.17893869945483e-05,7.05408759163823e-05,6.9324653917824e-05};
-double P1[] = {0.0,0.00943264209782069,0.49551807459988,0.165172691533293,0.0825863457666466,0.049551807459988,0.0330345383066586,0.0235960987904705,0.0176970740928528,0.0137643909611078,0.0110115127688862,0.00900941953817963,0.00750784961514969,0.00635279582820358,0.00544525356703164,0.00471921975809409,0.00412931728833233,0.00364351525441088,0.003238680226143,0.00289776651812795,0.00260798986631516,0.00235960987904705,0.00214509989004277,0.00195856946482166,0.00179535534275319,0.00165172691533293,0.00152467099876886,0.00141173240626746,0.00131089437724836,0.00122048786847261,0.00113912201057444,0.00106563026795673,0.000999028376209435,0.000938481201893711,0.000883276425311728,0.000832803486722487,0.000786536626349015,0.000744021133032852,0.000704862126031123,0.000668715350337219,0.000635279582820358,0.000604290334877902,0.000575514604645621,0.000548746483499313,0.000523803461522071,0.000500523307676646,0.000478761424734183,0.00045838859814975,0.000439289073226844,0.000421358906972687,0.000404504550693779,0.00038864162713716,0.00037369387224727,0.000359592216690769,0.000346273986442963,0.000333682205117764,0.000321764983506415,0.000310474984085138,0.000299768950151167,0.000289607290824009,0.000279953714463209,0.00027077490415294,0.000262040229825425,0.00025372149237065,0.000245792695734067,0.000238229843557634,0.000231010757389221,0.000224114913885065,0.000217523298770799,0.000211218275618022,0.000205183467743221,0.000199403651750455,0.000193864661424053,0.000188553300837093,0.000183457265679333,0.000178565071927885,0.000173865991087677,0.000169349991319166,0.000165007683849444,0.000160830274131736,0.000156809517278443,0.000152937677345642,0.000149207490093309,0.000145612128886241,0.000142145173436569,0.000138800581120414,0.000135572660629242,0.000132456047741213,0.000129445683019822,0.000126536791266568,0.000123724862571755,0.000121005634822925,0.000118375077544166,0.000115829376951819,0.000113364922123056,0.000110978292183624,0.000108666244429798,0.000106425703307534,0.000104253750178809,0.00010214761381156,0.000100104661535329,9.81223910098771e-05,9.61984225587031e-05,9.43304920235826e-05,9.25164441000522e-05,9.07542261171941e-05,8.90418822281904e-05,8.73775479809345e-05,8.57594452405468e-05,8.4185877437968e-05,8.2655225120914e-05,8.11659417854021e-05,7.97165499678056e-05,7.83056375789949e-05,7.69318544635739e-05,7.55939091685552e-05,7.42905659070284e-05,7.30206417034895e-05,7.17830037085151e-05,7.05765666713972e-05,6.94002905602072e-05,6.82531783195426e-05,6.71342737569272e-05,6.60426595494975e-05,6.49774553632153e-05,6.39378160774038e-05,6.29229301079212e-05,6.19320178227571e-05,6.09643300442765e-05,6.00191466327373e-05,5.90957751460799e-05,5.81935495713305e-05,5.73118291232801e-05,5.64499971063886e-05,5.5607459836144e-05,5.47836456163493e-05,5.39780037690501e-05,5.31900037140274e-05,5.24191340949836e-05,5.1664901949732e-05,5.09268319218787e-05,5.02044655116393e-05,4.9497360363588e-05,4.88050895892721e-05,4.81272411227544e-05,4.74634171072682e-05,4.68132333112782e-05,4.61763185723492e-05,4.55523142673175e-05,4.49408738073535e-05,4.43416621565888e-05,4.37543553730578e-05,4.31786401707807e-05,4.26142135018816e-05,4.20607821577013e-05,4.15180623879246e-05,4.09857795367973e-05,4.04636676955642e-05,3.99514693703039e-05,3.94489351643882e-05,3.89558234748333e-05,3.8471900201854e-05,3.79969384709669e-05,3.75307183670287e-05,3.70730266796259e-05,3.66236566592668e-05,3.61824077838539e-05,3.57490855349455e-05,3.5323501183339e-05,3.49054715835362e-05,3.4494818976671e-05,3.40913708015053e-05,3.36949595131157e-05,3.33054224089178e-05,3.29226014616889e-05,3.25463431592696e-05,3.21764983506415e-05,3.18129220980919e-05,3.1455473535192e-05,3.11040157303295e-05,3.07584155555481e-05,3.04185435604592e-05,3.00842738510036e-05,2.97554839728505e-05,2.94320547992326e-05,2.91138704230246e-05,2.88008180528846e-05,2.84927879132816e-05,2.81896731482467e-05,2.78913697286885e-05,2.75977763631233e-05,2.7308794411677e-05,2.70243278032221e-05,2.67442829555203e-05,2.64685686982469e-05,2.61970961987777e-05,2.59297788906269e-05,2.56665324044276e-05,2.54072745013526e-05,2.51519250088767e-05,2.49004057587879e-05,2.46526405273572e-05,2.44085549775814e-05,2.4168076603418e-05,2.39311346759335e-05,2.36976601912903e-05,2.3467585820501e-05,2.32408458608827e-05,2.30173761891434e-05,2.27971142160416e-05,2.25799988425555e-05,2.23659704175075e-05,2.21549706965877e-05,2.1946942802723e-05,2.17418311877443e-05,2.15395815953001e-05,2.13401410249733e-05,2.11434576975542e-05,2.09494810214298e-05,2.07581615600469e-05,2.05694510004101e-05,2.03833021225783e-05,2.01996687701227e-05,2.00185058215117e-05,1.98397691623911e-05,1.96634156587254e-05,1.94894031307721e-05,1.93176903278578e-05,1.91482369039292e-05,1.89810033938512e-05,1.88159511904264e-05,1.8653042522111e-05,1.84922404314032e-05,1.83335087538804e-05,1.81768120978643e-05,1.8022115824691e-05,1.78693860295665e-05,1.77185895229879e-05,1.75696938127107e-05,1.74226670862445e-05,1.72774781938591e-05,1.71340966320844e-05,1.6992492527687e-05,1.68526366221093e-05,1.67145002563543e-05,1.65780553563024e-05,1.64432744184463e-05,1.63101304960297e-05,1.61785971855779e-05,1.60486486138062e-05,1.59202594248957e-05,1.57934047681237e-05,1.5668060285837e-05,1.55442021017592e-05,1.54218068096194e-05,1.53008514620929e-05,1.51813135600453e-05,1.50631710420683e-05,1.49464022743003e-05,1.4830986040522e-05,1.4716901532518e-05,1.46041283406979e-05,1.44926464449674e-05,1.43824362058421e-05,1.42734783557979e-05,1.41657539908485e-05,1.40592445623459e-05,1.39539318689949e-05,1.38497980490771e-05,1.37468255728758e-05,1.36449972352989e-05,1.35442961486915e-05,1.34447057358335e-05,1.33462097231168e-05,1.32487921338969e-05,1.31524372820141e-05,1.30571297654777e-05,1.29628544603118e-05,1.28695965145542e-05,1.27773413424068e-05,1.26860746185325e-05,1.25957822724931e-05,1.25064504833265e-05,1.24180656742571e-05,1.23306145075369e-05,1.22440838794139e-05,1.21584609152222e-05,1.20737329645934e-05,1.19898875967838e-05,1.1906912596114e-05,1.18247959575201e-05,1.17435258822107e-05,1.16630907734284e-05,1.15834792323129e-05,1.15046800538618e-05,1.14266822229881e-05,1.13494749106706e-05,1.12730474701947e-05,1.1197389433482e-05,1.11224905075055e-05,1.10483405707888e-05,1.09749296699863e-05,1.09022480165426e-05,1.08302859834301e-05,1.07590341019602e-05,1.06884830586687e-05,1.06186236922721e-05,1.05494469906938e-05,1.04809440881568e-05,1.04131062623435e-05,1.03459249316187e-05,1.02793916523157e-05,1.02134981160829e-05,1.01482361472901e-05,1.0083597700492e-05,1.00195748579492e-05,9.95615982720272e-06,9.89334493870302e-06,9.83112264349106e-06,9.76948551092998e-06,9.70842622648667e-06,9.64793758956152e-06,9.58801251136548e-06,9.5286440128431e-06,9.46982522264036e-06,9.41154937511642e-06,9.35380980839792e-06,9.29659996247499e-06,9.23991337733795e-06,9.18374369115352e-06,9.12808463847987e-06,9.07293004851926e-06,9.0182738434077e-06,8.96411003654039e-06,8.91043273093236e-06,8.85723611761336e-06,8.80451447405614e-06,8.75226216263741e-06,8.70047362913068e-06,8.6491434012302e-06,8.59826608710532e-06,8.54783637398447e-06,8.49784902676818e-06,8.44829888667041e-06,8.39918086988744e-06,8.35048996629389e-06,8.30222123816503e-06,8.25436981892488e-06,8.20693091191957e-06,8.15989978921516e-06,8.11327179041964e-06,8.06704232152836e-06,8.02120685379241e-06,7.97576092260944e-06,7.93070012643651e-06,7.88602012572419e-06,7.84171664187181e-06,7.79778545620306e-06,7.7542224089617e-06,7.71102339832682e-06,7.66818437944722e-06,7.62570136349461e-06,7.58357041673497e-06,7.54178765961797e-06,7.50034926588381e-06,7.45925146168718e-06,7.41849052473807e-06,7.37806278345885e-06,7.33796461615744e-06,7.29819245021621e-06,7.25874276129612e-06,7.21961207255598e-06,7.18079695388632e-06,7.14229402115771e-06,7.10409993548307e-06,7.06621140249383e-06,7.0286251716295e-06,6.99133803544048e-06,6.95434682890376e-06,6.91764842875123e-06,6.88123975281044e-06,6.84511775935736e-06,6.80927944648115e-06,6.77372185146036e-06,6.73844205015067e-06,6.70343715638365e-06,6.66870432137648e-06,6.63424073315232e-06,6.60004361597112e-06,6.56611022977075e-06,6.53243786961808e-06,6.49902386516991e-06,6.46586558014353e-06,6.43296041179674e-06,6.40030579041707e-06,6.36789917882002e-06,6.33573807185628e-06,6.30381999592753e-06,6.27214250851081e-06,6.24070319769121e-06,6.20949968170275e-06,6.1785296084773e-06,6.1477906552013e-06,6.1172805278802e-06,6.08699696091049e-06,6.05693771665908e-06,6.02710058504993e-06,5.99748338315779e-06,5.96808395480898e-06,5.93890017018888e-06,5.90992992545625e-06,5.88117114236401e-06,5.85262176788651e-06,5.82427977385317e-06,5.79614315658817e-06,5.76820993655642e-06,5.74047815801529e-06,5.71294588867229e-06,5.6856112193485e-06,5.65847226364755e-06,5.63152715763018e-06,5.60477405949417e-06,5.5782111492596e-06,5.55183662845932e-06,5.52564871983451e-06,5.49964566703529e-06,5.4738257343262e-06,5.44818720629657e-06,5.42272838757556e-06,5.3974476025519e-06,5.37234319509817e-06,5.34741352829957e-06,5.32265698418707e-06,5.29807196347489e-06,5.2736568853022e-06,5.24941018697897e-06,5.22533032373594e-06,5.20141576847857e-06,5.17766501154488e-06,5.15407656046723e-06,5.13064893973783e-06,5.10738069057802e-06,5.08427037071115e-06,5.06131655413909e-06,5.03851783092225e-06,5.01587280696305e-06,4.99338010379281e-06,4.97103835836197e-06,4.94884622283357e-06,4.92680236437997e-06,4.90490546498272e-06,4.88315422123557e-06,4.86154734415046e-06,4.84008355896657e-06,4.81876160496231e-06,4.79758023527017e-06,4.77653821669442e-06,4.75563432953165e-06,4.73486736739396e-06,4.71423613703494e-06,4.69373945817827e-06,4.67337616334886e-06,4.65314509770666e-06,4.63304511888287e-06,4.61307509681872e-06,4.5932339136066e-06,4.57352046333361e-06,4.55393365192747e-06,4.5344723970047e-06,4.5151356277211e-06,4.49592228462441e-06,4.47683131950923e-06,4.45786169527403e-06,4.43901238578027e-06,4.42028237571368e-06,4.40167066044752e-06,4.38317624590782e-06,4.36479814844071e-06,4.34653539468154e-06,4.32838702142608e-06,4.31035207550348e-06,4.29242961365107e-06,4.27461870239111e-06,4.25691841790916e-06,4.23932784593433e-06,4.22184608162119e-06,4.20447222943345e-06,4.18720540302921e-06,4.17004472514794e-06,4.15298932749907e-06,4.13603835065214e-06,4.11919094392851e-06,4.10244626529465e-06,4.08580348125694e-06,4.06926176675793e-06,4.05282030507406e-06,4.03647828771489e-06,4.02023491432368e-06,4.00408939257941e-06,3.98804093810013e-06,3.97208877434773e-06,3.95623213253397e-06,3.94047025152786e-06,3.92480237776433e-06,3.90922776515415e-06,3.89374567499512e-06,3.87835537588447e-06,3.86305614363246e-06,3.84784726117722e-06,3.83272801850069e-06,3.81769771254578e-06,3.80275564713464e-06,3.78790113288802e-06,3.77313348714577e-06,3.75845203388839e-06,3.7438561036597e-06,3.72934503349048e-06,3.7149181668232e-06,3.70057485343778e-06,3.68631444937829e-06,3.67213631688068e-06,3.65803982430149e-06,3.64402434604746e-06,3.63008926250617e-06,3.61623395997752e-06,3.60245783060618e-06,3.5887602723149e-06,3.57514068873875e-06,3.56159848916019e-06,3.54813308844503e-06,3.5347439069792e-06,3.5214303706064e-06,3.50819191056653e-06,3.49502796343494e-06,3.48193797106253e-06,3.4689213805165e-06,3.45597764402204e-06,3.44310621890464e-06,3.43030656753324e-06,3.4175781572641e-06,3.40492046038535e-06,3.3923329540623e-06,3.37981512028347e-06,3.36736644580729e-06,3.35498642210947e-06,3.34267454533108e-06,3.33043031622731e-06,3.31825324011678e-06,3.30614282683169e-06,3.29409859066837e-06,3.28212005033866e-06,3.27020672892183e-06,3.25835815381704e-06,3.24657385669654e-06,3.23485337345937e-06,3.22319624418564e-06,3.21160201309145e-06,3.2000702284843e-06,3.18860044271912e-06,3.17719221215483e-06,3.16584509711142e-06,3.1545586618276e-06,3.14333247441896e-06,3.13216610683666e-06,3.1210591348266e-06,3.11001113788916e-06,3.09902169923937e-06,3.08809040576763e-06,3.07721684800084e-06,3.06640062006411e-06,3.05564131964283e-06,3.04493854794531e-06,3.03429190966578e-06,3.02370101294792e-06,3.0131654693488e-06,3.00268489380324e-06,2.99225890458865e-06,2.98188712329024e-06,2.97156917476675e-06,2.96130468711643e-06,2.95109329164362e-06,2.94093462282557e-06,2.93082831827977e-06,2.92077401873164e-06,2.91077136798256e-06,2.90082001287835e-06,2.89091960327808e-06,2.8810697920233e-06,2.87127023490758e-06,2.86152059064643e-06,2.85182052084763e-06,2.84216968998182e-06,2.8325677653535e-06,2.82301441707237e-06,2.81350931802499e-06,2.80405214384676e-06,2.79464257289425e-06,2.78528028621789e-06,2.77596496753489e-06,2.76669630320255e-06,2.75747398219187e-06,2.74829769606145e-06,2.73916713893168e-06,2.73008200745927e-06,2.72104200081205e-06,2.71204682064408e-06,2.703096171071e-06,2.69418975864572e-06,2.68532729233439e-06,2.67650848349257e-06,2.66773304584177e-06,2.65900069544622e-06,2.65031115068986e-06,2.64166413225367e-06,2.63305936309324e-06,2.62449656841651e-06,2.61597547566191e-06,2.60749581447662e-06,2.59905731669515e-06,2.5906597163181e-06,2.58230274949127e-06,2.57398615448486e-06,2.56570967167301e-06,2.55747304351354e-06,2.54927601452792e-06,2.54111833128143e-06,2.5329997423636e-06,2.52491999836882e-06,2.5168788518772e-06,2.50887605743562e-06,2.500911371539e-06,2.49298455261178e-06,2.48509536098959e-06,2.47724355890115e-06,2.46942891045036e-06,2.46165118159855e-06,2.45391014014698e-06,2.44620555571952e-06,2.43853719974547e-06,2.43090484544267e-06,2.42330826780066e-06,2.41574724356416e-06,2.4082215512166e-06,2.40073097096399e-06,2.39327528471876e-06,2.38585427608397e-06,2.37846773033758e-06,2.37111543441691e-06,2.36379717690327e-06,2.35651274800681e-06,2.3492619395514e-06,2.34204454495985e-06,2.33486035923911e-06,2.32770917896579e-06,2.32059080227171e-06,2.31350502882965e-06,2.30645165983932e-06,2.29943049801333e-06,2.29244134756344e-06,2.28548401418692e-06,2.27855830505302e-06,2.27166402878962e-06,2.26480099547001e-06,2.25796901659982e-06,2.25116790510403e-06,2.24439747531425e-06,2.23765754295595e-06,2.23094792513599e-06,2.22426844033019e-06,2.21761890837106e-06,2.21099915043562e-06,2.20440898903343e-06,2.19784824799464e-06,2.19131675245825e-06,2.18481432886045e-06,2.17834080492309e-06,2.17189600964225e-06,2.16547977327699e-06,2.15909192733812e-06,2.15273230457718e-06,2.14640073897548e-06,2.14009706573326e-06,2.13382112125897e-06,2.12757274315865e-06,2.12135177022544e-06,2.11515804242916e-06,2.10899140090604e-06,2.10285168794853e-06,2.09673874699519e-06,2.09065242262075e-06,2.0845925605262e-06,2.07855900752902e-06,2.0725516115535e-06,2.06657022162116e-06,2.06061468784128e-06,2.05468486140145e-06,2.04878059455834e-06,2.04290174062847e-06,2.03704815397911e-06,2.03121969001922e-06,2.0254162051906e-06,2.01963755695895e-06,2.01388360380523e-06,2.00815420521688e-06,2.00244922167933e-06,1.99676851466747e-06,1.99111194663725e-06,1.98547938101734e-06,1.97987068220091e-06,1.97428571553744e-06,1.96872434732466e-06,1.96318644480054e-06,1.95767187613537e-06,1.95218051042391e-06,1.94671221767762e-06,1.94126686881699e-06,1.93584433566387e-06,1.93044449093398e-06,1.92506720822943e-06,1.91971236203129e-06,1.91437982769232e-06,1.90906948142965e-06,1.90378120031766e-06,1.89851486228082e-06,1.89327034608667e-06,1.88804753133884e-06,1.88284629847014e-06,1.8776665287357e-06,1.8725081042062e-06,1.86737090776119e-06,1.8622548230824e-06,1.85715973464715e-06,1.85208552772189e-06,1.84703208835566e-06,1.84199930337376e-06,1.83698706037139e-06,1.83199524770733e-06,1.82702375449782e-06,1.82207247061029e-06,1.81714128665735e-06,1.81223009399071e-06,1.80733878469519e-06,1.8024672515828e-06,1.79761538818689e-06,1.79278308875628e-06,1.78797024824955e-06,1.78317676232931e-06,1.77840252735654e-06,1.773647440385e-06,1.76891139915566e-06,1.76419430209125e-06,1.75949604829074e-06,1.75481653752401e-06,1.75015567022647e-06,1.74551334749377e-06,1.74088947107657e-06,1.73628394337531e-06,1.73169666743508e-06,1.72712754694053e-06,1.72257648621078e-06,1.71804339019444e-06,1.71352816446462e-06,1.70903071521406e-06,1.7045509492502e-06,1.70008877399038e-06,1.69564409745707e-06,1.69121682827311e-06,1.68680687565701e-06,1.68241414941832e-06,1.67803855995299e-06,1.67368001823883e-06,1.66933843583095e-06,1.66501372485729e-06,1.6607057980142e-06,1.65641456856196e-06,1.65213995032051e-06,1.64788185766505e-06,1.64364020552176e-06,1.63941490936361e-06,1.63520588520607e-06,1.63101304960297e-06,1.6268363196424e-06,1.62267561294255e-06,1.61853084764768e-06,1.61440194242409e-06,1.61028881645613e-06,1.60619138944224e-06,1.60210958159106e-06,1.59804331361748e-06,1.59399250673885e-06,1.58995708267116e-06,1.58593696362521e-06,1.58193207230293e-06,1.57794233189359e-06,1.57396766607018e-06,1.57000799898572e-06,1.56606325526968e-06,1.56213336002434e-06,1.55821823882127e-06,1.55431781769781e-06,1.55043202315357e-06,1.54656078214694e-06,1.54270402209171e-06,1.53886167085362e-06,1.53503365674702e-06,1.5312199085315e-06,1.5274203554086e-06,1.52363492701849e-06,1.51986355343676e-06,1.51610616517115e-06,1.51236269315839e-06,1.50863306876096e-06,1.50491722376401e-06,1.50121509037221e-06,1.49752660120668e-06,1.49385168930188e-06,1.49019028810261e-06,1.48654233146099e-06,1.48290775363345e-06,1.47928648927782e-06,1.47567847345031e-06,1.47208364160268e-06,1.46850192957932e-06,1.46493327361436e-06,1.46137761032889e-06,1.4578348767281e-06,1.45430501019849e-06,1.45078794850514e-06,1.44728362978895e-06,1.44379199256388e-06,1.44031297571433e-06,1.43684651849239e-06,1.43339256051525e-06,1.42995104176251e-06,1.42652190257363e-06,1.42310508364531e-06,1.41970052602894e-06,1.41630817112803e-06,1.41292796069574e-06,1.40955983683235e-06,1.40620374198274e-06,1.40285961893403e-06,1.39952741081305e-06,1.39620706108396e-06,1.39289851354584e-06,1.38960171233035e-06,1.38631660189931e-06,1.3830431270424e-06,1.37978123287485e-06,1.3765308648351e-06,1.37329196868255e-06,1.37006449049528e-06,1.36684837666782e-06,1.36364357390893e-06,1.36045002923936e-06,1.35726768998967e-06,1.35409650379811e-06,1.35093641860838e-06,1.34778738266757e-06,1.34464934452399e-06,1.3415222530251e-06,1.3384060573154e-06,1.33530070683439e-06,1.33220615131449e-06,1.32912234077904e-06,1.32604922554025e-06,1.3229867561972e-06,1.31993488363388e-06,1.31689355901721e-06,1.31386273379508e-06,1.3108423596944e-06,1.30783238871921e-06,1.30483277314876e-06,1.30184346553559e-06,1.2988644187037e-06,1.29589558574666e-06,1.29293692002578e-06,1.28998837516825e-06,1.28704990506536e-06,1.28412146387067e-06,1.28120300599824e-06,1.27829448612083e-06,1.27539585916818e-06,1.27250708032521e-06,1.26962810503036e-06,1.2667588889738e-06,1.26389938809575e-06,1.26104955858482e-06,1.2582093568763e-06,1.25537873965048e-06,1.25255766383104e-06,1.24974608658339e-06,1.24694396531302e-06,1.24415125766394e-06,1.24136792151704e-06,1.23859391498851e-06,1.23582919642827e-06,1.2330737244184e-06,1.23032745777159e-06,1.2275903555296e-06,1.22486237696176e-06,1.2221434815634e-06,1.21943362905439e-06,1.21673277937763e-06,1.21404089269759e-06,1.21135792939882e-06,1.20868385008447e-06,1.20601861557491e-06,1.20336218690624e-06,1.20071452532889e-06,1.19807559230619e-06,1.19544534951298e-06,1.19282375883423e-06,1.19021078236362e-06,1.18760638240221e-06,1.18501052145707e-06,1.18242316223991e-06,1.17984426766578e-06,1.17727380085169e-06,1.17471172511534e-06,1.17215800397379e-06,1.16961260114214e-06,1.16707548053229e-06,1.16454660625161e-06,1.16202594260172e-06,1.15951345407717e-06,1.15700910536426e-06,1.15451286133974e-06,1.15202468706962e-06,1.14954454780789e-06,1.1470724089954e-06,1.14460823625857e-06,1.14215199540823e-06,1.13970365243844e-06,1.13726317352529e-06,1.13483052502578e-06,1.13240567347657e-06,1.12998858559295e-06,1.1275792282676e-06,1.12517756856947e-06,1.12278357374273e-06,1.12039721120555e-06,1.11801844854906e-06,1.11564725353624e-06,1.11328359410078e-06,1.11092743834607e-06,1.10857875454407e-06,1.10623751113426e-06,1.10390367672258e-06,1.10157722008039e-06,1.09925811014337e-06,1.09694631601058e-06,1.09464180694333e-06,1.09234455236423e-06,1.09005452185613e-06,1.08777168516114e-06,1.08549601217963e-06,1.08322747296922e-06,1.08096603774382e-06,1.07871167687261e-06,1.07646436087913e-06,1.07422406044025e-06,1.07199074638528e-06,1.06976438969497e-06,1.06754496150058e-06,1.06533243308297e-06,1.06312677587161e-06,1.06092796144375e-06,1.05873596152341e-06,1.05655074798054e-06,1.05437229283006e-06,1.05220056823103e-06,1.0500355464857e-06,1.04787720003866e-06,1.04572550147595e-06,1.0435804235242e-06,1.04144193904977e-06,1.03931002105785e-06,1.03718464269168e-06,1.03506577723164e-06,1.03295339809443e-06,1.03084747883226e-06,1.02874799313199e-06,1.02665491481433e-06,1.024568217833e-06,1.02248787627395e-06,1.02041386435453e-06,1.0183461564227e-06,1.01628472695626e-06,1.01422955056201e-06,1.01218060197502e-06,1.01013785605781e-06,1.00810128779963e-06,1.00607087231564e-06,1.0040465848462e-06,1.00202840075605e-06,1.00001629553365e-06,9.98010244790354e-07,9.96010224259712e-07,9.9401620979673e-07,9.92028177377136e-07,9.90046103096662e-07,9.88069963170322e-07,9.86099733931697e-07,9.84135391832232e-07,9.82176913440526e-07,9.80224275441638e-07,9.78277454636391e-07,9.76336427940684e-07,9.74401172384806e-07,9.72471665112757e-07,9.70547883381574e-07,9.68629804560662e-07,9.66717406131125e-07,9.64810665685107e-07,9.62909560925136e-07,9.61014069663472e-07,9.5912416982146e-07,9.57239839428883e-07,9.55361056623331e-07,9.5348779964956e-07,9.51620046858865e-07,9.49757776708456e-07,9.47900967760835e-07,9.46049598683177e-07,9.44203648246722e-07,9.42363095326163e-07,9.40527918899043e-07,9.38698098045154e-07,9.36873611945941e-07,9.35054439883909e-07,9.3324056124204e-07,9.31431955503199e-07,9.29628602249562e-07,9.27830481162039e-07,9.26037572019697e-07,9.24249854699195e-07,9.22467309174221e-07,9.20689915514926e-07,9.18917653887371e-07,9.17150504552972e-07,9.15388447867951e-07,9.13631464282792e-07,9.11879534341694e-07,9.10132638682036e-07,9.0839075803384e-07,9.06653873219244e-07,9.04921965151968e-07,9.03195014836792e-07,9.01473003369039e-07,8.9975591193405e-07,8.98043721806678e-07,8.96336414350771e-07,8.94633971018671e-07,8.92936373350704e-07,8.91243602974684e-07,8.89555641605414e-07,8.87872471044192e-07,8.86194073178324e-07,8.84520429980632e-07,8.8285152350897e-07,8.81187335905748e-07,8.79527849397451e-07,8.77873046294164e-07,8.76222908989099e-07,8.74577419958134e-07,8.72936561759338e-07,8.71300317032517e-07,8.69668668498748e-07,8.68041598959929e-07,8.66419091298322e-07,8.64801128476103e-07,8.63187693534916e-07,8.61578769595428e-07,8.59974339856889e-07,8.58374387596691e-07,8.56778896169931e-07,8.55187849008984e-07,8.53601229623068e-07,8.52019021597816e-07,8.50441208594857e-07,8.48867774351389e-07,8.4729870267976e-07,8.45733977467054e-07,8.4417358267468e-07,8.42617502337952e-07,8.41065720565691e-07,8.39518221539811e-07,8.37974989514922e-07,8.36436008817925e-07,8.34901263847616e-07,8.33370739074294e-07,8.31844419039359e-07,8.30322288354932e-07,8.2880433170346e-07,8.27290533837335e-07,8.25780879578508e-07,8.2427535381811e-07,8.22773941516073e-07,8.21276627700757e-07,8.19783397468574e-07,8.18294235983618e-07,8.16809128477295e-07,8.15328060247962e-07,8.13851016660556e-07,8.12377983146238e-07,8.10908945202032e-07,8.09443888390465e-07,8.07982798339219e-07,8.06525660740771e-07,8.05072461352049e-07,8.0362318599408e-07,8.02177820551645e-07,8.00736350972935e-07,7.99298763269214e-07,7.97865043514471e-07,7.9643517784509e-07,7.95009152459512e-07,7.93586953617903e-07,7.92168567641821e-07,7.90753980913889e-07,7.89343179877468e-07,7.87936151036332e-07,7.86532880954344e-07,7.85133356255137e-07,7.83737563621794e-07,7.82345489796534e-07,7.80957121580391e-07,7.79572445832908e-07,7.78191449471822e-07,7.76814119472757e-07,7.75440442868915e-07,7.74070406750772e-07,7.72703998265775e-07,7.7134120461804e-07,7.69982013068052e-07,7.68626410932369e-07,7.67274385583323e-07,7.6592592444873e-07,7.64581015011595e-07,7.6323964480982e-07,7.6190180143592e-07,7.60567472536733e-07,7.59236645813134e-07,7.57909309019755e-07,7.56585449964698e-07,7.55265056509263e-07,7.5394811656766e-07,7.5263461810674e-07,7.51324549145719e-07,7.500178977559e-07,7.48714652060408e-07,7.47414800233914e-07,7.46118330502372e-07,7.4482523114275e-07,7.43535490482762e-07,7.42249096900612e-07,7.40966038824725e-07,7.39686304733491e-07,7.38409883155003e-07,7.37136762666805e-07,7.3586693189563e-07,7.34600379517153e-07,7.3333709425573e-07,7.32077064884157e-07,7.30820280223411e-07,7.29566729142411e-07,7.28316400557762e-07,7.27069283433519e-07,7.25825366780938e-07,7.24584639658236e-07,7.23347091170348e-07,7.22112710468693e-07,7.20881486750928e-07,7.19653409260722e-07,7.18428467287513e-07,7.17206650166275e-07,7.15987947277293e-07,7.14772348045922e-07,7.13559841942367e-07,7.12350418481447e-07,7.11144067222376e-07,7.09940777768531e-07,7.08740539767232e-07,7.07543342909517e-07,7.06349176929923e-07,7.05158031606264e-07,7.03969896759412e-07,7.02784762253083e-07,7.01602617993616e-07,7.00423453929762e-07,6.99247260052466e-07,6.98074026394659e-07,6.96903743031047e-07,6.95736400077897e-07,6.94571987692829e-07,6.93410496074614e-07,6.9225191546296e-07,6.91096236138314e-07,6.89943448421653e-07,6.88793542674283e-07,6.8764650929764e-07,6.86502338733085e-07,6.85361021461708e-07,6.84222548004131e-07,6.83086908920307e-07,6.81954094809328e-07,6.80824096309229e-07,6.79696904096797e-07,6.78572508887373e-07,6.77450901434666e-07,6.76332072530563e-07,6.75216013004935e-07,6.74102713725454e-07,6.72992165597406e-07,6.71884359563501e-07,6.70779286603692e-07,6.69676937734993e-07,6.6857730401129e-07,6.67480376523166e-07,6.66386146397719e-07,6.65294604798377e-07,6.6420574292473e-07,6.63119552012343e-07,6.62036023332585e-07,6.6095514819245e-07,6.59876917934387e-07,6.58801323936124e-07,6.57728357610495e-07,6.56658010405271e-07,6.55590273802985e-07,6.54525139320771e-07,6.53462598510185e-07,6.52402642957046e-07,6.51345264281265e-07,6.5029045413668e-07,6.49238204210893e-07,6.48188506225103e-07,6.47141351933948e-07,6.46096733125338e-07,6.45054641620297e-07,6.44015069272802e-07,6.42978007969625e-07,6.41943449630173e-07,6.4091138620633e-07,6.39881809682304e-07,6.38854712074468e-07,6.37830085431205e-07,6.36807921832757e-07,6.35788213391071e-07,6.34770952249646e-07,6.33756130583379e-07,6.32743740598422e-07,6.31733774532024e-07,6.30726224652387e-07,6.29721083258519e-07,6.28718342680082e-07,6.27717995277249e-07,6.26720033440561e-07,6.25724449590774e-07,6.24731236178725e-07,6.23740385685183e-07,6.22751890620705e-07,6.21765743525502e-07,6.20781936969291e-07,6.19800463551158e-07,6.18821315899418e-07,6.17844486671479e-07,6.16869968553701e-07,6.1589775426126e-07,6.14927836538014e-07,6.13960208156365e-07,6.12994861917125e-07,6.12031790649384e-07,6.11070987210374e-07,6.10112444485338e-07,6.09156155387399e-07,6.08202112857426e-07,6.07250309863909e-07,6.06300739402824e-07,6.05353394497507e-07,6.04408268198526e-07,6.03465353583552e-07,6.02524643757233e-07,6.01586131851069e-07,6.00649811023285e-07,5.99715674458708e-07,5.9878371536864e-07,5.97853926990738e-07,5.96926302588891e-07,5.96000835453094e-07,5.95077518899332e-07,5.94156346269457e-07,5.93237310931067e-07,5.92320406277387e-07,5.91405625727151e-07,5.90492962724486e-07,5.89582410738789e-07,5.88673963264615e-07,5.8776761382156e-07,5.86863355954142e-07,5.85961183231691e-07,5.85061089248232e-07,5.84163067622372e-07,5.83267111997184e-07,5.823732160401e-07,5.81481373442795e-07,5.80591577921077e-07,5.79703823214776e-07,5.78818103087633e-07,5.77934411327194e-07,5.77052741744696e-07,5.76173088174964e-07,5.75295444476297e-07,5.74419804530366e-07,5.73546162242107e-07,5.72674511539611e-07,5.71804846374023e-07,5.70937160719435e-07,5.70071448572779e-07,5.69207703953729e-07,5.68345920904594e-07,5.67486093490215e-07,5.66628215797864e-07,5.65772281937142e-07,5.64918286039879e-07,5.6406622226003e-07,5.63216084773579e-07,5.62367867778438e-07,5.61521565494347e-07,5.60677172162777e-07,5.5983468204683e-07,5.58994089431144e-07,5.58155388621795e-07,5.573185739462e-07,5.56483639753022e-07,5.55650580412074e-07,5.54819390314225e-07,5.53990063871304e-07,5.53162595516007e-07,5.52336979701804e-07,5.51513210902845e-07,5.5069128361387e-07,5.49871192350111e-07,5.49052931647209e-07,5.48236496061117e-07,5.47421880168009e-07,5.46609078564196e-07,5.4579808586603e-07,5.44988896709816e-07,5.44181505751728e-07,5.43375907667713e-07,5.42572097153412e-07,5.41770068924065e-07,5.40969817714428e-07,5.40171338278687e-07,5.39374625390371e-07,5.38579673842264e-07,5.37786478446325e-07,5.36995034033601e-07,5.3620533545414e-07,5.35417377576911e-07,5.3463115528972e-07,5.33846663499126e-07,5.33063897130359e-07,5.32282851127238e-07,5.31503520452088e-07,5.30725900085662e-07,5.29949985027058e-07,5.29175770293636e-07,5.28403250920945e-07,5.27632421962635e-07,5.26863278490387e-07,5.26095815593824e-07,5.25330028380441e-07,5.24565911975524e-07,5.23803461522071e-07,5.23042672180718e-07,5.22283539129657e-07,5.21526057564567e-07,5.20770222698531e-07,5.20016029761966e-07,5.19263474002542e-07,5.18512550685112e-07,5.17763255091637e-07,5.17015582521107e-07,5.16269528289475e-07,5.15525087729577e-07,5.14782256191062e-07,5.14041029040318e-07,5.13301401660404e-07,5.12563369450972e-07,5.11826927828197e-07,5.11092072224711e-07,5.10358798089525e-07,5.09627100887963e-07,5.0889697610159e-07,5.08168419228145e-07,5.07441425781467e-07,5.06715991291429e-07,5.0599211130387e-07,5.05269781380524e-07,5.04548997098954e-07,5.03829754052483e-07,5.03112047850129e-07,5.02395874116535e-07,5.01681228491903e-07,5.00968106631928e-07,5.00256504207735e-07,4.99546416905808e-07,4.98837840427927e-07,4.98130770491105e-07,4.9742520282752e-07,4.96721133184452e-07,4.9601855732422e-07,4.95317471024115e-07,4.94617870076341e-07,4.93919750287948e-07,4.93223107480772e-07,4.92527937491369e-07,4.91834236170959e-07,4.91141999385356e-07,4.90451223014913e-07,4.89761902954456e-07,4.89074035113228e-07,4.88387615414823e-07,4.87702639797131e-07,4.87019104212271e-07,4.8633700462654e-07,4.85656337020345e-07,4.84977097388148e-07,4.84299281738409e-07,4.83622886093523e-07,4.82947906489764e-07,4.82274338977226e-07,4.81602179619766e-07,4.80931424494948e-07,4.80262069693981e-07,4.79594111321666e-07,4.78927545496341e-07,4.78262368349818e-07,4.77598576027334e-07,4.7693616468749e-07,4.76275130502199e-07,4.75615469656628e-07,4.74957178349145e-07,4.74300252791263e-07,4.73644689207584e-07,4.72990483835751e-07,4.72337632926384e-07,4.71686132743038e-07,4.71035979562137e-07,4.70387169672933e-07,4.69739699377444e-07,4.69093564990405e-07,4.68448762839215e-07,4.67805289263887e-07,4.67163140616991e-07,4.66522313263607e-07,4.65882803581271e-07,4.65244607959927e-07,4.64607722801871e-07,4.63972144521704e-07,4.63337869546282e-07,4.62704894314661e-07,4.62073215278054e-07,4.61442828899776e-07,4.60813731655195e-07,4.60185920031687e-07,4.5955939052858e-07,4.58934139657113e-07,4.5831016394038e-07,4.57687459913287e-07,4.57066024122502e-07,4.56445853126406e-07,4.55826943495048e-07,4.55209291810096e-07,4.54592894664787e-07,4.53977748663888e-07,4.53363850423639e-07,4.52751196571715e-07,4.52139783747176e-07,4.51529608600418e-07,4.50920667793135e-07,4.50312957998266e-07,4.49706475899951e-07,4.49101218193491e-07,4.48497181585296e-07,4.47894362792842e-07,4.47292758544632e-07,4.46692365580142e-07,4.46093180649786e-07,4.45495200514867e-07,4.44898421947533e-07,4.44302841730736e-07,4.43708456658186e-07,4.43115263534312e-07,4.42523259174213e-07,4.41932440403619e-07,4.41342804058852e-07,4.40754346986773e-07,4.40167066044752e-07,4.39580958100618e-07,4.3899602003262e-07,4.38412248729385e-07,4.37829641089877e-07,4.37248194023357e-07,4.36667904449338e-07,4.36088769297548e-07,4.35510785507889e-07,4.34933950030396e-07,4.34358259825193e-07,4.33783711862462e-07,4.33210303122392e-07,4.3263803059515e-07,4.32066891280833e-07,4.31496882189433e-07,4.30928000340799e-07,4.30360242764592e-07,4.29793606500254e-07,4.29228088596964e-07,4.28663686113602e-07,4.28100396118709e-07,4.27538215690451e-07,4.26977141916579e-07,4.26417171894393e-07,4.25858302730705e-07,4.25300531541797e-07,4.24743855453392e-07,4.24188271600608e-07,4.23633777127927e-07,4.23080369189158e-07,4.22528044947397e-07,4.21976801574993e-07,4.21426636253513e-07,4.20877546173704e-07,4.20329528535457e-07,4.19782580547773e-07,4.19236699428725e-07,4.18691882405426e-07,4.1814812671399e-07,4.17605429599501e-07,4.17063788315973e-07,4.16523200126322e-07,4.15983662302324e-07,4.15445172124587e-07,4.14907726882511e-07,4.1437132387426e-07,4.13835960406722e-07,4.1330163379548e-07,4.12768341364776e-07,4.12236080447478e-07,4.11704848385046e-07,4.11174642527499e-07,4.10645460233384e-07,4.10117298869739e-07,4.09590155812066e-07,4.09064028444292e-07,4.08538914158741e-07,4.080148103561e-07,4.07491714445387e-07,4.0696962384392e-07,4.06448535977282e-07,4.05928448279294e-07,4.05409358191981e-07,4.04891263165537e-07,4.04374160658302e-07,4.03858048136721e-07,4.03342923075322e-07,4.02828782956679e-07,4.02315625271384e-07,4.01803447518015e-07,4.01292247203107e-07,4.00782021841119e-07,4.00272768954409e-07,3.99764486073197e-07,3.99257170735541e-07,3.98750820487303e-07,3.98245432882123e-07,3.97741005481385e-07,3.97237535854194e-07,3.96735021577338e-07,3.96233460235268e-07,3.95732849420063e-07,3.95233186731401e-07,3.94734469776535e-07,3.94236696170259e-07,3.93739863534884e-07,3.93243969500205e-07,3.92749011703477e-07,3.92254987789385e-07,3.91761895410014e-07,3.91269732224826e-07,3.90778495900626e-07,3.90288184111542e-07,3.89798794538988e-07,3.89310324871646e-07,3.88822772805432e-07,3.88336136043473e-07,3.87850412296076e-07,3.87365599280706e-07,3.86881694721955e-07,3.86398696351515e-07,3.85916601908157e-07,3.85435409137698e-07,3.84955115792978e-07,3.84475719633834e-07,3.83997218427071e-07,3.8351960994644e-07,3.8304289197261e-07,3.82567062293141e-07,3.82092118702461e-07,3.81618059001837e-07,3.81144880999355e-07,3.80672582509889e-07,3.80201161355078e-07,3.79730615363302e-07,3.79260942369655e-07,3.78792140215922e-07,3.78324206750554e-07,3.7785713982864e-07,3.77390937311886e-07,3.76925597068592e-07,3.76461116973621e-07,3.75997494908383e-07,3.75534728760803e-07,3.75072816425304e-07,3.74611755802777e-07,3.74151544800563e-07,3.73692181332422e-07,3.73233663318517e-07,3.72775988685386e-07,3.72319155365919e-07,3.71863161299334e-07,3.71408004431159e-07,3.709536827132e-07,3.70500194103527e-07,3.70047536566442e-07,3.69595708072466e-07,3.69144706598308e-07,3.68694530126847e-07,3.68245176647107e-07,3.67796644154236e-07,3.67348930649483e-07,3.66902034140177e-07,3.66455952639703e-07,3.66010684167479e-07,3.6556622674894e-07,3.65122578415507e-07,3.64679737204572e-07,3.64237701159476e-07,3.63796468329482e-07,3.63356036769761e-07,3.62916404541365e-07,3.62477569711206e-07,3.62039530352038e-07,3.61602284542434e-07,3.61165830366765e-07,3.60730165915176e-07,3.60295289283573e-07,3.59861198573592e-07,3.59427891892589e-07,3.58995367353608e-07,3.58563623075372e-07,3.58132657182253e-07,3.57702467804256e-07,3.57273053077e-07,3.56844411141695e-07,3.56416540145122e-07,3.55989438239615e-07,3.55563103583041e-07,3.55137534338776e-07,3.54712728675692e-07,3.5428868476813e-07,3.53865400795886e-07,3.53442874944189e-07,3.53021105403683e-07,3.52600090370405e-07,3.52179828045768e-07,3.51760316636541e-07,3.51341554354831e-07,3.50923539418062e-07,3.50506270048956e-07,3.50089744475517e-07,3.49673960931009e-07,3.49258917653939e-07,3.48844612888039e-07,3.48431044882244e-07,3.48018211890678e-07,3.47606112172631e-07,3.47194743992545e-07,3.46784105619993e-07,3.46374195329662e-07,3.45965011401334e-07,3.45556552119868e-07,3.45148815775184e-07,3.44741800662242e-07,3.44335505081025e-07,3.43929927336524e-07,3.43525065738718e-07,3.43120918602555e-07,3.42717484247937e-07,3.42314760999702e-07,3.41912747187606e-07,3.41511441146306e-07,3.41110841215343e-07,3.40710945739123e-07,3.40311753066904e-07,3.39913261552774e-07,3.39515469555638e-07,3.39118375439198e-07,3.3872197757194e-07,3.38326274327113e-07,3.37931264082715e-07,3.37536945221475e-07,3.37143316130838e-07,3.36750375202946e-07,3.36358120834626e-07,3.35966551427368e-07,3.35575665387313e-07,3.35185461125235e-07,3.34795937056524e-07,3.34407091601174e-07,3.34018923183761e-07,3.33631430233432e-07,3.33244611183886e-07,3.3285846447336e-07,3.32472988544613e-07,3.32088181844908e-07,3.31704042826002e-07,3.31320569944122e-07,3.30937761659958e-07,3.30555616438641e-07,3.30174132749734e-07,3.29793309067208e-07,3.29413143869436e-07,3.29033635639172e-07,3.28654782863536e-07,3.28276584034004e-07,3.27899037646386e-07,3.27522142200815e-07,3.27145896201733e-07,3.26770298157874e-07,3.26395346582248e-07,3.26021039992131e-07,3.25647376909045e-07,3.25274355858748e-07,3.24901975371217e-07,3.24530233980632e-07,3.24159130225366e-07,3.23788662647965e-07,3.2341882979514e-07,3.23049630217749e-07,3.2268106247078e-07,3.22313125113345e-07,3.21945816708658e-07,3.21579135824024e-07,3.21213081030826e-07,3.20847650904511e-07,3.20482844024574e-07,3.20118658974546e-07,3.1975509434198e-07,3.19392148718436e-07,3.1902982069947e-07,3.18668108884618e-07,3.18307011877384e-07,3.17946528285224e-07,3.17586656719536e-07,3.17227395795645e-07,3.16868744132789e-07,3.16510700354108e-07,3.16153263086628e-07,3.15796430961248e-07,3.1544020261273e-07,3.15084576679683e-07,3.14729551804551e-07,3.143751266336e-07,3.14021299816904e-07,3.13668070008337e-07,3.1331543586555e-07,3.12963396049971e-07,3.12611949226782e-07,3.12261094064911e-07,3.1191082923702e-07,3.1156115341949e-07,3.11212065292409e-07,3.10863563539562e-07,3.10515646848415e-07,3.10168313910106e-07,3.0982156341943e-07,3.09475394074827e-07,3.09129804578373e-07,3.08784793635763e-07,3.08440359956303e-07,3.08096502252896e-07,3.07753219242029e-07,3.07410509643764e-07,3.07068372181723e-07,3.06726805583078e-07,3.06385808578539e-07,3.06045379902341e-07,3.05705518292232e-07,3.05366222489466e-07,3.05027491238785e-07,3.04689323288409e-07,3.04351717390029e-07,3.04014672298788e-07,3.03678186773278e-07,3.0334225957552e-07,3.03006889470959e-07,3.02672075228449e-07,3.02337815620246e-07,3.02004109421989e-07,3.01670955412699e-07,3.01338352374757e-07,3.01006299093904e-07,3.00674794359219e-07,3.00343836963116e-07,3.00013425701331e-07,2.99683559372907e-07,2.99354236780189e-07,2.99025456728811e-07,2.98697218027681e-07,2.98369519488979e-07,2.98042359928135e-07,2.97715738163831e-07,2.97389653017978e-07,2.97064103315714e-07,2.9673908788539e-07,2.96414605558561e-07,2.96090655169972e-07,2.95767235557553e-07,2.95444345562403e-07,2.95121984028783e-07,2.94800149804106e-07,2.94478841738924e-07,2.94158058686921e-07,2.938377995049e-07,2.93518063052772e-07,2.93198848193552e-07,2.92880153793342e-07,2.92561978721323e-07,2.92244321849747e-07,2.91927182053926e-07,2.91610558212219e-07,2.91294449206026e-07,2.90978853919779e-07,2.90663771240928e-07,2.90349200059931e-07,2.9003513927025e-07,2.89721587768336e-07,2.89408544453622e-07,2.8909600822851e-07,2.88783977998366e-07,2.88472452671506e-07,2.88161431159192e-07,2.87850912375615e-07,2.87540895237893e-07,2.87231378666054e-07,2.86922361583035e-07,2.86613842914667e-07,2.86305821589664e-07,2.85998296539622e-07,2.85691266698999e-07,2.85384731005116e-07,2.8507868839814e-07,2.84773137821079e-07,2.84468078219771e-07,2.84163508542876e-07,2.83859427741867e-07,2.8355583477102e-07,2.83252728587406e-07,2.82950108150881e-07,2.82647972424078e-07,2.82346320372398e-07,2.82045150964001e-07,2.81744463169796e-07,2.81444255963435e-07,2.81144528321302e-07,2.80845279222503e-07,2.80546507648862e-07,2.80248212584908e-07,2.79950393017868e-07,2.79653047937658e-07,2.79356176336875e-07,2.79059777210788e-07,2.7876384955733e-07,2.78468392377089e-07,2.781734046733e-07,2.77878885451835e-07,2.77584833721198e-07,2.77291248492514e-07,2.7699812877952e-07,2.76705473598559e-07,2.76413281968571e-07,2.76121552911084e-07,2.75830285450207e-07,2.75539478612622e-07,2.75249131427571e-07,2.74959242926858e-07,2.74669812144829e-07,2.74380838118375e-07,2.74092319886915e-07,2.73804256492394e-07,2.73516646979272e-07,2.73229490394517e-07,2.72942785787597e-07,2.72656532210473e-07,2.7237072871759e-07,2.72085374365869e-07,2.71800468214701e-07,2.71516009325936e-07,2.71231996763879e-07,2.70948429595282e-07,2.7066530688933e-07,2.70382627717644e-07,2.70100391154265e-07,2.69818596275648e-07,2.69537242160658e-07,2.69256327890558e-07,2.68975852549005e-07,2.68695815222041e-07,2.68416214998085e-07,2.68137050967926e-07,2.67858322224716e-07,2.67580027863963e-07,2.67302166983523e-07,2.67024738683592e-07,2.667477420667e-07,2.66471176237704e-07,2.66195040303779e-07,2.65919333374412e-07,2.65644054561395e-07,2.65369202978817e-07,2.65094777743058e-07,2.64820777972781e-07,2.64547202788925e-07,2.64274051314698e-07,2.6400132267557e-07,2.63729015999267e-07,2.63457130415763e-07,2.63185665057272e-07,2.62914619058243e-07,2.62643991555352e-07,2.62373781687497e-07,2.62103988595787e-07,2.61834611423541e-07,2.61565649316275e-07,2.61297101421699e-07,2.61028966889712e-07,2.60761244872389e-07,2.60493934523981e-07,2.60227035000903e-07,2.59960545461732e-07,2.59694465067196e-07,2.5942879298017e-07,2.59163528365671e-07,2.58898670390847e-07,2.58634218224973e-07,2.58370171039444e-07,2.58106528007771e-07,2.57843288305571e-07,2.5758045111056e-07,2.57318015602551e-07,2.57055980963445e-07,2.56794346377222e-07,2.56533111029941e-07,2.56272274109728e-07,2.56011834806771e-07,2.55751792313316e-07,2.55492145823657e-07,2.55232894534136e-07,2.54974037643127e-07,2.54715574351041e-07,2.54457503860311e-07,2.54199825375389e-07,2.53942538102742e-07,2.53685641250842e-07,2.53429134030164e-07,2.53173015653175e-07,2.52917285334334e-07,2.52661942290079e-07,2.52406985738827e-07,2.52152414900967e-07,2.51898228998849e-07,2.51644427256785e-07,2.51391008901038e-07,2.51137973159819e-07,2.50885319263279e-07,2.50633046443508e-07,2.50381153934519e-07,2.50129640972254e-07,2.49878506794571e-07,2.4962775064124e-07,2.49377371753937e-07,2.49127369376239e-07,2.48877742753617e-07,2.48628491133433e-07,2.48379613764931e-07,2.48131109899234e-07,2.47882978789334e-07,2.47635219690095e-07,2.47387831858237e-07,2.47140814552337e-07,2.46894167032824e-07,2.46647888561968e-07,2.4640197840388e-07,2.46156435824504e-07,2.45911260091611e-07,2.45666450474795e-07,2.45422006245467e-07,2.45177926676849e-07,2.4493421104397e-07,2.44690858623658e-07,2.44447868694538e-07,2.44205240537025e-07,2.43962973433317e-07,2.43721066667394e-07,2.43479519525008e-07,2.43238331293681e-07,2.42997501262697e-07,2.427570287231e-07,2.42516912967687e-07,2.42277153291001e-07,2.4203774898933e-07,2.41798699360699e-07,2.41560003704864e-07,2.4132166132331e-07,2.41083671519243e-07,2.40846033597588e-07,2.4060874686498e-07,2.40371810629761e-07,2.40135224201976e-07,2.39898986893366e-07,2.39663098017364e-07,2.39427556889092e-07,2.3919236282535e-07,2.38957515144618e-07,2.38723013167047e-07,2.38488856214456e-07,2.38255043610324e-07,2.3802157467979e-07,2.37788448749643e-07,2.37555665148322e-07,2.37323223205906e-07,2.37091122254116e-07,2.36859361626301e-07,2.36627940657443e-07,2.36396858684145e-07,2.36166115044629e-07,2.35935709078732e-07,2.35705640127899e-07,2.35475907535182e-07,2.35246510645231e-07,2.35017448804291e-07,2.34788721360199e-07,2.34560327662378e-07,2.34332267061831e-07,2.34104538911139e-07,2.33877142564455e-07,2.33650077377499e-07,2.33423342707555e-07,2.33196937913465e-07,2.32970862355623e-07,2.32745115395976e-07,2.32519696398014e-07,2.32294604726767e-07,2.32069839748802e-07,2.31845400832217e-07,2.31621287346638e-07,2.31397498663211e-07,2.31174034154603e-07,2.30950893194994e-07,2.30728075160074e-07,2.30505579427036e-07,2.30283405374577e-07,2.30061552382886e-07,2.29840019833649e-07,2.29618807110036e-07,2.29397913596703e-07,2.29177338679783e-07,2.28957081746886e-07,2.2873714218709e-07,2.28517519390943e-07,2.28298212750453e-07,2.28079221659086e-07,2.27860545511761e-07,2.2764218370485e-07,2.27424135636167e-07,2.2720640070497e-07,2.26988978311951e-07,2.26771867859237e-07,2.26555068750385e-07,2.26338580390375e-07,2.26122402185609e-07,2.25906533543904e-07,2.25690973874492e-07,2.25475722588012e-07,2.25260779096507e-07,2.25046142813424e-07,2.24831813153601e-07,2.24617789533274e-07,2.24404071370065e-07,2.24190658082979e-07,2.23977549092406e-07,2.23764743820109e-07,2.23552241689226e-07,2.23340042124262e-07,2.2312814455109e-07,2.2291654839694e-07,2.22705253090402e-07,2.2249425806142e-07,2.22283562741286e-07,2.22073166562639e-07,2.21863068959457e-07};
+//
+// The distribution of degrees.
+//
+double P[] = {0.0,0.00943264209782069,0.49551807459988,0.165172691533293,0.0825863457666466,0.049551807459988,0.0330345383066586,0.0235960987904705,0.0176970740928528,0.0137643909611078,0.0110115127688862,0.00900941953817963,0.00750784961514969,0.00635279582820358,0.00544525356703164,0.00471921975809409,0.00412931728833233,0.00364351525441088,0.003238680226143,0.00289776651812795,0.00260798986631516,0.00235960987904705,0.00214509989004277,0.00195856946482166,0.00179535534275319,0.00165172691533293,0.00152467099876886,0.00141173240626746,0.00131089437724836,0.00122048786847261,0.00113912201057444,0.00106563026795673,0.000999028376209435,0.000938481201893711,0.000883276425311728,0.000832803486722487,0.000786536626349015,0.000744021133032852,0.000704862126031123,0.000668715350337219,0.000635279582820358,0.000604290334877902,0.000575514604645621,0.000548746483499313,0.000523803461522071,0.000500523307676646,0.000478761424734183,0.00045838859814975,0.000439289073226844,0.000421358906972687,0.000404504550693779,0.00038864162713716,0.00037369387224727,0.000359592216690769,0.000346273986442963,0.000333682205117764,0.000321764983506415,0.000310474984085138,0.000299768950151167,0.000289607290824009,0.000279953714463209,0.00027077490415294,0.000262040229825425,0.00025372149237065,0.000245792695734067,0.000238229843557634,0.000231010757389221,0.000224114913885065,0.000217523298770799,0.000211218275618022,0.000205183467743221,0.000199403651750455,0.000193864661424053,0.000188553300837093,0.000183457265679333,0.000178565071927885,0.000173865991087677,0.000169349991319166,0.000165007683849444,0.000160830274131736,0.000156809517278443,0.000152937677345642,0.000149207490093309,0.000145612128886241,0.000142145173436569,0.000138800581120414,0.000135572660629242,0.000132456047741213,0.000129445683019822,0.000126536791266568,0.000123724862571755,0.000121005634822925,0.000118375077544166,0.000115829376951819,0.000113364922123056,0.000110978292183624,0.000108666244429798,0.000106425703307534,0.000104253750178809,0.00010214761381156,0.000100104661535329,9.81223910098771e-05,9.61984225587031e-05,9.43304920235826e-05,9.25164441000522e-05,9.07542261171941e-05,8.90418822281904e-05,8.73775479809345e-05,8.57594452405468e-05,8.4185877437968e-05,8.2655225120914e-05,8.11659417854021e-05,7.97165499678056e-05,7.83056375789949e-05,7.69318544635739e-05,7.55939091685552e-05,7.42905659070284e-05,7.30206417034895e-05,7.17830037085151e-05,7.05765666713972e-05,6.94002905602072e-05,6.82531783195426e-05,6.71342737569272e-05,6.60426595494975e-05,6.49774553632153e-05,6.39378160774038e-05,6.29229301079212e-05,6.19320178227571e-05,6.09643300442765e-05,6.00191466327373e-05,5.90957751460799e-05,5.81935495713305e-05,5.73118291232801e-05,5.64499971063886e-05,5.5607459836144e-05,5.47836456163493e-05,5.39780037690501e-05,5.31900037140274e-05,5.24191340949836e-05,5.1664901949732e-05,5.09268319218787e-05,5.02044655116393e-05,4.9497360363588e-05,4.88050895892721e-05,4.81272411227544e-05,4.74634171072682e-05,4.68132333112782e-05,4.61763185723492e-05,4.55523142673175e-05,4.49408738073535e-05,4.43416621565888e-05,4.37543553730578e-05,4.31786401707807e-05,4.26142135018816e-05,4.20607821577013e-05,4.15180623879246e-05,4.09857795367973e-05,4.04636676955642e-05,3.99514693703039e-05,3.94489351643882e-05,3.89558234748333e-05,3.8471900201854e-05,3.79969384709669e-05,3.75307183670287e-05,3.70730266796259e-05,3.66236566592668e-05,3.61824077838539e-05,3.57490855349455e-05,3.5323501183339e-05,3.49054715835362e-05,3.4494818976671e-05,3.40913708015053e-05,3.36949595131157e-05,3.33054224089178e-05,3.29226014616889e-05,3.25463431592696e-05,3.21764983506415e-05,3.18129220980919e-05,3.1455473535192e-05,3.11040157303295e-05,3.07584155555481e-05,3.04185435604592e-05,3.00842738510036e-05,2.97554839728505e-05,2.94320547992326e-05,2.91138704230246e-05,2.88008180528846e-05,2.84927879132816e-05,2.81896731482467e-05,2.78913697286885e-05,2.75977763631233e-05,2.7308794411677e-05,2.70243278032221e-05,2.67442829555203e-05,2.64685686982469e-05,2.61970961987777e-05,2.59297788906269e-05,2.56665324044276e-05,2.54072745013526e-05,2.51519250088767e-05,2.49004057587879e-05,2.46526405273572e-05,2.44085549775814e-05,2.4168076603418e-05,2.39311346759335e-05,2.36976601912903e-05,2.3467585820501e-05,2.32408458608827e-05,2.30173761891434e-05,2.27971142160416e-05,2.25799988425555e-05,2.23659704175075e-05,2.21549706965877e-05,2.1946942802723e-05,2.17418311877443e-05,2.15395815953001e-05,2.13401410249733e-05,2.11434576975542e-05,2.09494810214298e-05,2.07581615600469e-05,2.05694510004101e-05,2.03833021225783e-05,2.01996687701227e-05,2.00185058215117e-05,1.98397691623911e-05,1.96634156587254e-05,1.94894031307721e-05,1.93176903278578e-05,1.91482369039292e-05,1.89810033938512e-05,1.88159511904264e-05,1.8653042522111e-05,1.84922404314032e-05,1.83335087538804e-05,1.81768120978643e-05,1.8022115824691e-05,1.78693860295665e-05,1.77185895229879e-05,1.75696938127107e-05,1.74226670862445e-05,1.72774781938591e-05,1.71340966320844e-05,1.6992492527687e-05,1.68526366221093e-05,1.67145002563543e-05,1.65780553563024e-05,1.64432744184463e-05,1.63101304960297e-05,1.61785971855779e-05,1.60486486138062e-05,1.59202594248957e-05,1.57934047681237e-05,1.5668060285837e-05,1.55442021017592e-05,1.54218068096194e-05,1.53008514620929e-05,1.51813135600453e-05,1.50631710420683e-05,1.49464022743003e-05,1.4830986040522e-05,1.4716901532518e-05,1.46041283406979e-05,1.44926464449674e-05,1.43824362058421e-05,1.42734783557979e-05,1.41657539908485e-05,1.40592445623459e-05,1.39539318689949e-05,1.38497980490771e-05,1.37468255728758e-05,1.36449972352989e-05,1.35442961486915e-05,1.34447057358335e-05,1.33462097231168e-05,1.32487921338969e-05,1.31524372820141e-05,1.30571297654777e-05,1.29628544603118e-05,1.28695965145542e-05,1.27773413424068e-05,1.26860746185325e-05,1.25957822724931e-05,1.25064504833265e-05,1.24180656742571e-05,1.23306145075369e-05,1.22440838794139e-05,1.21584609152222e-05,1.20737329645934e-05,1.19898875967838e-05,1.1906912596114e-05,1.18247959575201e-05,1.17435258822107e-05,1.16630907734284e-05,1.15834792323129e-05,1.15046800538618e-05,1.14266822229881e-05,1.13494749106706e-05,1.12730474701947e-05,1.1197389433482e-05,1.11224905075055e-05,1.10483405707888e-05,1.09749296699863e-05,1.09022480165426e-05,1.08302859834301e-05,1.07590341019602e-05,1.06884830586687e-05,1.06186236922721e-05,1.05494469906938e-05,1.04809440881568e-05,1.04131062623435e-05,1.03459249316187e-05,1.02793916523157e-05,1.02134981160829e-05,1.01482361472901e-05,1.0083597700492e-05,1.00195748579492e-05,9.95615982720272e-06,9.89334493870302e-06,9.83112264349106e-06,9.76948551092998e-06,9.70842622648667e-06,9.64793758956152e-06,9.58801251136548e-06,9.5286440128431e-06,9.46982522264036e-06,9.41154937511642e-06,9.35380980839792e-06,9.29659996247499e-06,9.23991337733795e-06,9.18374369115352e-06,9.12808463847987e-06,9.07293004851926e-06,9.0182738434077e-06,8.96411003654039e-06,8.91043273093236e-06,8.85723611761336e-06,8.80451447405614e-06,8.75226216263741e-06,8.70047362913068e-06,8.6491434012302e-06,8.59826608710532e-06,8.54783637398447e-06,8.49784902676818e-06,8.44829888667041e-06,8.39918086988744e-06,8.35048996629389e-06,8.30222123816503e-06,8.25436981892488e-06,8.20693091191957e-06,8.15989978921516e-06,8.11327179041964e-06,8.06704232152836e-06,8.02120685379241e-06,7.97576092260944e-06,7.93070012643651e-06,7.88602012572419e-06,7.84171664187181e-06,7.79778545620306e-06,7.7542224089617e-06,7.71102339832682e-06,7.66818437944722e-06,7.62570136349461e-06,7.58357041673497e-06,7.54178765961797e-06,7.50034926588381e-06,7.45925146168718e-06,7.41849052473807e-06,7.37806278345885e-06,7.33796461615744e-06,7.29819245021621e-06,7.25874276129612e-06,7.21961207255598e-06,7.18079695388632e-06,7.14229402115771e-06,7.10409993548307e-06,7.06621140249383e-06,7.0286251716295e-06,6.99133803544048e-06,6.95434682890376e-06,6.91764842875123e-06,6.88123975281044e-06,6.84511775935736e-06,6.80927944648115e-06,6.77372185146036e-06,6.73844205015067e-06,6.70343715638365e-06,6.66870432137648e-06,6.63424073315232e-06,6.60004361597112e-06,6.56611022977075e-06,6.53243786961808e-06,6.49902386516991e-06,6.46586558014353e-06,6.43296041179674e-06,6.40030579041707e-06,6.36789917882002e-06,6.33573807185628e-06,6.30381999592753e-06,6.27214250851081e-06,6.24070319769121e-06,6.20949968170275e-06,6.1785296084773e-06,6.1477906552013e-06,6.1172805278802e-06,6.08699696091049e-06,6.05693771665908e-06,6.02710058504993e-06,5.99748338315779e-06,5.96808395480898e-06,5.93890017018888e-06,5.90992992545625e-06,5.88117114236401e-06,5.85262176788651e-06,5.82427977385317e-06,5.79614315658817e-06,5.76820993655642e-06,5.74047815801529e-06,5.71294588867229e-06,5.6856112193485e-06,5.65847226364755e-06,5.63152715763018e-06,5.60477405949417e-06,5.5782111492596e-06,5.55183662845932e-06,5.52564871983451e-06,5.49964566703529e-06,5.4738257343262e-06,5.44818720629657e-06,5.42272838757556e-06,5.3974476025519e-06,5.37234319509817e-06,5.34741352829957e-06,5.32265698418707e-06,5.29807196347489e-06,5.2736568853022e-06,5.24941018697897e-06,5.22533032373594e-06,5.20141576847857e-06,5.17766501154488e-06,5.15407656046723e-06,5.13064893973783e-06,5.10738069057802e-06,5.08427037071115e-06,5.06131655413909e-06,5.03851783092225e-06,5.01587280696305e-06,4.99338010379281e-06,4.97103835836197e-06,4.94884622283357e-06,4.92680236437997e-06,4.90490546498272e-06,4.88315422123557e-06,4.86154734415046e-06,4.84008355896657e-06,4.81876160496231e-06,4.79758023527017e-06,4.77653821669442e-06,4.75563432953165e-06,4.73486736739396e-06,4.71423613703494e-06,4.69373945817827e-06,4.67337616334886e-06,4.65314509770666e-06,4.63304511888287e-06,4.61307509681872e-06,4.5932339136066e-06,4.57352046333361e-06,4.55393365192747e-06,4.5344723970047e-06,4.5151356277211e-06,4.49592228462441e-06,4.47683131950923e-06,4.45786169527403e-06,4.43901238578027e-06,4.42028237571368e-06,4.40167066044752e-06,4.38317624590782e-06,4.36479814844071e-06,4.34653539468154e-06,4.32838702142608e-06,4.31035207550348e-06,4.29242961365107e-06,4.27461870239111e-06,4.25691841790916e-06,4.23932784593433e-06,4.22184608162119e-06,4.20447222943345e-06,4.18720540302921e-06,4.17004472514794e-06,4.15298932749907e-06,4.13603835065214e-06,4.11919094392851e-06,4.10244626529465e-06,4.08580348125694e-06,4.06926176675793e-06,4.05282030507406e-06,4.03647828771489e-06,4.02023491432368e-06,4.00408939257941e-06,3.98804093810013e-06,3.97208877434773e-06,3.95623213253397e-06,3.94047025152786e-06,3.92480237776433e-06,3.90922776515415e-06,3.89374567499512e-06,3.87835537588447e-06,3.86305614363246e-06,3.84784726117722e-06,3.83272801850069e-06,3.81769771254578e-06,3.80275564713464e-06,3.78790113288802e-06,3.77313348714577e-06,3.75845203388839e-06,3.7438561036597e-06,3.72934503349048e-06,3.7149181668232e-06,3.70057485343778e-06,3.68631444937829e-06,3.67213631688068e-06,3.65803982430149e-06,3.64402434604746e-06,3.63008926250617e-06,3.61623395997752e-06,3.60245783060618e-06,3.5887602723149e-06,3.57514068873875e-06,3.56159848916019e-06,3.54813308844503e-06,3.5347439069792e-06,3.5214303706064e-06,3.50819191056653e-06,3.49502796343494e-06,3.48193797106253e-06,3.4689213805165e-06,3.45597764402204e-06,3.44310621890464e-06,3.43030656753324e-06,3.4175781572641e-06,3.40492046038535e-06,3.3923329540623e-06,3.37981512028347e-06,3.36736644580729e-06,3.35498642210947e-06,3.34267454533108e-06,3.33043031622731e-06,3.31825324011678e-06,3.30614282683169e-06,3.29409859066837e-06,3.28212005033866e-06,3.27020672892183e-06,3.25835815381704e-06,3.24657385669654e-06,3.23485337345937e-06,3.22319624418564e-06,3.21160201309145e-06,3.2000702284843e-06,3.18860044271912e-06,3.17719221215483e-06,3.16584509711142e-06,3.1545586618276e-06,3.14333247441896e-06,3.13216610683666e-06,3.1210591348266e-06,3.11001113788916e-06,3.09902169923937e-06,3.08809040576763e-06,3.07721684800084e-06,3.06640062006411e-06,3.05564131964283e-06,3.04493854794531e-06,3.03429190966578e-06,3.02370101294792e-06,3.0131654693488e-06,3.00268489380324e-06,2.99225890458865e-06,2.98188712329024e-06,2.97156917476675e-06,2.96130468711643e-06,2.95109329164362e-06,2.94093462282557e-06,2.93082831827977e-06,2.92077401873164e-06,2.91077136798256e-06,2.90082001287835e-06,2.89091960327808e-06,2.8810697920233e-06,2.87127023490758e-06,2.86152059064643e-06,2.85182052084763e-06,2.84216968998182e-06,2.8325677653535e-06,2.82301441707237e-06,2.81350931802499e-06,2.80405214384676e-06,2.79464257289425e-06,2.78528028621789e-06,2.77596496753489e-06,2.76669630320255e-06,2.75747398219187e-06,2.74829769606145e-06,2.73916713893168e-06,2.73008200745927e-06,2.72104200081205e-06,2.71204682064408e-06,2.703096171071e-06,2.69418975864572e-06,2.68532729233439e-06,2.67650848349257e-06,2.66773304584177e-06,2.65900069544622e-06,2.65031115068986e-06,2.64166413225367e-06,2.63305936309324e-06,2.62449656841651e-06,2.61597547566191e-06,2.60749581447662e-06,2.59905731669515e-06,2.5906597163181e-06,2.58230274949127e-06,2.57398615448486e-06,2.56570967167301e-06,2.55747304351354e-06,2.54927601452792e-06,2.54111833128143e-06,2.5329997423636e-06,2.52491999836882e-06,2.5168788518772e-06,2.50887605743562e-06,2.500911371539e-06,2.49298455261178e-06,2.48509536098959e-06,2.47724355890115e-06,2.46942891045036e-06,2.46165118159855e-06,2.45391014014698e-06,2.44620555571952e-06,2.43853719974547e-06,2.43090484544267e-06,2.42330826780066e-06,2.41574724356416e-06,2.4082215512166e-06,2.40073097096399e-06,2.39327528471876e-06,2.38585427608397e-06,2.37846773033758e-06,2.37111543441691e-06,2.36379717690327e-06,2.35651274800681e-06,2.3492619395514e-06,2.34204454495985e-06,2.33486035923911e-06,2.32770917896579e-06,2.32059080227171e-06,2.31350502882965e-06,2.30645165983932e-06,2.29943049801333e-06,2.29244134756344e-06,2.28548401418692e-06,2.27855830505302e-06,2.27166402878962e-06,2.26480099547001e-06,2.25796901659982e-06,2.25116790510403e-06,2.24439747531425e-06,2.23765754295595e-06,2.23094792513599e-06,2.22426844033019e-06,2.21761890837106e-06,2.21099915043562e-06,2.20440898903343e-06,2.19784824799464e-06,2.19131675245825e-06,2.18481432886045e-06,2.17834080492309e-06,2.17189600964225e-06,2.16547977327699e-06,2.15909192733812e-06,2.15273230457718e-06,2.14640073897548e-06,2.14009706573326e-06,2.13382112125897e-06,2.12757274315865e-06,2.12135177022544e-06,2.11515804242916e-06,2.10899140090604e-06,2.10285168794853e-06,2.09673874699519e-06,2.09065242262075e-06,2.0845925605262e-06,2.07855900752902e-06,2.0725516115535e-06,2.06657022162116e-06,2.06061468784128e-06,2.05468486140145e-06,2.04878059455834e-06,2.04290174062847e-06,2.03704815397911e-06,2.03121969001922e-06,2.0254162051906e-06,2.01963755695895e-06,2.01388360380523e-06,2.00815420521688e-06,2.00244922167933e-06,1.99676851466747e-06,1.99111194663725e-06,1.98547938101734e-06,1.97987068220091e-06,1.97428571553744e-06,1.96872434732466e-06,1.96318644480054e-06,1.95767187613537e-06,1.95218051042391e-06,1.94671221767762e-06,1.94126686881699e-06,1.93584433566387e-06,1.93044449093398e-06,1.92506720822943e-06,1.91971236203129e-06,1.91437982769232e-06,1.90906948142965e-06,1.90378120031766e-06,1.89851486228082e-06,1.89327034608667e-06,1.88804753133884e-06,1.88284629847014e-06,1.8776665287357e-06,1.8725081042062e-06,1.86737090776119e-06,1.8622548230824e-06,1.85715973464715e-06,1.85208552772189e-06,1.84703208835566e-06,1.84199930337376e-06,1.83698706037139e-06,1.83199524770733e-06,1.82702375449782e-06,1.82207247061029e-06,1.81714128665735e-06,1.81223009399071e-06,1.80733878469519e-06,1.8024672515828e-06,1.79761538818689e-06,1.79278308875628e-06,1.78797024824955e-06,1.78317676232931e-06,1.77840252735654e-06,1.773647440385e-06,1.76891139915566e-06,1.76419430209125e-06,1.75949604829074e-06,1.75481653752401e-06,1.75015567022647e-06,1.74551334749377e-06,1.74088947107657e-06,1.73628394337531e-06,1.73169666743508e-06,1.72712754694053e-06,1.72257648621078e-06,1.71804339019444e-06,1.71352816446462e-06,1.70903071521406e-06,1.7045509492502e-06,1.70008877399038e-06,1.69564409745707e-06,1.69121682827311e-06,1.68680687565701e-06,1.68241414941832e-06,1.67803855995299e-06,1.67368001823883e-06,1.66933843583095e-06,1.66501372485729e-06,1.6607057980142e-06,1.65641456856196e-06,1.65213995032051e-06,1.64788185766505e-06,1.64364020552176e-06,1.63941490936361e-06,1.63520588520607e-06,1.63101304960297e-06,1.6268363196424e-06,1.62267561294255e-06,1.61853084764768e-06,1.61440194242409e-06,1.61028881645613e-06,1.60619138944224e-06,1.60210958159106e-06,1.59804331361748e-06,1.59399250673885e-06,1.58995708267116e-06,1.58593696362521e-06,1.58193207230293e-06,1.57794233189359e-06,1.57396766607018e-06,1.57000799898572e-06,1.56606325526968e-06,1.56213336002434e-06,1.55821823882127e-06,1.55431781769781e-06,1.55043202315357e-06,1.54656078214694e-06,1.54270402209171e-06,1.53886167085362e-06,1.53503365674702e-06,1.5312199085315e-06,1.5274203554086e-06,1.52363492701849e-06,1.51986355343676e-06,1.51610616517115e-06,1.51236269315839e-06,1.50863306876096e-06,1.50491722376401e-06,1.50121509037221e-06,1.49752660120668e-06,1.49385168930188e-06,1.49019028810261e-06,1.48654233146099e-06,1.48290775363345e-06,1.47928648927782e-06,1.47567847345031e-06,1.47208364160268e-06,1.46850192957932e-06,1.46493327361436e-06,1.46137761032889e-06,1.4578348767281e-06,1.45430501019849e-06,1.45078794850514e-06,1.44728362978895e-06,1.44379199256388e-06,1.44031297571433e-06,1.43684651849239e-06,1.43339256051525e-06,1.42995104176251e-06,1.42652190257363e-06,1.42310508364531e-06,1.41970052602894e-06,1.41630817112803e-06,1.41292796069574e-06,1.40955983683235e-06,1.40620374198274e-06,1.40285961893403e-06,1.39952741081305e-06,1.39620706108396e-06,1.39289851354584e-06,1.38960171233035e-06,1.38631660189931e-06,1.3830431270424e-06,1.37978123287485e-06,1.3765308648351e-06,1.37329196868255e-06,1.37006449049528e-06,1.36684837666782e-06,1.36364357390893e-06,1.36045002923936e-06,1.35726768998967e-06,1.35409650379811e-06,1.35093641860838e-06,1.34778738266757e-06,1.34464934452399e-06,1.3415222530251e-06,1.3384060573154e-06,1.33530070683439e-06,1.33220615131449e-06,1.32912234077904e-06,1.32604922554025e-06,1.3229867561972e-06,1.31993488363388e-06,1.31689355901721e-06,1.31386273379508e-06,1.3108423596944e-06,1.30783238871921e-06,1.30483277314876e-06,1.30184346553559e-06,1.2988644187037e-06,1.29589558574666e-06,1.29293692002578e-06,1.28998837516825e-06,1.28704990506536e-06,1.28412146387067e-06,1.28120300599824e-06,1.27829448612083e-06,1.27539585916818e-06,1.27250708032521e-06,1.26962810503036e-06,1.2667588889738e-06,1.26389938809575e-06,1.26104955858482e-06,1.2582093568763e-06,1.25537873965048e-06,1.25255766383104e-06,1.24974608658339e-06,1.24694396531302e-06,1.24415125766394e-06,1.24136792151704e-06,1.23859391498851e-06,1.23582919642827e-06,1.2330737244184e-06,1.23032745777159e-06,1.2275903555296e-06,1.22486237696176e-06,1.2221434815634e-06,1.21943362905439e-06,1.21673277937763e-06,1.21404089269759e-06,1.21135792939882e-06,1.20868385008447e-06,1.20601861557491e-06,1.20336218690624e-06,1.20071452532889e-06,1.19807559230619e-06,1.19544534951298e-06,1.19282375883423e-06,1.19021078236362e-06,1.18760638240221e-06,1.18501052145707e-06,1.18242316223991e-06,1.17984426766578e-06,1.17727380085169e-06,1.17471172511534e-06,1.17215800397379e-06,1.16961260114214e-06,1.16707548053229e-06,1.16454660625161e-06,1.16202594260172e-06,1.15951345407717e-06,1.15700910536426e-06,1.15451286133974e-06,1.15202468706962e-06,1.14954454780789e-06,1.1470724089954e-06,1.14460823625857e-06,1.14215199540823e-06,1.13970365243844e-06,1.13726317352529e-06,1.13483052502578e-06,1.13240567347657e-06,1.12998858559295e-06,1.1275792282676e-06,1.12517756856947e-06,1.12278357374273e-06,1.12039721120555e-06,1.11801844854906e-06,1.11564725353624e-06,1.11328359410078e-06,1.11092743834607e-06,1.10857875454407e-06,1.10623751113426e-06,1.10390367672258e-06,1.10157722008039e-06,1.09925811014337e-06,1.09694631601058e-06,1.09464180694333e-06,1.09234455236423e-06,1.09005452185613e-06,1.08777168516114e-06,1.08549601217963e-06,1.08322747296922e-06,1.08096603774382e-06,1.07871167687261e-06,1.07646436087913e-06,1.07422406044025e-06,1.07199074638528e-06,1.06976438969497e-06,1.06754496150058e-06,1.06533243308297e-06,1.06312677587161e-06,1.06092796144375e-06,1.05873596152341e-06,1.05655074798054e-06,1.05437229283006e-06,1.05220056823103e-06,1.0500355464857e-06,1.04787720003866e-06,1.04572550147595e-06,1.0435804235242e-06,1.04144193904977e-06,1.03931002105785e-06,1.03718464269168e-06,1.03506577723164e-06,1.03295339809443e-06,1.03084747883226e-06,1.02874799313199e-06,1.02665491481433e-06,1.024568217833e-06,1.02248787627395e-06,1.02041386435453e-06,1.0183461564227e-06,1.01628472695626e-06,1.01422955056201e-06,1.01218060197502e-06,1.01013785605781e-06,1.00810128779963e-06,1.00607087231564e-06,1.0040465848462e-06,1.00202840075605e-06,1.00001629553365e-06,9.98010244790354e-07,9.96010224259712e-07,9.9401620979673e-07,9.92028177377136e-07,9.90046103096662e-07,9.88069963170322e-07,9.86099733931697e-07,9.84135391832232e-07,9.82176913440526e-07,9.80224275441638e-07,9.78277454636391e-07,9.76336427940684e-07,9.74401172384806e-07,9.72471665112757e-07,9.70547883381574e-07,9.68629804560662e-07,9.66717406131125e-07,9.64810665685107e-07,9.62909560925136e-07,9.61014069663472e-07,9.5912416982146e-07,9.57239839428883e-07,9.55361056623331e-07,9.5348779964956e-07,9.51620046858865e-07,9.49757776708456e-07,9.47900967760835e-07,9.46049598683177e-07,9.44203648246722e-07,9.42363095326163e-07,9.40527918899043e-07,9.38698098045154e-07,9.36873611945941e-07,9.35054439883909e-07,9.3324056124204e-07,9.31431955503199e-07,9.29628602249562e-07,9.27830481162039e-07,9.26037572019697e-07,9.24249854699195e-07,9.22467309174221e-07,9.20689915514926e-07,9.18917653887371e-07,9.17150504552972e-07,9.15388447867951e-07,9.13631464282792e-07,9.11879534341694e-07,9.10132638682036e-07,9.0839075803384e-07,9.06653873219244e-07,9.04921965151968e-07,9.03195014836792e-07,9.01473003369039e-07,8.9975591193405e-07,8.98043721806678e-07,8.96336414350771e-07,8.94633971018671e-07,8.92936373350704e-07,8.91243602974684e-07,8.89555641605414e-07,8.87872471044192e-07,8.86194073178324e-07,8.84520429980632e-07,8.8285152350897e-07,8.81187335905748e-07,8.79527849397451e-07,8.77873046294164e-07,8.76222908989099e-07,8.74577419958134e-07,8.72936561759338e-07,8.71300317032517e-07,8.69668668498748e-07,8.68041598959929e-07,8.66419091298322e-07,8.64801128476103e-07,8.63187693534916e-07,8.61578769595428e-07,8.59974339856889e-07,8.58374387596691e-07,8.56778896169931e-07,8.55187849008984e-07,8.53601229623068e-07,8.52019021597816e-07,8.50441208594857e-07,8.48867774351389e-07,8.4729870267976e-07,8.45733977467054e-07,8.4417358267468e-07,8.42617502337952e-07,8.41065720565691e-07,8.39518221539811e-07,8.37974989514922e-07,8.36436008817925e-07,8.34901263847616e-07,8.33370739074294e-07,8.31844419039359e-07,8.30322288354932e-07,8.2880433170346e-07,8.27290533837335e-07,8.25780879578508e-07,8.2427535381811e-07,8.22773941516073e-07,8.21276627700757e-07,8.19783397468574e-07,8.18294235983618e-07,8.16809128477295e-07,8.15328060247962e-07,8.13851016660556e-07,8.12377983146238e-07,8.10908945202032e-07,8.09443888390465e-07,8.07982798339219e-07,8.06525660740771e-07,8.05072461352049e-07,8.0362318599408e-07,8.02177820551645e-07,8.00736350972935e-07,7.99298763269214e-07,7.97865043514471e-07,7.9643517784509e-07,7.95009152459512e-07,7.93586953617903e-07,7.92168567641821e-07,7.90753980913889e-07,7.89343179877468e-07,7.87936151036332e-07,7.86532880954344e-07,7.85133356255137e-07,7.83737563621794e-07,7.82345489796534e-07,7.80957121580391e-07,7.79572445832908e-07,7.78191449471822e-07,7.76814119472757e-07,7.75440442868915e-07,7.74070406750772e-07,7.72703998265775e-07,7.7134120461804e-07,7.69982013068052e-07,7.68626410932369e-07,7.67274385583323e-07,7.6592592444873e-07,7.64581015011595e-07,7.6323964480982e-07,7.6190180143592e-07,7.60567472536733e-07,7.59236645813134e-07,7.57909309019755e-07,7.56585449964698e-07,7.55265056509263e-07,7.5394811656766e-07,7.5263461810674e-07,7.51324549145719e-07,7.500178977559e-07,7.48714652060408e-07,7.47414800233914e-07,7.46118330502372e-07,7.4482523114275e-07,7.43535490482762e-07,7.42249096900612e-07,7.40966038824725e-07,7.39686304733491e-07,7.38409883155003e-07,7.37136762666805e-07,7.3586693189563e-07,7.34600379517153e-07,7.3333709425573e-07,7.32077064884157e-07,7.30820280223411e-07,7.29566729142411e-07,7.28316400557762e-07,7.27069283433519e-07,7.25825366780938e-07,7.24584639658236e-07,7.23347091170348e-07,7.22112710468693e-07,7.20881486750928e-07,7.19653409260722e-07,7.18428467287513e-07,7.17206650166275e-07,7.15987947277293e-07,7.14772348045922e-07,7.13559841942367e-07,7.12350418481447e-07,7.11144067222376e-07,7.09940777768531e-07,7.08740539767232e-07,7.07543342909517e-07,7.06349176929923e-07,7.05158031606264e-07,7.03969896759412e-07,7.02784762253083e-07,7.01602617993616e-07,7.00423453929762e-07,6.99247260052466e-07,6.98074026394659e-07,6.96903743031047e-07,6.95736400077897e-07,6.94571987692829e-07,6.93410496074614e-07,6.9225191546296e-07,6.91096236138314e-07,6.89943448421653e-07,6.88793542674283e-07,6.8764650929764e-07,6.86502338733085e-07,6.85361021461708e-07,6.84222548004131e-07,6.83086908920307e-07,6.81954094809328e-07,6.80824096309229e-07,6.79696904096797e-07,6.78572508887373e-07,6.77450901434666e-07,6.76332072530563e-07,6.75216013004935e-07,6.74102713725454e-07,6.72992165597406e-07,6.71884359563501e-07,6.70779286603692e-07,6.69676937734993e-07,6.6857730401129e-07,6.67480376523166e-07,6.66386146397719e-07,6.65294604798377e-07,6.6420574292473e-07,6.63119552012343e-07,6.62036023332585e-07,6.6095514819245e-07,6.59876917934387e-07,6.58801323936124e-07,6.57728357610495e-07,6.56658010405271e-07,6.55590273802985e-07,6.54525139320771e-07,6.53462598510185e-07,6.52402642957046e-07,6.51345264281265e-07,6.5029045413668e-07,6.49238204210893e-07,6.48188506225103e-07,6.47141351933948e-07,6.46096733125338e-07,6.45054641620297e-07,6.44015069272802e-07,6.42978007969625e-07,6.41943449630173e-07,6.4091138620633e-07,6.39881809682304e-07,6.38854712074468e-07,6.37830085431205e-07,6.36807921832757e-07,6.35788213391071e-07,6.34770952249646e-07,6.33756130583379e-07,6.32743740598422e-07,6.31733774532024e-07,6.30726224652387e-07,6.29721083258519e-07,6.28718342680082e-07,6.27717995277249e-07,6.26720033440561e-07,6.25724449590774e-07,6.24731236178725e-07,6.23740385685183e-07,6.22751890620705e-07,6.21765743525502e-07,6.20781936969291e-07,6.19800463551158e-07,6.18821315899418e-07,6.17844486671479e-07,6.16869968553701e-07,6.1589775426126e-07,6.14927836538014e-07,6.13960208156365e-07,6.12994861917125e-07,6.12031790649384e-07,6.11070987210374e-07,6.10112444485338e-07,6.09156155387399e-07,6.08202112857426e-07,6.07250309863909e-07,6.06300739402824e-07,6.05353394497507e-07,6.04408268198526e-07,6.03465353583552e-07,6.02524643757233e-07,6.01586131851069e-07,6.00649811023285e-07,5.99715674458708e-07,5.9878371536864e-07,5.97853926990738e-07,5.96926302588891e-07,5.96000835453094e-07,5.95077518899332e-07,5.94156346269457e-07,5.93237310931067e-07,5.92320406277387e-07,5.91405625727151e-07,5.90492962724486e-07,5.89582410738789e-07,5.88673963264615e-07,5.8776761382156e-07,5.86863355954142e-07,5.85961183231691e-07,5.85061089248232e-07,5.84163067622372e-07,5.83267111997184e-07,5.823732160401e-07,5.81481373442795e-07,5.80591577921077e-07,5.79703823214776e-07,5.78818103087633e-07,5.77934411327194e-07,5.77052741744696e-07,5.76173088174964e-07,5.75295444476297e-07,5.74419804530366e-07,5.73546162242107e-07,5.72674511539611e-07,5.71804846374023e-07,5.70937160719435e-07,5.70071448572779e-07,5.69207703953729e-07,5.68345920904594e-07,5.67486093490215e-07,5.66628215797864e-07,5.65772281937142e-07,5.64918286039879e-07,5.6406622226003e-07,5.63216084773579e-07,5.62367867778438e-07,5.61521565494347e-07,5.60677172162777e-07,5.5983468204683e-07,5.58994089431144e-07,5.58155388621795e-07,5.573185739462e-07,5.56483639753022e-07,5.55650580412074e-07,5.54819390314225e-07,5.53990063871304e-07,5.53162595516007e-07,5.52336979701804e-07,5.51513210902845e-07,5.5069128361387e-07,5.49871192350111e-07,5.49052931647209e-07,5.48236496061117e-07,5.47421880168009e-07,5.46609078564196e-07,5.4579808586603e-07,5.44988896709816e-07,5.44181505751728e-07,5.43375907667713e-07,5.42572097153412e-07,5.41770068924065e-07,5.40969817714428e-07,5.40171338278687e-07,5.39374625390371e-07,5.38579673842264e-07,5.37786478446325e-07,5.36995034033601e-07,5.3620533545414e-07,5.35417377576911e-07,5.3463115528972e-07,5.33846663499126e-07,5.33063897130359e-07,5.32282851127238e-07,5.31503520452088e-07,5.30725900085662e-07,5.29949985027058e-07,5.29175770293636e-07,5.28403250920945e-07,5.27632421962635e-07,5.26863278490387e-07,5.26095815593824e-07,5.25330028380441e-07,5.24565911975524e-07,5.23803461522071e-07,5.23042672180718e-07,5.22283539129657e-07,5.21526057564567e-07,5.20770222698531e-07,5.20016029761966e-07,5.19263474002542e-07,5.18512550685112e-07,5.17763255091637e-07,5.17015582521107e-07,5.16269528289475e-07,5.15525087729577e-07,5.14782256191062e-07,5.14041029040318e-07,5.13301401660404e-07,5.12563369450972e-07,5.11826927828197e-07,5.11092072224711e-07,5.10358798089525e-07,5.09627100887963e-07,5.0889697610159e-07,5.08168419228145e-07,5.07441425781467e-07,5.06715991291429e-07,5.0599211130387e-07,5.05269781380524e-07,5.04548997098954e-07,5.03829754052483e-07,5.03112047850129e-07,5.02395874116535e-07,5.01681228491903e-07,5.00968106631928e-07,5.00256504207735e-07,4.99546416905808e-07,4.98837840427927e-07,4.98130770491105e-07,4.9742520282752e-07,4.96721133184452e-07,4.9601855732422e-07,4.95317471024115e-07,4.94617870076341e-07,4.93919750287948e-07,4.93223107480772e-07,4.92527937491369e-07,4.91834236170959e-07,4.91141999385356e-07,4.90451223014913e-07,4.89761902954456e-07,4.89074035113228e-07,4.88387615414823e-07,4.87702639797131e-07,4.87019104212271e-07,4.8633700462654e-07,4.85656337020345e-07,4.84977097388148e-07,4.84299281738409e-07,4.83622886093523e-07,4.82947906489764e-07,4.82274338977226e-07,4.81602179619766e-07,4.80931424494948e-07,4.80262069693981e-07,4.79594111321666e-07,4.78927545496341e-07,4.78262368349818e-07,4.77598576027334e-07,4.7693616468749e-07,4.76275130502199e-07,4.75615469656628e-07,4.74957178349145e-07,4.74300252791263e-07,4.73644689207584e-07,4.72990483835751e-07,4.72337632926384e-07,4.71686132743038e-07,4.71035979562137e-07,4.70387169672933e-07,4.69739699377444e-07,4.69093564990405e-07,4.68448762839215e-07,4.67805289263887e-07,4.67163140616991e-07,4.66522313263607e-07,4.65882803581271e-07,4.65244607959927e-07,4.64607722801871e-07,4.63972144521704e-07,4.63337869546282e-07,4.62704894314661e-07,4.62073215278054e-07,4.61442828899776e-07,4.60813731655195e-07,4.60185920031687e-07,4.5955939052858e-07,4.58934139657113e-07,4.5831016394038e-07,4.57687459913287e-07,4.57066024122502e-07,4.56445853126406e-07,4.55826943495048e-07,4.55209291810096e-07,4.54592894664787e-07,4.53977748663888e-07,4.53363850423639e-07,4.52751196571715e-07,4.52139783747176e-07,4.51529608600418e-07,4.50920667793135e-07,4.50312957998266e-07,4.49706475899951e-07,4.49101218193491e-07,4.48497181585296e-07,4.47894362792842e-07,4.47292758544632e-07,4.46692365580142e-07,4.46093180649786e-07,4.45495200514867e-07,4.44898421947533e-07,4.44302841730736e-07,4.43708456658186e-07,4.43115263534312e-07,4.42523259174213e-07,4.41932440403619e-07,4.41342804058852e-07,4.40754346986773e-07,4.40167066044752e-07,4.39580958100618e-07,4.3899602003262e-07,4.38412248729385e-07,4.37829641089877e-07,4.37248194023357e-07,4.36667904449338e-07,4.36088769297548e-07,4.35510785507889e-07,4.34933950030396e-07,4.34358259825193e-07,4.33783711862462e-07,4.33210303122392e-07,4.3263803059515e-07,4.32066891280833e-07,4.31496882189433e-07,4.30928000340799e-07,4.30360242764592e-07,4.29793606500254e-07,4.29228088596964e-07,4.28663686113602e-07,4.28100396118709e-07,4.27538215690451e-07,4.26977141916579e-07,4.26417171894393e-07,4.25858302730705e-07,4.25300531541797e-07,4.24743855453392e-07,4.24188271600608e-07,4.23633777127927e-07,4.23080369189158e-07,4.22528044947397e-07,4.21976801574993e-07,4.21426636253513e-07,4.20877546173704e-07,4.20329528535457e-07,4.19782580547773e-07,4.19236699428725e-07,4.18691882405426e-07,4.1814812671399e-07,4.17605429599501e-07,4.17063788315973e-07,4.16523200126322e-07,4.15983662302324e-07,4.15445172124587e-07,4.14907726882511e-07,4.1437132387426e-07,4.13835960406722e-07,4.1330163379548e-07,4.12768341364776e-07,4.12236080447478e-07,4.11704848385046e-07,4.11174642527499e-07,4.10645460233384e-07,4.10117298869739e-07,4.09590155812066e-07,4.09064028444292e-07,4.08538914158741e-07,4.080148103561e-07,4.07491714445387e-07,4.0696962384392e-07,4.06448535977282e-07,4.05928448279294e-07,4.05409358191981e-07,4.04891263165537e-07,4.04374160658302e-07,4.03858048136721e-07,4.03342923075322e-07,4.02828782956679e-07,4.02315625271384e-07,4.01803447518015e-07,4.01292247203107e-07,4.00782021841119e-07,4.00272768954409e-07,3.99764486073197e-07,3.99257170735541e-07,3.98750820487303e-07,3.98245432882123e-07,3.97741005481385e-07,3.97237535854194e-07,3.96735021577338e-07,3.96233460235268e-07,3.95732849420063e-07,3.95233186731401e-07,3.94734469776535e-07,3.94236696170259e-07,3.93739863534884e-07,3.93243969500205e-07,3.92749011703477e-07,3.92254987789385e-07,3.91761895410014e-07,3.91269732224826e-07,3.90778495900626e-07,3.90288184111542e-07,3.89798794538988e-07,3.89310324871646e-07,3.88822772805432e-07,3.88336136043473e-07,3.87850412296076e-07,3.87365599280706e-07,3.86881694721955e-07,3.86398696351515e-07,3.85916601908157e-07,3.85435409137698e-07,3.84955115792978e-07,3.84475719633834e-07,3.83997218427071e-07,3.8351960994644e-07,3.8304289197261e-07,3.82567062293141e-07,3.82092118702461e-07,3.81618059001837e-07,3.81144880999355e-07,3.80672582509889e-07,3.80201161355078e-07,3.79730615363302e-07,3.79260942369655e-07,3.78792140215922e-07,3.78324206750554e-07,3.7785713982864e-07,3.77390937311886e-07,3.76925597068592e-07,3.76461116973621e-07,3.75997494908383e-07,3.75534728760803e-07,3.75072816425304e-07,3.74611755802777e-07,3.74151544800563e-07,3.73692181332422e-07,3.73233663318517e-07,3.72775988685386e-07,3.72319155365919e-07,3.71863161299334e-07,3.71408004431159e-07,3.709536827132e-07,3.70500194103527e-07,3.70047536566442e-07,3.69595708072466e-07,3.69144706598308e-07,3.68694530126847e-07,3.68245176647107e-07,3.67796644154236e-07,3.67348930649483e-07,3.66902034140177e-07,3.66455952639703e-07,3.66010684167479e-07,3.6556622674894e-07,3.65122578415507e-07,3.64679737204572e-07,3.64237701159476e-07,3.63796468329482e-07,3.63356036769761e-07,3.62916404541365e-07,3.62477569711206e-07,3.62039530352038e-07,3.61602284542434e-07,3.61165830366765e-07,3.60730165915176e-07,3.60295289283573e-07,3.59861198573592e-07,3.59427891892589e-07,3.58995367353608e-07,3.58563623075372e-07,3.58132657182253e-07,3.57702467804256e-07,3.57273053077e-07,3.56844411141695e-07,3.56416540145122e-07,3.55989438239615e-07,3.55563103583041e-07,3.55137534338776e-07,3.54712728675692e-07,3.5428868476813e-07,3.53865400795886e-07,3.53442874944189e-07,3.53021105403683e-07,3.52600090370405e-07,3.52179828045768e-07,3.51760316636541e-07,3.51341554354831e-07,3.50923539418062e-07,3.50506270048956e-07,3.50089744475517e-07,3.49673960931009e-07,3.49258917653939e-07,3.48844612888039e-07,3.48431044882244e-07,3.48018211890678e-07,3.47606112172631e-07,3.47194743992545e-07,3.46784105619993e-07,3.46374195329662e-07,3.45965011401334e-07,3.45556552119868e-07,3.45148815775184e-07,3.44741800662242e-07,3.44335505081025e-07,3.43929927336524e-07,3.43525065738718e-07,3.43120918602555e-07,3.42717484247937e-07,3.42314760999702e-07,3.41912747187606e-07,3.41511441146306e-07,3.41110841215343e-07,3.40710945739123e-07,3.40311753066904e-07,3.39913261552774e-07,3.39515469555638e-07,3.39118375439198e-07,3.3872197757194e-07,3.38326274327113e-07,3.37931264082715e-07,3.37536945221475e-07,3.37143316130838e-07,3.36750375202946e-07,3.36358120834626e-07,3.35966551427368e-07,3.35575665387313e-07,3.35185461125235e-07,3.34795937056524e-07,3.34407091601174e-07,3.34018923183761e-07,3.33631430233432e-07,3.33244611183886e-07,3.3285846447336e-07,3.32472988544613e-07,3.32088181844908e-07,3.31704042826002e-07,3.31320569944122e-07,3.30937761659958e-07,3.30555616438641e-07,3.30174132749734e-07,3.29793309067208e-07,3.29413143869436e-07,3.29033635639172e-07,3.28654782863536e-07,3.28276584034004e-07,3.27899037646386e-07,3.27522142200815e-07,3.27145896201733e-07,3.26770298157874e-07,3.26395346582248e-07,3.26021039992131e-07,3.25647376909045e-07,3.25274355858748e-07,3.24901975371217e-07,3.24530233980632e-07,3.24159130225366e-07,3.23788662647965e-07,3.2341882979514e-07,3.23049630217749e-07,3.2268106247078e-07,3.22313125113345e-07,3.21945816708658e-07,3.21579135824024e-07,3.21213081030826e-07,3.20847650904511e-07,3.20482844024574e-07,3.20118658974546e-07,3.1975509434198e-07,3.19392148718436e-07,3.1902982069947e-07,3.18668108884618e-07,3.18307011877384e-07,3.17946528285224e-07,3.17586656719536e-07,3.17227395795645e-07,3.16868744132789e-07,3.16510700354108e-07,3.16153263086628e-07,3.15796430961248e-07,3.1544020261273e-07,3.15084576679683e-07,3.14729551804551e-07,3.143751266336e-07,3.14021299816904e-07,3.13668070008337e-07,3.1331543586555e-07,3.12963396049971e-07,3.12611949226782e-07,3.12261094064911e-07,3.1191082923702e-07,3.1156115341949e-07,3.11212065292409e-07,3.10863563539562e-07,3.10515646848415e-07,3.10168313910106e-07,3.0982156341943e-07,3.09475394074827e-07,3.09129804578373e-07,3.08784793635763e-07,3.08440359956303e-07,3.08096502252896e-07,3.07753219242029e-07,3.07410509643764e-07,3.07068372181723e-07,3.06726805583078e-07,3.06385808578539e-07,3.06045379902341e-07,3.05705518292232e-07,3.05366222489466e-07,3.05027491238785e-07,3.04689323288409e-07,3.04351717390029e-07,3.04014672298788e-07,3.03678186773278e-07,3.0334225957552e-07,3.03006889470959e-07,3.02672075228449e-07,3.02337815620246e-07,3.02004109421989e-07,3.01670955412699e-07,3.01338352374757e-07,3.01006299093904e-07,3.00674794359219e-07,3.00343836963116e-07,3.00013425701331e-07,2.99683559372907e-07,2.99354236780189e-07,2.99025456728811e-07,2.98697218027681e-07,2.98369519488979e-07,2.98042359928135e-07,2.97715738163831e-07,2.97389653017978e-07,2.97064103315714e-07,2.9673908788539e-07,2.96414605558561e-07,2.96090655169972e-07,2.95767235557553e-07,2.95444345562403e-07,2.95121984028783e-07,2.94800149804106e-07,2.94478841738924e-07,2.94158058686921e-07,2.938377995049e-07,2.93518063052772e-07,2.93198848193552e-07,2.92880153793342e-07,2.92561978721323e-07,2.92244321849747e-07,2.91927182053926e-07,2.91610558212219e-07,2.91294449206026e-07,2.90978853919779e-07,2.90663771240928e-07,2.90349200059931e-07,2.9003513927025e-07,2.89721587768336e-07,2.89408544453622e-07,2.8909600822851e-07,2.88783977998366e-07,2.88472452671506e-07,2.88161431159192e-07,2.87850912375615e-07,2.87540895237893e-07,2.87231378666054e-07,2.86922361583035e-07,2.86613842914667e-07,2.86305821589664e-07,2.85998296539622e-07,2.85691266698999e-07,2.85384731005116e-07,2.8507868839814e-07,2.84773137821079e-07,2.84468078219771e-07,2.84163508542876e-07,2.83859427741867e-07,2.8355583477102e-07,2.83252728587406e-07,2.82950108150881e-07,2.82647972424078e-07,2.82346320372398e-07,2.82045150964001e-07,2.81744463169796e-07,2.81444255963435e-07,2.81144528321302e-07,2.80845279222503e-07,2.80546507648862e-07,2.80248212584908e-07,2.79950393017868e-07,2.79653047937658e-07,2.79356176336875e-07,2.79059777210788e-07,2.7876384955733e-07,2.78468392377089e-07,2.781734046733e-07,2.77878885451835e-07,2.77584833721198e-07,2.77291248492514e-07,2.7699812877952e-07,2.76705473598559e-07,2.76413281968571e-07,2.76121552911084e-07,2.75830285450207e-07,2.75539478612622e-07,2.75249131427571e-07,2.74959242926858e-07,2.74669812144829e-07,2.74380838118375e-07,2.74092319886915e-07,2.73804256492394e-07,2.73516646979272e-07,2.73229490394517e-07,2.72942785787597e-07,2.72656532210473e-07,2.7237072871759e-07,2.72085374365869e-07,2.71800468214701e-07,2.71516009325936e-07,2.71231996763879e-07,2.70948429595282e-07,2.7066530688933e-07,2.70382627717644e-07,2.70100391154265e-07,2.69818596275648e-07,2.69537242160658e-07,2.69256327890558e-07,2.68975852549005e-07,2.68695815222041e-07,2.68416214998085e-07,2.68137050967926e-07,2.67858322224716e-07,2.67580027863963e-07,2.67302166983523e-07,2.67024738683592e-07,2.667477420667e-07,2.66471176237704e-07,2.66195040303779e-07,2.65919333374412e-07,2.65644054561395e-07,2.65369202978817e-07,2.65094777743058e-07,2.64820777972781e-07,2.64547202788925e-07,2.64274051314698e-07,2.6400132267557e-07,2.63729015999267e-07,2.63457130415763e-07,2.63185665057272e-07,2.62914619058243e-07,2.62643991555352e-07,2.62373781687497e-07,2.62103988595787e-07,2.61834611423541e-07,2.61565649316275e-07,2.61297101421699e-07,2.61028966889712e-07,2.60761244872389e-07,2.60493934523981e-07,2.60227035000903e-07,2.59960545461732e-07,2.59694465067196e-07,2.5942879298017e-07,2.59163528365671e-07,2.58898670390847e-07,2.58634218224973e-07,2.58370171039444e-07,2.58106528007771e-07,2.57843288305571e-07,2.5758045111056e-07,2.57318015602551e-07,2.57055980963445e-07,2.56794346377222e-07,2.56533111029941e-07,2.56272274109728e-07,2.56011834806771e-07,2.55751792313316e-07,2.55492145823657e-07,2.55232894534136e-07,2.54974037643127e-07,2.54715574351041e-07,2.54457503860311e-07,2.54199825375389e-07,2.53942538102742e-07,2.53685641250842e-07,2.53429134030164e-07,2.53173015653175e-07,2.52917285334334e-07,2.52661942290079e-07,2.52406985738827e-07,2.52152414900967e-07,2.51898228998849e-07,2.51644427256785e-07,2.51391008901038e-07,2.51137973159819e-07,2.50885319263279e-07,2.50633046443508e-07,2.50381153934519e-07,2.50129640972254e-07,2.49878506794571e-07,2.4962775064124e-07,2.49377371753937e-07,2.49127369376239e-07,2.48877742753617e-07,2.48628491133433e-07,2.48379613764931e-07,2.48131109899234e-07,2.47882978789334e-07,2.47635219690095e-07,2.47387831858237e-07,2.47140814552337e-07,2.46894167032824e-07,2.46647888561968e-07,2.4640197840388e-07,2.46156435824504e-07,2.45911260091611e-07,2.45666450474795e-07,2.45422006245467e-07,2.45177926676849e-07,2.4493421104397e-07,2.44690858623658e-07,2.44447868694538e-07,2.44205240537025e-07,2.43962973433317e-07,2.43721066667394e-07,2.43479519525008e-07,2.43238331293681e-07,2.42997501262697e-07,2.427570287231e-07,2.42516912967687e-07,2.42277153291001e-07,2.4203774898933e-07,2.41798699360699e-07,2.41560003704864e-07,2.4132166132331e-07,2.41083671519243e-07,2.40846033597588e-07,2.4060874686498e-07,2.40371810629761e-07,2.40135224201976e-07,2.39898986893366e-07,2.39663098017364e-07,2.39427556889092e-07,2.3919236282535e-07,2.38957515144618e-07,2.38723013167047e-07,2.38488856214456e-07,2.38255043610324e-07,2.3802157467979e-07,2.37788448749643e-07,2.37555665148322e-07,2.37323223205906e-07,2.37091122254116e-07,2.36859361626301e-07,2.36627940657443e-07,2.36396858684145e-07,2.36166115044629e-07,2.35935709078732e-07,2.35705640127899e-07,2.35475907535182e-07,2.35246510645231e-07,2.35017448804291e-07,2.34788721360199e-07,2.34560327662378e-07,2.34332267061831e-07,2.34104538911139e-07,2.33877142564455e-07,2.33650077377499e-07,2.33423342707555e-07,2.33196937913465e-07,2.32970862355623e-07,2.32745115395976e-07,2.32519696398014e-07,2.32294604726767e-07,2.32069839748802e-07,2.31845400832217e-07,2.31621287346638e-07,2.31397498663211e-07,2.31174034154603e-07,2.30950893194994e-07,2.30728075160074e-07,2.30505579427036e-07,2.30283405374577e-07,2.30061552382886e-07,2.29840019833649e-07,2.29618807110036e-07,2.29397913596703e-07,2.29177338679783e-07,2.28957081746886e-07,2.2873714218709e-07,2.28517519390943e-07,2.28298212750453e-07,2.28079221659086e-07,2.27860545511761e-07,2.2764218370485e-07,2.27424135636167e-07,2.2720640070497e-07,2.26988978311951e-07,2.26771867859237e-07,2.26555068750385e-07,2.26338580390375e-07,2.26122402185609e-07,2.25906533543904e-07,2.25690973874492e-07,2.25475722588012e-07,2.25260779096507e-07,2.25046142813424e-07,2.24831813153601e-07,2.24617789533274e-07,2.24404071370065e-07,2.24190658082979e-07,2.23977549092406e-07,2.23764743820109e-07,2.23552241689226e-07,2.23340042124262e-07,2.2312814455109e-07,2.2291654839694e-07,2.22705253090402e-07,2.2249425806142e-07,2.22283562741286e-07,2.22073166562639e-07,2.21863068959457e-07};
-
-static int aes_random(char *ctx);
-
+//
+// The number of bytes that are in the randomized buffer.
+// AES 128 bit uses 16 byte blocks.
+//
#define RANDOMNESS_BUFFER_SIZE 16
+#define RANDOMNESS_AES_KEY "0123456789012345"
-#define RANDOMNESS_MAX
-
-#define SEED(ctx, s) aes_seed_context(ctx, s)
-
-#define RAND(ctx) (((double) ((unsigned int) aes_random(ctx)))/((double)UINT_MAX))
-
-#define RANDOM(ctx, n) (( (unsigned int) aes_random(ctx)) % (n))
-
-static int
-get_degree0(int size, VALUE rnd_ctx)
-{
- int rval = 1;
- double d = RAND(RSTRING(rnd_ctx)->ptr) - P0[rval];
- while (d > 0.0) {
- rval ++;
- d = d - P0[rval];
- }
- if (rval > size)
- return size;
- else
- return rval;
-}
-static int
-get_degree1(int size, VALUE rnd_ctx)
-{
- int rval = 1;
- double d = RAND(RSTRING(rnd_ctx)->ptr) - P1[rval];
- while (d > 0.0) {
- rval ++;
- d = d - P1[rval];
- }
- if (rval > size)
- return size;
- else
- return rval;
-}
-
-
-int (*get_degree_func(int size))(int, VALUE)
-{
- if (size < 1024)
- return &get_degree0;
- return &get_degree1;
-}
-
-
+//
+// Encrypt the buffer of ctx and set its counter to 0
+//
static void
aes_randomize_context(char *ctx)
{
AES_KEY key;
- AES_set_encrypt_key((unsigned char *) "0123456789012345", 128, &key);
+ AES_set_encrypt_key((unsigned char *) RANDOMNESS_AES_KEY, 128, &key);
AES_encrypt((unsigned char *) ctx + 4, (unsigned char *) ctx + 4, &key);
( (int *) ctx )[0] = 0;
}
-static void
-aes_seed_context(char *ctx, int seed)
-{
- int tmp;
-
- for (tmp = 1; tmp < ( (RANDOMNESS_BUFFER_SIZE / 4) + 1 ); tmp++) {
- ( (int *) ctx )[tmp] = seed;
- }
- aes_randomize_context(ctx);
-}
-
+//
+// Get the int at the counter of ctx in the buffer of ctx.
+//
static int
aes_random(char *ctx)
{
@@ -116,12 +65,54 @@
}
+//
+// Fill the buffer of ctx with seed and randomize it.
+//
+static void
+aes_seed_context(char *ctx, int seed)
+{
+ int tmp;
+
+ for (tmp = 1; tmp < ( (RANDOMNESS_BUFFER_SIZE / 4) + 1 ); tmp++) {
+ ( (int *) ctx )[tmp] = seed;
+ }
+ aes_randomize_context(ctx);
+}
+
+//
+// Return a ruby String suitable to use as a randomness context.
+//
static VALUE
get_aes_context()
{
return rb_str_new(0, RANDOMNESS_BUFFER_SIZE + 4);
}
+//
+// Use macros for the random functions so that they are easy to swap.
+//
+#define SEED(ctx, s) aes_seed_context(ctx, s)
+#define RAND(ctx) (((double) ((unsigned int) aes_random(ctx)))/((double)UINT_MAX))
+#define RANDOM(ctx, n) (( (unsigned int) aes_random(ctx)) % (n))
+
+//
+// Get a random degree for a check block.
+//
+static int
+get_degree(int size, VALUE rnd_ctx)
+{
+ int rval = 1;
+ double d = RAND(RSTRING(rnd_ctx)->ptr) - P[rval];
+ while (d > 0.0) {
+ rval ++;
+ d = d - P[rval];
+ }
+ if (rval > size)
+ return size;
+ else
+ return rval;
+}
+
static char
get_is_known(VALUE decode_status, int block_number)
{
@@ -164,7 +155,7 @@
}
static char
-get_check_block(VALUE self, int seed, int index, VALUE aux_blocks, int (*degree_func)(int, VALUE), VALUE rnd_ctx)
+get_check_block(VALUE self, int seed, int index, VALUE aux_blocks, VALUE rnd_ctx)
{
int degree;
int empty_block = 1;
@@ -173,7 +164,7 @@
//printf("creating check block %d:", index);
// Find [degree] blocks.
- for (degree = degree_func(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
+ for (degree = get_degree(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
int block_number;
char found_block;
@@ -243,7 +234,6 @@
int size = ( (int *) RSTRING(chunk)->ptr )[1];
int tmp, tmp2;
char got_new_block = 0;
- int (*degree_func)(int, VALUE) = get_degree_func(size);
VALUE rnd_ctx = get_aes_context();
SEED(RSTRING(rnd_ctx)->ptr, seed);
@@ -252,7 +242,7 @@
//printf("looking at check block %d:", tmp);
- degree = degree_func(size, rnd_ctx);
+ degree = get_degree(size, rnd_ctx);
if (degree == 1) {
int block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
@@ -289,7 +279,7 @@
}
}
//printf("\n");
- fflush(NULL);
+ //fflush(NULL);
}
return (got_new_block ? Qtrue : Qfalse);
@@ -331,7 +321,6 @@
int seed;
struct timeval tmp_timeval;
char chunk[chunk_size];
- int (*degree_func)(int, VALUE) = get_degree_func(RSTRING(self)->len);
VALUE rnd_ctx = get_aes_context();
gettimeofday(&tmp_timeval, NULL);
srandom(tmp_timeval.tv_usec);
@@ -341,7 +330,7 @@
( (int *) chunk) [1] = RSTRING(self)->len;
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < chunk_size; tmp++) {
- chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, degree_func, rnd_ctx);
+ chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, rnd_ctx);
}
return (rb_str_new(chunk, chunk_size));
@@ -446,7 +435,7 @@
}
}
}
- fflush(NULL);
+ //fflush(NULL);
return (got_new_block ? Qtrue : Qfalse);
}
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-23 13:21:16 UTC (rev 133)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-23 17:09:39 UTC (rev 134)
@@ -22,9 +22,8 @@
#
class SuperString < String
- E = [0.05, 0.01]
- Q = [3, 3]
- THRESHOLDS = [1024]
+ E = 0.01
+ Q = 3
#
# Will return a chunk of check blocks for this SuperString.
@@ -97,18 +96,9 @@
private
def get_aux_blocks
- (self.size * (get_q * get_e * 0.55)).ceil
+ (self.size * (Q * E * 0.55)).ceil
end
- def get_q
- 0.upto(THRESHOLDS.size - 1) do |n|
- if size < THRESHOLDS[n]
- return Q[n]
- end
- end
- return Q.last
- end
-
def do_decode
found_new_block = false
@_known_chunks.each do |known_chunk|
@@ -119,23 +109,14 @@
return found_new_block
end
- def get_e
- 0.upto(THRESHOLDS.size - 1) do |n|
- if size < THRESHOLDS[n]
- return E[n]
- end
- end
- return E.last
- end
-
def ensure_aux_blocks
@_aux_blocks ||= nil
- _fill_aux_blocks(get_aux_blocks, get_q) unless @_aux_blocks
+ _fill_aux_blocks(get_aux_blocks, Q) unless @_aux_blocks
end
def ensure_aux_hash
@_aux_hash ||= nil
- _fill_aux_hash(get_q, get_aux_blocks) unless @_aux_hash
+ _fill_aux_hash(Q, get_aux_blocks) unless @_aux_hash
end
end
From nobody at rubyforge.org Sat Dec 23 12:10:55 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 23 Dec 2006 12:10:55 -0500 (EST)
Subject: [Archipelago-submits] [135] trunk/oneliner/ext/superstring_ext.c:
more comments.
Message-ID: <20061223171056.0B8545241037@rubyforge.org>
Revision: 135
Author: zond
Date: 2006-12-23 12:10:55 -0500 (Sat, 23 Dec 2006)
Log Message:
-----------
more comments.
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 17:09:39 UTC (rev 134)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 17:10:55 UTC (rev 135)
@@ -113,6 +113,9 @@
return rval;
}
+//
+// Return whether the block_number is known according to the decode_status.
+//
static char
get_is_known(VALUE decode_status, int block_number)
{
@@ -121,6 +124,9 @@
return ((RSTRING(decode_status)->ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
}
+//
+// Set that the block_number is known according to the decode_status.
+//
static void
set_is_known(VALUE decode_status, int block_number)
{
@@ -130,6 +136,9 @@
RSTRING(decode_status)->ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
}
+//
+// Set the data or aux block with index to be value, and set it as known.
+//
static void
set_value(VALUE aux_blocks, int index, char value, VALUE self, VALUE decode_status)
{
From nobody at rubyforge.org Sat Dec 23 16:10:42 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 23 Dec 2006 16:10:42 -0500 (EST)
Subject: [Archipelago-submits] [136] trunk/oneliner: more tests and comments
Message-ID: <20061223211042.96D5C5241307@rubyforge.org>
Revision: 136
Author: zond
Date: 2006-12-23 16:10:40 -0500 (Sat, 23 Dec 2006)
Log Message:
-----------
more tests and comments
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/tests/superstring_test.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 17:10:55 UTC (rev 135)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 21:10:40 UTC (rev 136)
@@ -153,6 +153,9 @@
}
}
+//
+// Get the value at index from data or aux blocks.
+//
static char
get_value(VALUE aux_blocks, int index, VALUE self)
{
@@ -163,6 +166,9 @@
}
}
+//
+// Get a random check block from our data and aux blocks.
+//
static char
get_check_block(VALUE self, int seed, int index, VALUE aux_blocks, VALUE rnd_ctx)
{
@@ -199,43 +205,70 @@
return block;
}
-
-static VALUE _get_aes_context(VALUE self) {
-
+//
+// Get a random context, mainly for testing purposes.
+//
+static VALUE
+_get_aes_context(VALUE self)
+{
return (get_aes_context());
}
-
-static VALUE _aes_seed_context(VALUE self, VALUE _ctx, VALUE _s) {
+//
+// Seed a context, mainly for testing purposes.
+//
+static VALUE
+_aes_seed_context(VALUE self, VALUE _ctx, VALUE _s)
+{
char * ctx = STR2CSTR(_ctx);
int s = NUM2INT(_s);
aes_seed_context(ctx, s);
-return Qnil;
+ return Qnil;
}
-static VALUE _aes_random(VALUE self, VALUE _ctx) {
+//
+// Get a random int from the context, mainly for testing purposes.
+//
+static VALUE
+_aes_random(VALUE self, VALUE _ctx)
+{
char * ctx = STR2CSTR(_ctx);
return INT2NUM(aes_random(ctx));
}
-
-static VALUE _macro_rand(VALUE self, VALUE _ctx) {
+//
+// Get what the RAND macro produces, mainly for testing purposes.
+//
+static VALUE
+_macro_rand(VALUE self, VALUE _ctx)
+{
char * ctx = STR2CSTR(_ctx);
return rb_float_new(RAND(ctx));
}
-
-static VALUE _macro_random(VALUE self, VALUE _ctx, VALUE _lim) {
+//
+// Get what the RANDOM macro produces, mainly for testing purposes.
+//
+static VALUE
+_macro_random(VALUE self, VALUE _ctx, VALUE _lim)
+{
char * ctx = STR2CSTR(_ctx);
int lim = NUM2INT(_lim);
return INT2NUM(RANDOM(ctx, lim));
}
-static VALUE _decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks) {
+//
+// Decode the given _chunk using the provided _decode_status and _aux_blocks.
+//
+// Returns whether the decoding produced any new blocks.
+//
+static VALUE
+_decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks)
+{
VALUE chunk = (_chunk);
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
@@ -294,7 +327,12 @@
return (got_new_block ? Qtrue : Qfalse);
}
-static VALUE _fill_aux_blocks(VALUE self, VALUE _size, VALUE _q) {
+//
+// Create the @_aux_blocks instance attribute with _size blocks and the given _q value.
+//
+static VALUE
+_fill_aux_blocks(VALUE self, VALUE _size, VALUE _q)
+{
int size = NUM2INT(_size);
int q = NUM2INT(_q);
@@ -319,7 +357,7 @@
}
}
rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
-return Qnil;
+ return Qnil;
}
static VALUE _get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks) {
@@ -382,10 +420,15 @@
rb_funcall(aux_ary, set_func, 2, INT2NUM(tmp), data_block_string);
}
rb_ivar_set(self, rb_intern("@_aux_hash"), aux_ary);
-return Qnil;
+ return Qnil;
}
-static VALUE _oneline_done(VALUE self, VALUE _decode_status) {
+//
+// Returns whether the decoding process is finished.
+//
+static VALUE
+_oneline_done(VALUE self, VALUE _decode_status)
+{
VALUE decode_status = (_decode_status);
int tmp;
@@ -404,8 +447,12 @@
return (Qtrue);
}
-
-static VALUE _aux_decode(VALUE self, VALUE _decode_status, VALUE _aux_blocks, VALUE _aux_hash) {
+//
+// Decode our aux blocks, and return if it produced any new blocks.
+//
+static VALUE
+_aux_decode(VALUE self, VALUE _decode_status, VALUE _aux_blocks, VALUE _aux_hash)
+{
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
VALUE aux_hash = (_aux_hash);
Modified: trunk/oneliner/tests/superstring_test.rb
===================================================================
--- trunk/oneliner/tests/superstring_test.rb 2006-12-23 17:10:55 UTC (rev 135)
+++ trunk/oneliner/tests/superstring_test.rb 2006-12-23 21:10:40 UTC (rev 136)
@@ -14,6 +14,18 @@
assert(r2 >= 0)
assert(r2 < 13)
end
+ 10.times do
+ seed = rand(1 << 31)
+ values = []
+ s._aes_seed_context(c, seed)
+ 100.times do
+ values << s._aes_random(c)
+ end
+ s._aes_seed_context(c, seed)
+ 100.times do |n|
+ assert_equal(values[n], s._aes_random(c))
+ end
+ end
end
def test_decoding
From nobody at rubyforge.org Sat Dec 23 18:23:59 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sat, 23 Dec 2006 18:23:59 -0500 (EST)
Subject: [Archipelago-submits] [137] trunk/oneliner/ext/superstring_ext.c:
more preparation for variable block size and more comments
Message-ID: <20061223232359.A4DAB5241381@rubyforge.org>
Revision: 137
Author: zond
Date: 2006-12-23 18:23:59 -0500 (Sat, 23 Dec 2006)
Log Message:
-----------
more preparation for variable block size and more comments
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 21:10:40 UTC (rev 136)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-23 23:23:59 UTC (rev 137)
@@ -167,14 +167,13 @@
}
//
-// Get a random check block from our data and aux blocks.
+// Get a random check block from our data and aux blocks and append it to chunk at index.
//
-static char
-get_check_block(VALUE self, int seed, int index, VALUE aux_blocks, VALUE rnd_ctx)
+static void
+append_check_block(VALUE self, int seed, int index, VALUE aux_blocks, VALUE rnd_ctx, char *chunk)
{
int degree;
int empty_block = 1;
- char block = 0;
//printf("creating check block %d:", index);
@@ -195,14 +194,13 @@
}
// Create the block by xoring.
if (empty_block) {
- block = found_block;
+ chunk[index] = found_block;
empty_block = 0;
} else {
- block = block ^ found_block;
+ chunk[index] = chunk[index] ^ found_block;
}
}
- //printf(" => %d\n", block);
- return block;
+ //printf(" => %d\n", chunk[index]);
}
//
@@ -360,7 +358,12 @@
return Qnil;
}
-static VALUE _get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks) {
+//
+// Return a chunk of check blocks that is _chunk_size big.
+//
+static VALUE
+_get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks)
+{
int chunk_size = NUM2INT(_chunk_size);
VALUE aux_blocks = (_aux_blocks);
@@ -377,14 +380,18 @@
( (int *) chunk) [1] = RSTRING(self)->len;
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < chunk_size; tmp++) {
- chunk[tmp] = get_check_block(self, seed, tmp, aux_blocks, rnd_ctx);
+ append_check_block(self, seed, tmp, aux_blocks, rnd_ctx, chunk);
}
return (rb_str_new(chunk, chunk_size));
}
-
-static VALUE _fill_aux_hash(VALUE self, VALUE _q, VALUE _size) {
+//
+// Create the instance attribute @_aux_hash containing the structure of our aux blocks.
+//
+static VALUE
+_fill_aux_hash(VALUE self, VALUE _q, VALUE _size)
+{
int q = NUM2INT(_q);
int size = NUM2INT(_size);
From nobody at rubyforge.org Sun Dec 24 07:44:19 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 24 Dec 2006 07:44:19 -0500 (EST)
Subject: [Archipelago-submits] [138] trunk/oneliner/ext/superstring_ext.c:
now aux block generation takes block size into account as well
Message-ID: <20061224124419.599645240B60@rubyforge.org>
Revision: 138
Author: zond
Date: 2006-12-24 07:44:19 -0500 (Sun, 24 Dec 2006)
Log Message:
-----------
now aux block generation takes block size into account as well
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-23 23:23:59 UTC (rev 137)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-24 12:44:19 UTC (rev 138)
@@ -167,37 +167,40 @@
}
//
-// Get a random check block from our data and aux blocks and append it to chunk at index.
+// Get a random check block of block_size from our data and aux blocks and append it to chunk at index.
//
static void
-append_check_block(VALUE self, int seed, int index, VALUE aux_blocks, VALUE rnd_ctx, char *chunk)
+append_check_block(VALUE self, int seed, int index, VALUE aux_blocks, VALUE rnd_ctx, char *chunk, int block_size)
{
int degree;
int empty_block = 1;
+ int tmp;
//printf("creating check block %d:", index);
// Find [degree] blocks.
for (degree = get_degree(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
int block_number;
- char found_block;
+ char *found_block;
block_number = RANDOM(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len + RSTRING(aux_blocks)->len);
// Depending on whether the block is in our data or our own, debug about it
// and remember what it was.
if (block_number < RSTRING(self)->len) {
- found_block = RSTRING(self)->ptr[block_number];
+ found_block = RSTRING(self)->ptr + block_number;
//printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
} else {
- found_block = RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len];
+ found_block = RSTRING(aux_blocks)->ptr + block_number - RSTRING(self)->len;
//printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
}
// Create the block by xoring.
if (empty_block) {
- chunk[index] = found_block;
+ memcpy(chunk + index, found_block, block_size);
empty_block = 0;
} else {
- chunk[index] = chunk[index] ^ found_block;
+ for (tmp = 0; tmp < block_size; tmp++) {
+ chunk[index + tmp] = chunk[index + tmp] ^ found_block[tmp];
+ }
}
}
//printf(" => %d\n", chunk[index]);
@@ -326,6 +329,15 @@
}
//
+// Return the number of chars in a block.
+//
+static int
+get_block_size(int len)
+{
+ return 1;
+}
+
+//
// Create the @_aux_blocks instance attribute with _size blocks and the given _q value.
//
static VALUE
@@ -333,28 +345,31 @@
{
int size = NUM2INT(_size);
int q = NUM2INT(_q);
+ int block_size = get_block_size(RSTRING(self)->len);
- char aux_blocks[size];
+ char aux_blocks[size * block_size];
char initialized_aux_blocks[size];
- int tmp, tmp2;
+ int tmp, tmp2, tmp3;
VALUE rnd_ctx = get_aes_context();
for (tmp = 0; tmp < size; tmp++)
initialized_aux_blocks[tmp] = 0;
SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
- for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+ for (tmp = 0; tmp < RSTRING(self)->len; tmp = tmp + block_size) {
for (tmp2 = 0; tmp2 < q; tmp2++) {
int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
if (initialized_aux_blocks[aux_block_nr]) {
- aux_blocks[aux_block_nr] = aux_blocks[aux_block_nr] ^ RSTRING(self)->ptr[tmp];
+ for (tmp3 = 0; tmp3 < block_size; tmp3++) {
+ aux_blocks[(aux_block_nr * block_size) + tmp3] = RSTRING(self)->ptr[tmp + tmp3] ^ aux_blocks[(aux_block_nr * block_size) + tmp3];
+ }
} else {
- aux_blocks[aux_block_nr] = RSTRING(self)->ptr[tmp];
+ memcpy(aux_blocks + (aux_block_nr * block_size), RSTRING(self)->ptr + tmp, block_size);
initialized_aux_blocks[aux_block_nr] = 1;
}
}
}
- rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size));
+ rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size * block_size));
return Qnil;
}
@@ -366,6 +381,7 @@
{
int chunk_size = NUM2INT(_chunk_size);
VALUE aux_blocks = (_aux_blocks);
+ int block_size = get_block_size(RSTRING(self)->len);
unsigned int tmp;
int seed;
@@ -379,8 +395,8 @@
( (int *) chunk) [0] = seed;
( (int *) chunk) [1] = RSTRING(self)->len;
SEED(RSTRING(rnd_ctx)->ptr, seed);
- for (tmp = 8; tmp < chunk_size; tmp++) {
- append_check_block(self, seed, tmp, aux_blocks, rnd_ctx, chunk);
+ for (tmp = 8; tmp < chunk_size; tmp = tmp + block_size) {
+ append_check_block(self, seed, tmp, aux_blocks, rnd_ctx, chunk, block_size);
}
return (rb_str_new(chunk, chunk_size));
@@ -394,6 +410,7 @@
{
int q = NUM2INT(_q);
int size = NUM2INT(_size);
+ int block_size = get_block_size(RSTRING(self)->len);
int tmp, tmp2;
VALUE aux_ary = rb_ary_new();
From nobody at rubyforge.org Wed Dec 27 07:12:40 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:12:40 -0500 (EST)
Subject: [Archipelago-submits] [139] trunk/oneliner: moved block size
decisions into ruby code
Message-ID: <20061227121240.61A5F5240F5F@rubyforge.org>
Revision: 139
Author: zond
Date: 2006-12-27 07:12:39 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
moved block size decisions into ruby code
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-24 12:44:19 UTC (rev 138)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:12:39 UTC (rev 139)
@@ -329,23 +329,14 @@
}
//
-// Return the number of chars in a block.
-//
-static int
-get_block_size(int len)
-{
- return 1;
-}
-
-//
// Create the @_aux_blocks instance attribute with _size blocks and the given _q value.
//
static VALUE
-_fill_aux_blocks(VALUE self, VALUE _size, VALUE _q)
+_fill_aux_blocks(VALUE self, VALUE _size, VALUE _q, VALUE block_size_value)
{
int size = NUM2INT(_size);
int q = NUM2INT(_q);
- int block_size = get_block_size(RSTRING(self)->len);
+ int block_size = NUM2INT(block_size_value);
char aux_blocks[size * block_size];
char initialized_aux_blocks[size];
@@ -377,11 +368,11 @@
// Return a chunk of check blocks that is _chunk_size big.
//
static VALUE
-_get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks)
+_get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks, VALUE block_size_value)
{
int chunk_size = NUM2INT(_chunk_size);
VALUE aux_blocks = (_aux_blocks);
- int block_size = get_block_size(RSTRING(self)->len);
+ int block_size = NUM2INT(block_size_value);
unsigned int tmp;
int seed;
@@ -406,11 +397,11 @@
// Create the instance attribute @_aux_hash containing the structure of our aux blocks.
//
static VALUE
-_fill_aux_hash(VALUE self, VALUE _q, VALUE _size)
+_fill_aux_hash(VALUE self, VALUE _q, VALUE _size, VALUE block_size_value)
{
int q = NUM2INT(_q);
int size = NUM2INT(_size);
- int block_size = get_block_size(RSTRING(self)->len);
+ int block_size = NUM2INT(block_size_value);
int tmp, tmp2;
VALUE aux_ary = rb_ary_new();
@@ -532,10 +523,10 @@
rb_define_method(c, "_aes_seed_context", (VALUE(*)(ANYARGS))_aes_seed_context, 2);
rb_define_method(c, "_aux_decode", (VALUE(*)(ANYARGS))_aux_decode, 3);
rb_define_method(c, "_decode_chunk", (VALUE(*)(ANYARGS))_decode_chunk, 3);
- rb_define_method(c, "_fill_aux_blocks", (VALUE(*)(ANYARGS))_fill_aux_blocks, 2);
- rb_define_method(c, "_fill_aux_hash", (VALUE(*)(ANYARGS))_fill_aux_hash, 2);
+ rb_define_method(c, "_fill_aux_blocks", (VALUE(*)(ANYARGS))_fill_aux_blocks, 3);
+ rb_define_method(c, "_fill_aux_hash", (VALUE(*)(ANYARGS))_fill_aux_hash, 3);
rb_define_method(c, "_get_aes_context", (VALUE(*)(ANYARGS))_get_aes_context, 0);
- rb_define_method(c, "_get_chunk", (VALUE(*)(ANYARGS))_get_chunk, 2);
+ rb_define_method(c, "_get_chunk", (VALUE(*)(ANYARGS))_get_chunk, 3);
rb_define_method(c, "_macro_rand", (VALUE(*)(ANYARGS))_macro_rand, 1);
rb_define_method(c, "_macro_random", (VALUE(*)(ANYARGS))_macro_random, 2);
rb_define_method(c, "_oneline_done", (VALUE(*)(ANYARGS))_oneline_done, 1);
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-24 12:44:19 UTC (rev 138)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:12:39 UTC (rev 139)
@@ -34,7 +34,7 @@
#
def oneline_encode(chunk_size)
ensure_aux_blocks
- return _get_chunk(chunk_size, @_aux_blocks)
+ return _get_chunk(chunk_size, @_aux_blocks, get_block_size)
end
#
@@ -109,14 +109,18 @@
return found_new_block
end
+ def get_block_size
+ return 1
+ end
+
def ensure_aux_blocks
@_aux_blocks ||= nil
- _fill_aux_blocks(get_aux_blocks, Q) unless @_aux_blocks
+ _fill_aux_blocks(get_aux_blocks, Q, get_block_size) unless @_aux_blocks
end
def ensure_aux_hash
@_aux_hash ||= nil
- _fill_aux_hash(Q, get_aux_blocks) unless @_aux_hash
+ _fill_aux_hash(Q, get_aux_blocks, get_block_size) unless @_aux_hash
end
end
From nobody at rubyforge.org Wed Dec 27 07:23:52 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:23:52 -0500 (EST)
Subject: [Archipelago-submits] [140]
trunk/oneliner/lib/oneliner/superstring.rb: made strings
mutate to conform to block size, and remember the original size,
and return to it when decoding is done.
Message-ID: <20061227122352.745325240F5F@rubyforge.org>
Revision: 140
Author: zond
Date: 2006-12-27 07:23:52 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
made strings mutate to conform to block size, and remember the original size, and return to it when decoding is done.
Modified Paths:
--------------
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:12:39 UTC (rev 139)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:23:52 UTC (rev 140)
@@ -34,6 +34,7 @@
#
def oneline_encode(chunk_size)
ensure_aux_blocks
+ ensure_encode_size
return _get_chunk(chunk_size, @_aux_blocks, get_block_size)
end
@@ -45,14 +46,10 @@
#
def oneline_decode(chunk)
- needed_size = chunk[4..7].unpack("L").first
- if size == 0
- concat("\000" * needed_size)
- elsif size != needed_size
- raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
- end
+ ensure_decode_size(chunk)
+ ensure_encode_size
- @_decode_status ||= "\000" * (((needed_size + get_aux_blocks) / 8) + 1)
+ @_decode_status ||= "\000" * (((size + get_aux_blocks) / 8) + 1)
@_known_chunks ||= []
@_aux_blocks ||= "\000" * get_aux_blocks
@@ -70,8 +67,15 @@
# Returns whether the decoding is done.
#
def oneline_done
- return nil unless @_decode_status
- return _oneline_done(@_decode_status)
+ if @_decode_status
+ if _oneline_done(@_decode_status)
+ slice!(@_original_size..-1)
+ else
+ false
+ end
+ else
+ return nil
+ end
end
#
@@ -95,6 +99,14 @@
private
+ def ensure_encode_size
+ @_original_size = size
+ block_size = get_block_size
+ if size % block_size != 0
+ concat(" " * (block_size - (size % block_size)))
+ end
+ end
+
def get_aux_blocks
(self.size * (Q * E * 0.55)).ceil
end
@@ -112,6 +124,15 @@
def get_block_size
return 1
end
+
+ def ensure_decode_size(chunk)
+ needed_size = chunk[4..7].unpack("L").first
+ if size == 0
+ concat("\000" * needed_size)
+ elsif size != needed_size
+ raise "The argument to oneline_decode must be a chunk produced by oneline_encode from the same source"
+ end
+ end
def ensure_aux_blocks
@_aux_blocks ||= nil
From nobody at rubyforge.org Wed Dec 27 07:26:07 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:26:07 -0500 (EST)
Subject: [Archipelago-submits] [141] trunk/oneliner: renamed the mutative
methods
Message-ID: <20061227122607.4F8015240F5F@rubyforge.org>
Revision: 141
Author: zond
Date: 2006-12-27 07:26:07 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
renamed the mutative methods
Modified Paths:
--------------
trunk/oneliner/lib/oneliner/superstring.rb
trunk/oneliner/tests/superstring_benchmark.rb
trunk/oneliner/tests/superstring_test.rb
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:23:52 UTC (rev 140)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:26:07 UTC (rev 141)
@@ -32,7 +32,9 @@
# 8 bytes are used for metadata, so smaller chunks than that will
# result in errors.
#
- def oneline_encode(chunk_size)
+ # Beware: This String will be modified when you call this method!
+ #
+ def oneline_encode!(chunk_size)
ensure_aux_blocks
ensure_encode_size
return _get_chunk(chunk_size, @_aux_blocks, get_block_size)
@@ -44,7 +46,10 @@
# Will also remember the chunk for future reference if it was not
# enough to decode the entire SuperString.
#
- def oneline_decode(chunk)
+ # Will return whether the given data + any previouly given data
+ # is enough.
+ #
+ def oneline_decode!(chunk)
ensure_decode_size(chunk)
ensure_encode_size
Modified: trunk/oneliner/tests/superstring_benchmark.rb
===================================================================
--- trunk/oneliner/tests/superstring_benchmark.rb 2006-12-27 12:23:52 UTC (rev 140)
+++ trunk/oneliner/tests/superstring_benchmark.rb 2006-12-27 12:26:07 UTC (rev 141)
@@ -31,8 +31,8 @@
def measure_required(dest, source)
total = source.size.to_f
used = source.size.to_f
- dest.oneline_decode(source.oneline_encode(source.size))
- while (!dest.oneline_decode(source.oneline_encode((source.size.to_f * 0.1) + 8)))
+ dest.oneline_decode!(source.oneline_encode!(source.size))
+ while (!dest.oneline_decode!(source.oneline_encode!((source.size.to_f * 0.1) + 8)))
used += (source.size.to_f * 0.1)
end
return used/total
Modified: trunk/oneliner/tests/superstring_test.rb
===================================================================
--- trunk/oneliner/tests/superstring_test.rb 2006-12-27 12:23:52 UTC (rev 140)
+++ trunk/oneliner/tests/superstring_test.rb 2006-12-27 12:26:07 UTC (rev 141)
@@ -32,7 +32,7 @@
10.times do
s = Oneliner::SuperString.new
s2 = Oneliner::SuperString.new(" " * 1024)
- assert(s.oneline_decode(s2.oneline_encode(2048)))
+ assert(s.oneline_decode!(s2.oneline_encode!(2048)))
assert_equal(s2, s)
end
end
From nobody at rubyforge.org Wed Dec 27 07:27:41 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:27:41 -0500 (EST)
Subject: [Archipelago-submits] [142]
trunk/oneliner/lib/oneliner/superstring.rb: more performance
saving ensure_...
Message-ID: <20061227122741.78AD75240FA6@rubyforge.org>
Revision: 142
Author: zond
Date: 2006-12-27 07:27:41 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
more performance saving ensure_...
Modified Paths:
--------------
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:26:07 UTC (rev 141)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:27:41 UTC (rev 142)
@@ -105,10 +105,12 @@
private
def ensure_encode_size
- @_original_size = size
- block_size = get_block_size
- if size % block_size != 0
- concat(" " * (block_size - (size % block_size)))
+ unless @_original_size
+ @_original_size = size
+ block_size = get_block_size
+ if size % block_size != 0
+ concat(" " * (block_size - (size % block_size)))
+ end
end
end
From nobody at rubyforge.org Wed Dec 27 07:28:06 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:28:06 -0500 (EST)
Subject: [Archipelago-submits] [143]
trunk/oneliner/lib/oneliner/superstring.rb: removed redundant
comment
Message-ID: <20061227122806.4A2625240FA6@rubyforge.org>
Revision: 143
Author: zond
Date: 2006-12-27 07:28:06 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
removed redundant comment
Modified Paths:
--------------
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:27:41 UTC (rev 142)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:28:06 UTC (rev 143)
@@ -32,8 +32,6 @@
# 8 bytes are used for metadata, so smaller chunks than that will
# result in errors.
#
- # Beware: This String will be modified when you call this method!
- #
def oneline_encode!(chunk_size)
ensure_aux_blocks
ensure_encode_size
From nobody at rubyforge.org Wed Dec 27 07:31:45 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:31:45 -0500 (EST)
Subject: [Archipelago-submits] [144] trunk/oneliner: sending block_size to
decode_chunk and aux_decode
Message-ID: <20061227123145.81D655240FE3@rubyforge.org>
Revision: 144
Author: zond
Date: 2006-12-27 07:31:45 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
sending block_size to decode_chunk and aux_decode
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:28:06 UTC (rev 143)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:31:45 UTC (rev 144)
@@ -268,7 +268,7 @@
// Returns whether the decoding produced any new blocks.
//
static VALUE
-_decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks)
+_decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks, VALUE block_size_value)
{
VALUE chunk = (_chunk);
VALUE decode_status = (_decode_status);
@@ -278,6 +278,7 @@
int tmp, tmp2;
char got_new_block = 0;
VALUE rnd_ctx = get_aes_context();
+ int block_size = NUM2INT(block_size_value);
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
@@ -466,11 +467,12 @@
// Decode our aux blocks, and return if it produced any new blocks.
//
static VALUE
-_aux_decode(VALUE self, VALUE _decode_status, VALUE _aux_blocks, VALUE _aux_hash)
+_aux_decode(VALUE self, VALUE _decode_status, VALUE _aux_blocks, VALUE _aux_hash, VALUE block_size_value)
{
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
VALUE aux_hash = (_aux_hash);
+ int block_size = NUM2INT(block_size_value);
int tmp, tmp2;
char got_new_block = 0;
@@ -521,8 +523,8 @@
c = rb_const_get_at(c,rb_intern("SuperString"));
rb_define_method(c, "_aes_random", (VALUE(*)(ANYARGS))_aes_random, 1);
rb_define_method(c, "_aes_seed_context", (VALUE(*)(ANYARGS))_aes_seed_context, 2);
- rb_define_method(c, "_aux_decode", (VALUE(*)(ANYARGS))_aux_decode, 3);
- rb_define_method(c, "_decode_chunk", (VALUE(*)(ANYARGS))_decode_chunk, 3);
+ rb_define_method(c, "_aux_decode", (VALUE(*)(ANYARGS))_aux_decode, 4);
+ rb_define_method(c, "_decode_chunk", (VALUE(*)(ANYARGS))_decode_chunk, 4);
rb_define_method(c, "_fill_aux_blocks", (VALUE(*)(ANYARGS))_fill_aux_blocks, 3);
rb_define_method(c, "_fill_aux_hash", (VALUE(*)(ANYARGS))_fill_aux_hash, 3);
rb_define_method(c, "_get_aes_context", (VALUE(*)(ANYARGS))_get_aes_context, 0);
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:28:06 UTC (rev 143)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:31:45 UTC (rev 144)
@@ -34,7 +34,7 @@
#
def oneline_encode!(chunk_size)
ensure_aux_blocks
- ensure_encode_size
+ ensure_encode_size(get_block_size)
return _get_chunk(chunk_size, @_aux_blocks, get_block_size)
end
@@ -50,18 +50,19 @@
def oneline_decode!(chunk)
ensure_decode_size(chunk)
- ensure_encode_size
+ block_size = get_block_size
+ ensure_encode_size(block_size)
@_decode_status ||= "\000" * (((size + get_aux_blocks) / 8) + 1)
@_known_chunks ||= []
@_aux_blocks ||= "\000" * get_aux_blocks
- found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks)
- do_decode if found_new_block
+ found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks, block_size)
+ do_decode(block_size) if found_new_block
@_known_chunks.unshift(chunk)
- nil while do_decode
+ nil while do_decode(block_size)
return oneline_done
end
@@ -102,10 +103,9 @@
private
- def ensure_encode_size
+ def ensure_encode_size(block_size)
unless @_original_size
@_original_size = size
- block_size = get_block_size
if size % block_size != 0
concat(" " * (block_size - (size % block_size)))
end
@@ -116,13 +116,13 @@
(self.size * (Q * E * 0.55)).ceil
end
- def do_decode
+ def do_decode(block_size)
found_new_block = false
@_known_chunks.each do |known_chunk|
- found_new_block = _decode_chunk(known_chunk, @_decode_status, @_aux_blocks) || found_new_block
+ found_new_block = _decode_chunk(known_chunk, @_decode_status, @_aux_blocks, block_size) || found_new_block
end
ensure_aux_hash
- found_new_block = _aux_decode(@_decode_status, @_aux_blocks, @_aux_hash) || found_new_block
+ found_new_block = _aux_decode(@_decode_status, @_aux_blocks, @_aux_hash, block_size) || found_new_block
return found_new_block
end
From nobody at rubyforge.org Wed Dec 27 07:45:43 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:45:43 -0500 (EST)
Subject: [Archipelago-submits] [145] trunk/oneliner/ext/superstring_ext.c:
in the middle of making decoding block_size sensitive
Message-ID: <20061227124543.0EC27524112D@rubyforge.org>
Revision: 145
Author: zond
Date: 2006-12-27 07:45:42 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
in the middle of making decoding block_size sensitive
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:31:45 UTC (rev 144)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:45:42 UTC (rev 145)
@@ -153,6 +153,20 @@
}
}
+static void
+set_value2(VALUE aux_blocks, int index, char *value, VALUE self, VALUE decode_status, int block_size)
+{
+ if ((index * block_size) < RSTRING(self)->len) {
+ rb_str_modify(self);
+ memcpy(RSTRING(self)->ptr + (index * block_size), value, block_size);
+ set_is_known(decode_status, index);
+ } else {
+ rb_str_modify(aux_blocks);
+ memcpy(RSTRING(aux_blocks)->ptr + ((index - (RSTRING(self)->len / block_size)) * block_size), value, block_size);
+ set_is_known(decode_status, index);
+ }
+}
+
//
// Get the value at index from data or aux blocks.
//
@@ -166,6 +180,16 @@
}
}
+static char*
+get_value2(VALUE aux_blocks, int index, VALUE self, int block_size)
+{
+ if ((index * block_size) < RSTRING(self)->len) {
+ return RSTRING(self)->ptr + (index * block_size);
+ } else {
+ return RSTRING(aux_blocks)->ptr + ((index - (RSTRING(self)->len / block_size) ) * block_size);
+ }
+}
+
//
// Get a random check block of block_size from our data and aux blocks and append it to chunk at index.
//
@@ -275,13 +299,13 @@
VALUE aux_blocks = (_aux_blocks);
int seed = ( (int *) RSTRING(chunk)->ptr )[0];
int size = ( (int *) RSTRING(chunk)->ptr )[1];
- int tmp, tmp2;
+ int tmp;
char got_new_block = 0;
VALUE rnd_ctx = get_aes_context();
int block_size = NUM2INT(block_size_value);
SEED(RSTRING(rnd_ctx)->ptr, seed);
- for (tmp = 8; tmp < RSTRING(chunk)->len; tmp++) {
+ for (tmp = 8; tmp < RSTRING(chunk)->len; tmp = tmp + block_size) {
int degree;
//printf("looking at check block %d:", tmp);
@@ -289,10 +313,10 @@
degree = get_degree(size, rnd_ctx);
if (degree == 1) {
int block_nr;
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
//printf(" %d", block_nr);
if (!get_is_known(decode_status, block_nr)) {
- set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr[tmp], self, decode_status);
+ set_value2(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
//printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
} else {
@@ -301,15 +325,23 @@
} else {
int missing_blocks;
int missing_block = 0;
- char xor_sum = RSTRING(chunk)->ptr[tmp];
+ int tmp2;
+ char xor_sum[block_size];
+ memcpy(xor_sum, RSTRING(chunk)->ptr + tmp, block_size);
+
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
int block_nr;
//printf(" %d", block_nr);
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
if (get_is_known(decode_status, block_nr)) {
+ int tmp3;
+ char *this_value = get_value2(aux_blocks, block_nr, self, block_size);
+
missing_blocks--;
- xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ for (tmp3 = 0; tmp3 < block_size; tmp3++) {
+ xor_sum[tmp3] = xor_sum[tmp3] ^ this_value[tmp3];
+ }
//printf("!");
} else {
missing_block = block_nr;
@@ -317,7 +349,7 @@
}
}
if (missing_blocks == 1) {
- set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ set_value2(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
//printf(" => [%d]=%d", missing_block, xor_sum);
}
From nobody at rubyforge.org Wed Dec 27 07:52:30 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:52:30 -0500 (EST)
Subject: [Archipelago-submits] [146] trunk/oneliner/ext/superstring_ext.c:
made aux_decode block_size sensitive
Message-ID: <20061227125230.233BD5240F2B@rubyforge.org>
Revision: 146
Author: zond
Date: 2006-12-27 07:52:29 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
made aux_decode block_size sensitive
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:45:42 UTC (rev 145)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:52:29 UTC (rev 146)
@@ -333,7 +333,7 @@
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
int block_nr;
//printf(" %d", block_nr);
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size + RSTRING(aux_blocks)->len);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
if (get_is_known(decode_status, block_nr)) {
int tmp3;
char *this_value = get_value2(aux_blocks, block_nr, self, block_size);
@@ -506,35 +506,43 @@
VALUE aux_hash = (_aux_hash);
int block_size = NUM2INT(block_size_value);
- int tmp, tmp2;
+ int tmp;
char got_new_block = 0;
VALUE get_func = rb_intern("[]");
- for (tmp = 0; tmp < RSTRING(aux_blocks)->len; tmp++) {
- if (get_is_known(decode_status, RSTRING(self)->len + tmp)) {
+ for (tmp = 0; tmp < RSTRING(aux_blocks)->len; tmp = tmp + block_size) {
+ if (get_is_known(decode_status, (RSTRING(self)->len + tmp) / block_size)) {
VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
if (RSTRING(data_block_string)->len == 4) {
int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[0];
if (!get_is_known(decode_status, block_nr)) {
- set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr[tmp], self, decode_status);
+ set_value2(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
} else {
}
} else {
int missing_blocks;
int missing_block = 0;
- char xor_sum = RSTRING(aux_blocks)->ptr[tmp];
+ int tmp2;
+ char xor_sum[block_size];
+ memcpy(xor_sum, RSTRING(aux_blocks)->ptr + tmp, block_size);
+
for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[tmp2];
if (get_is_known(decode_status, block_nr)) {
- missing_blocks--;
- xor_sum = xor_sum ^ get_value(aux_blocks, block_nr, self);
+ int tmp3;
+ char *this_value = get_value2(aux_blocks, block_nr, self, block_size);
+
+ missing_blocks--;
+ for (tmp3 = 0; tmp3 < block_size; tmp3++) {
+ xor_sum[tmp3] = xor_sum[tmp3] ^ this_value[tmp3];
+ }
} else {
missing_block = block_nr;
}
}
if (missing_blocks == 1) {
- set_value(aux_blocks, missing_block, xor_sum, self, decode_status);
+ set_value2(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
}
}
From nobody at rubyforge.org Wed Dec 27 07:58:15 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 07:58:15 -0500 (EST)
Subject: [Archipelago-submits] [147] trunk/oneliner/ext/superstring_ext.c:
removed intermediary set/get value methods
Message-ID: <20061227125816.05CDE5240F2B@rubyforge.org>
Revision: 147
Author: zond
Date: 2006-12-27 07:58:15 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
removed intermediary set/get value methods
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:52:29 UTC (rev 146)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:58:15 UTC (rev 147)
@@ -140,22 +140,8 @@
// Set the data or aux block with index to be value, and set it as known.
//
static void
-set_value(VALUE aux_blocks, int index, char value, VALUE self, VALUE decode_status)
+set_value(VALUE aux_blocks, int index, char *value, VALUE self, VALUE decode_status, int block_size)
{
- if (index < RSTRING(self)->len) {
- rb_str_modify(self);
- RSTRING(self)->ptr[index] = value;
- set_is_known(decode_status, index);
- } else {
- rb_str_modify(aux_blocks);
- RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len] = value;
- set_is_known(decode_status, index);
- }
-}
-
-static void
-set_value2(VALUE aux_blocks, int index, char *value, VALUE self, VALUE decode_status, int block_size)
-{
if ((index * block_size) < RSTRING(self)->len) {
rb_str_modify(self);
memcpy(RSTRING(self)->ptr + (index * block_size), value, block_size);
@@ -170,18 +156,8 @@
//
// Get the value at index from data or aux blocks.
//
-static char
-get_value(VALUE aux_blocks, int index, VALUE self)
-{
- if (index < RSTRING(self)->len) {
- return RSTRING(self)->ptr[index];
- } else {
- return RSTRING(aux_blocks)->ptr[index - RSTRING(self)->len];
- }
-}
-
static char*
-get_value2(VALUE aux_blocks, int index, VALUE self, int block_size)
+get_value(VALUE aux_blocks, int index, VALUE self, int block_size)
{
if ((index * block_size) < RSTRING(self)->len) {
return RSTRING(self)->ptr + (index * block_size);
@@ -316,7 +292,7 @@
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
//printf(" %d", block_nr);
if (!get_is_known(decode_status, block_nr)) {
- set_value2(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
+ set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
//printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
} else {
@@ -336,7 +312,7 @@
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
if (get_is_known(decode_status, block_nr)) {
int tmp3;
- char *this_value = get_value2(aux_blocks, block_nr, self, block_size);
+ char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
for (tmp3 = 0; tmp3 < block_size; tmp3++) {
@@ -349,7 +325,7 @@
}
}
if (missing_blocks == 1) {
- set_value2(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
//printf(" => [%d]=%d", missing_block, xor_sum);
}
@@ -515,7 +491,7 @@
if (RSTRING(data_block_string)->len == 4) {
int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[0];
if (!get_is_known(decode_status, block_nr)) {
- set_value2(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr + tmp, self, decode_status, block_size);
+ set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
} else {
}
@@ -531,7 +507,7 @@
int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[tmp2];
if (get_is_known(decode_status, block_nr)) {
int tmp3;
- char *this_value = get_value2(aux_blocks, block_nr, self, block_size);
+ char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
for (tmp3 = 0; tmp3 < block_size; tmp3++) {
@@ -542,7 +518,7 @@
}
}
if (missing_blocks == 1) {
- set_value2(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
+ set_value(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
}
}
From nobody at rubyforge.org Wed Dec 27 08:01:01 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 08:01:01 -0500 (EST)
Subject: [Archipelago-submits] [148] trunk/oneliner: made oneline_done
block_size aware
Message-ID: <20061227130101.B7A645240F2B@rubyforge.org>
Revision: 148
Author: zond
Date: 2006-12-27 08:01:01 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
made oneline_done block_size aware
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 12:58:15 UTC (rev 147)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 13:01:01 UTC (rev 148)
@@ -451,9 +451,10 @@
// Returns whether the decoding process is finished.
//
static VALUE
-_oneline_done(VALUE self, VALUE _decode_status)
+_oneline_done(VALUE self, VALUE _decode_status, VALUE block_size_value)
{
VALUE decode_status = (_decode_status);
+ int block_size = NUM2INT(block_size_value);
int tmp;
if (decode_status == Qnil)
@@ -463,7 +464,7 @@
return (Qfalse);
}
}
- for (tmp = 0; tmp < (RSTRING(self)->len % 8); tmp++) {
+ for (tmp = 0; tmp < ((RSTRING(self)->len / block_size) % 8); tmp++) {
if (! ( (unsigned char) RSTRING(self)->ptr[tmp] ) & (1 << tmp)) {
return (Qfalse);
}
@@ -547,7 +548,7 @@
rb_define_method(c, "_get_chunk", (VALUE(*)(ANYARGS))_get_chunk, 3);
rb_define_method(c, "_macro_rand", (VALUE(*)(ANYARGS))_macro_rand, 1);
rb_define_method(c, "_macro_random", (VALUE(*)(ANYARGS))_macro_random, 2);
- rb_define_method(c, "_oneline_done", (VALUE(*)(ANYARGS))_oneline_done, 1);
+ rb_define_method(c, "_oneline_done", (VALUE(*)(ANYARGS))_oneline_done, 2);
}
#ifdef __cplusplus
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 12:58:15 UTC (rev 147)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 13:01:01 UTC (rev 148)
@@ -64,15 +64,15 @@
nil while do_decode(block_size)
- return oneline_done
+ return oneline_done(block_size)
end
#
# Returns whether the decoding is done.
#
- def oneline_done
+ def oneline_done(block_size = get_block_size)
if @_decode_status
- if _oneline_done(@_decode_status)
+ if _oneline_done(@_decode_status, block_size)
slice!(@_original_size..-1)
else
false
From nobody at rubyforge.org Wed Dec 27 11:04:47 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 11:04:47 -0500 (EST)
Subject: [Archipelago-submits] [149] trunk/oneliner: removed lots of printfs,
added some useful macros.
Message-ID: <20061227160447.B96735241589@rubyforge.org>
Revision: 149
Author: zond
Date: 2006-12-27 11:04:47 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
removed lots of printfs, added some useful macros.
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 13:01:01 UTC (rev 148)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:04:47 UTC (rev 149)
@@ -94,7 +94,11 @@
#define SEED(ctx, s) aes_seed_context(ctx, s)
#define RAND(ctx) (((double) ((unsigned int) aes_random(ctx)))/((double)UINT_MAX))
#define RANDOM(ctx, n) (( (unsigned int) aes_random(ctx)) % (n))
+#define N_DATA_BLOCKS(self, block_size) (RSTRING(self)->len / block_size)
+#define N_AUX_BLOCKS(aux_blocks, block_size) (RSTRING(aux_blocks)->len / block_size)
+#define N_BLOCKS(self, aux_blocks, block_size) ((RSTRING(self)->len + RSTRING(aux_blocks)->len) / block_size)
+
//
// Get a random degree for a check block.
//
@@ -148,7 +152,7 @@
set_is_known(decode_status, index);
} else {
rb_str_modify(aux_blocks);
- memcpy(RSTRING(aux_blocks)->ptr + ((index - (RSTRING(self)->len / block_size)) * block_size), value, block_size);
+ memcpy(RSTRING(aux_blocks)->ptr + ((index - N_DATA_BLOCKS(self, block_size)) * block_size), value, block_size);
set_is_known(decode_status, index);
}
}
@@ -162,11 +166,22 @@
if ((index * block_size) < RSTRING(self)->len) {
return RSTRING(self)->ptr + (index * block_size);
} else {
- return RSTRING(aux_blocks)->ptr + ((index - (RSTRING(self)->len / block_size) ) * block_size);
+ return RSTRING(aux_blocks)->ptr + ((index - N_DATA_BLOCKS(self, block_size)) * block_size);
}
}
//
+// Make dest into source1 ^ source2.
+//
+static void
+xor_string(char *dest, char *source1, char *source2, int len)
+{
+ for (; len > -1; len--) {
+ dest[len - 1] = source1[len - 1] ^ source2[len - 1];
+ }
+}
+
+//
// Get a random check block of block_size from our data and aux blocks and append it to chunk at index.
//
static void
@@ -176,7 +191,6 @@
int empty_block = 1;
int tmp;
- //printf("creating check block %d:", index);
// Find [degree] blocks.
for (degree = get_degree(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
@@ -188,10 +202,8 @@
// and remember what it was.
if (block_number < RSTRING(self)->len) {
found_block = RSTRING(self)->ptr + block_number;
- //printf(" d[%d]=%d", block_number, RSTRING(self)->ptr[block_number]);
} else {
found_block = RSTRING(aux_blocks)->ptr + block_number - RSTRING(self)->len;
- //printf(" a[%d]=%d", block_number - RSTRING(self)->len, RSTRING(aux_blocks)->ptr[block_number - RSTRING(self)->len]);
}
// Create the block by xoring.
if (empty_block) {
@@ -199,11 +211,10 @@
empty_block = 0;
} else {
for (tmp = 0; tmp < block_size; tmp++) {
- chunk[index + tmp] = chunk[index + tmp] ^ found_block[tmp];
+ chunk[index + tmp] = chunk[index + tmp] ^ found_block[tmp];
}
}
}
- //printf(" => %d\n", chunk[index]);
}
//
@@ -284,19 +295,13 @@
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp = tmp + block_size) {
int degree;
- //printf("looking at check block %d:", tmp);
-
degree = get_degree(size, rnd_ctx);
if (degree == 1) {
int block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
- //printf(" %d", block_nr);
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
- //printf(" => [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
- } else {
- //printf(" [%d]=%d", block_nr, RSTRING(chunk)->ptr[tmp]);
}
} else {
int missing_blocks;
@@ -308,7 +313,6 @@
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
int block_nr;
- //printf(" %d", block_nr);
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
if (get_is_known(decode_status, block_nr)) {
int tmp3;
@@ -318,20 +322,15 @@
for (tmp3 = 0; tmp3 < block_size; tmp3++) {
xor_sum[tmp3] = xor_sum[tmp3] ^ this_value[tmp3];
}
- //printf("!");
} else {
missing_block = block_nr;
- //printf("?");
}
}
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
- //printf(" => [%d]=%d", missing_block, xor_sum);
}
}
- //printf("\n");
- //fflush(NULL);
}
return (got_new_block ? Qtrue : Qfalse);
@@ -525,7 +524,6 @@
}
}
}
- //fflush(NULL);
return (got_new_block ? Qtrue : Qfalse);
}
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 13:01:01 UTC (rev 148)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 16:04:47 UTC (rev 149)
@@ -104,6 +104,7 @@
private
def ensure_encode_size(block_size)
+ @_original_size ||= nil
unless @_original_size
@_original_size = size
if size % block_size != 0
From nobody at rubyforge.org Wed Dec 27 11:05:19 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 11:05:19 -0500 (EST)
Subject: [Archipelago-submits] [150] trunk/oneliner/ext/superstring_ext.c:
used one of the useful macros
Message-ID: <20061227160519.7741F5241589@rubyforge.org>
Revision: 150
Author: zond
Date: 2006-12-27 11:05:19 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
used one of the useful macros
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:04:47 UTC (rev 149)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:05:19 UTC (rev 150)
@@ -197,7 +197,7 @@
int block_number;
char *found_block;
- block_number = RANDOM(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len + RSTRING(aux_blocks)->len);
+ block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
// Depending on whether the block is in our data or our own, debug about it
// and remember what it was.
if (block_number < RSTRING(self)->len) {
From nobody at rubyforge.org Wed Dec 27 11:06:18 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 11:06:18 -0500 (EST)
Subject: [Archipelago-submits] [151] trunk/oneliner/ext/superstring_ext.c:
simplifed a bit of append_check_block
Message-ID: <20061227160618.D59325241589@rubyforge.org>
Revision: 151
Author: zond
Date: 2006-12-27 11:06:18 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
simplifed a bit of append_check_block
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:05:19 UTC (rev 150)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:06:18 UTC (rev 151)
@@ -198,13 +198,8 @@
char *found_block;
block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
- // Depending on whether the block is in our data or our own, debug about it
- // and remember what it was.
- if (block_number < RSTRING(self)->len) {
- found_block = RSTRING(self)->ptr + block_number;
- } else {
- found_block = RSTRING(aux_blocks)->ptr + block_number - RSTRING(self)->len;
- }
+ found_block = get_value(aux_blocks, block_number, self, block_size);
+
// Create the block by xoring.
if (empty_block) {
memcpy(chunk + index, found_block, block_size);
From nobody at rubyforge.org Wed Dec 27 11:09:20 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 11:09:20 -0500 (EST)
Subject: [Archipelago-submits] [152] trunk/oneliner/ext/superstring_ext.c:
refactored more in append_check_block
Message-ID: <20061227160920.4EC195241589@rubyforge.org>
Revision: 152
Author: zond
Date: 2006-12-27 11:09:20 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
refactored more in append_check_block
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:06:18 UTC (rev 151)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:09:20 UTC (rev 152)
@@ -194,15 +194,12 @@
// Find [degree] blocks.
for (degree = get_degree(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
- int block_number;
- char *found_block;
+ int block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
+ char *found_block = get_value(aux_blocks, block_number, self, block_size);
- block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
- found_block = get_value(aux_blocks, block_number, self, block_size);
-
// Create the block by xoring.
if (empty_block) {
- memcpy(chunk + index, found_block, block_size);
+ memcpy(chunk + (index * block_size), found_block, block_size);
empty_block = 0;
} else {
for (tmp = 0; tmp < block_size; tmp++) {
From nobody at rubyforge.org Wed Dec 27 11:15:22 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 11:15:22 -0500 (EST)
Subject: [Archipelago-submits] [153] trunk/oneliner/ext/superstring_ext.c:
rewrote xor_string.
Message-ID: <20061227161522.EE0CC524158A@rubyforge.org>
Revision: 153
Author: zond
Date: 2006-12-27 11:15:22 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
rewrote xor_string. made append_check_block use it
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:09:20 UTC (rev 152)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:15:22 UTC (rev 153)
@@ -176,9 +176,8 @@
static void
xor_string(char *dest, char *source1, char *source2, int len)
{
- for (; len > -1; len--) {
- dest[len - 1] = source1[len - 1] ^ source2[len - 1];
- }
+ for (len--; len >= 0; len--)
+ dest[len] = source1[len] ^ source2[len];
}
//
@@ -202,9 +201,7 @@
memcpy(chunk + (index * block_size), found_block, block_size);
empty_block = 0;
} else {
- for (tmp = 0; tmp < block_size; tmp++) {
- chunk[index + tmp] = chunk[index + tmp] ^ found_block[tmp];
- }
+ xor_string(chunk + index, chunk + index, found_block, block_size);
}
}
}
From nobody at rubyforge.org Wed Dec 27 11:20:13 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 11:20:13 -0500 (EST)
Subject: [Archipelago-submits] [154] trunk/oneliner/ext/superstring_ext.c:
optimized away xor_string
Message-ID: <20061227162013.97D23524158F@rubyforge.org>
Revision: 154
Author: zond
Date: 2006-12-27 11:20:13 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
optimized away xor_string
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:15:22 UTC (rev 153)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:20:13 UTC (rev 154)
@@ -176,8 +176,13 @@
static void
xor_string(char *dest, char *source1, char *source2, int len)
{
- for (len--; len >= 0; len--)
- dest[len] = source1[len] ^ source2[len];
+ int tmp;
+ for (tmp = 0; tmp < (len / 4); tmp++) {
+ ( (int *) dest )[tmp] = ( (int *) source1 )[tmp] ^ ( (int *) source2 )[tmp];
+ }
+ for (tmp = 0; tmp < (len % 4); tmp++) {
+ dest[len - tmp - 1] = source1[len - tmp - 1] ^ source2[len - tmp - 1];
+ }
}
//
From nobody at rubyforge.org Wed Dec 27 12:08:46 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 12:08:46 -0500 (EST)
Subject: [Archipelago-submits] [155] trunk/oneliner/ext/superstring_ext.c:
optimized away at oneline_done
Message-ID: <20061227170846.DE23352415AE@rubyforge.org>
Revision: 155
Author: zond
Date: 2006-12-27 12:08:46 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
optimized away at oneline_done
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 16:20:13 UTC (rev 154)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:08:46 UTC (rev 155)
@@ -444,24 +444,24 @@
// Returns whether the decoding process is finished.
//
static VALUE
-_oneline_done(VALUE self, VALUE _decode_status, VALUE block_size_value)
+_oneline_done(VALUE self, VALUE decode_status, VALUE block_size_value)
{
- VALUE decode_status = (_decode_status);
int block_size = NUM2INT(block_size_value);
+ int tmp;
+ int number_of_ints = RSTRING(self)->len / 32;
+ int number_of_chars = RSTRING(self)->len / 8;
- int tmp;
if (decode_status == Qnil)
return (Qfalse);
- for (tmp = 0; tmp < (RSTRING(decode_status)->len - 1); tmp++) {
- if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != 255) {
+ for (tmp = 0; tmp < number_of_ints; tmp++)
+ if (( (unsigned int *) RSTRING(decode_status)->ptr )[tmp] != UINT_MAX)
+ return Qfalse;
+ for (tmp = (number_of_ints * 4); tmp < number_of_chars; tmp++)
+ if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != UCHAR_MAX)
return (Qfalse);
- }
- }
- for (tmp = 0; tmp < ((RSTRING(self)->len / block_size) % 8); tmp++) {
- if (! ( (unsigned char) RSTRING(self)->ptr[tmp] ) & (1 << tmp)) {
+ for (tmp = 0; tmp < ((RSTRING(self)->len / block_size) % 8); tmp++)
+ if (! (( (unsigned char) RSTRING(decode_status)->ptr[RSTRING(decode_status)->len - 1] ) & (1 << tmp)))
return (Qfalse);
- }
- }
return (Qtrue);
}
From nobody at rubyforge.org Wed Dec 27 12:12:33 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 12:12:33 -0500 (EST)
Subject: [Archipelago-submits] [156] trunk/oneliner/ext/superstring_ext.c:
moved xor_string a bit.
Message-ID: <20061227171233.3A02752415AE@rubyforge.org>
Revision: 156
Author: zond
Date: 2006-12-27 12:12:32 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
moved xor_string a bit. made decode_chunk use it
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:08:46 UTC (rev 155)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:12:32 UTC (rev 156)
@@ -100,6 +100,21 @@
//
+// Make dest into source1 ^ source2.
+//
+static void
+xor_string(char *dest, char *source1, char *source2, int len)
+{
+ int tmp;
+ for (tmp = 0; tmp < (len / 4); tmp++) {
+ ( (int *) dest )[tmp] = ( (int *) source1 )[tmp] ^ ( (int *) source2 )[tmp];
+ }
+ for (tmp = 0; tmp < (len % 4); tmp++) {
+ dest[len - tmp - 1] = source1[len - tmp - 1] ^ source2[len - tmp - 1];
+ }
+}
+
+//
// Get a random degree for a check block.
//
static int
@@ -171,21 +186,6 @@
}
//
-// Make dest into source1 ^ source2.
-//
-static void
-xor_string(char *dest, char *source1, char *source2, int len)
-{
- int tmp;
- for (tmp = 0; tmp < (len / 4); tmp++) {
- ( (int *) dest )[tmp] = ( (int *) source1 )[tmp] ^ ( (int *) source2 )[tmp];
- }
- for (tmp = 0; tmp < (len % 4); tmp++) {
- dest[len - tmp - 1] = source1[len - tmp - 1] ^ source2[len - tmp - 1];
- }
-}
-
-//
// Get a random check block of block_size from our data and aux blocks and append it to chunk at index.
//
static void
@@ -313,9 +313,7 @@
char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
- for (tmp3 = 0; tmp3 < block_size; tmp3++) {
- xor_sum[tmp3] = xor_sum[tmp3] ^ this_value[tmp3];
- }
+ xor_string(xor_sum, xor_sum, this_value, block_size);
} else {
missing_block = block_nr;
}
From nobody at rubyforge.org Wed Dec 27 12:13:35 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 12:13:35 -0500 (EST)
Subject: [Archipelago-submits] [157] trunk/oneliner/ext/superstring_ext.c:
made fill_aux_blocks use xor_string
Message-ID: <20061227171335.68B6352415B1@rubyforge.org>
Revision: 157
Author: zond
Date: 2006-12-27 12:13:35 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
made fill_aux_blocks use xor_string
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:12:32 UTC (rev 156)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:13:35 UTC (rev 157)
@@ -351,9 +351,7 @@
for (tmp2 = 0; tmp2 < q; tmp2++) {
int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
if (initialized_aux_blocks[aux_block_nr]) {
- for (tmp3 = 0; tmp3 < block_size; tmp3++) {
- aux_blocks[(aux_block_nr * block_size) + tmp3] = RSTRING(self)->ptr[tmp + tmp3] ^ aux_blocks[(aux_block_nr * block_size) + tmp3];
- }
+ xor_string(aux_blocks + (aux_block_nr * block_size), aux_blocks + (aux_block_nr * block_size), RSTRING(self)->ptr + tmp, block_size);
} else {
memcpy(aux_blocks + (aux_block_nr * block_size), RSTRING(self)->ptr + tmp, block_size);
initialized_aux_blocks[aux_block_nr] = 1;
From nobody at rubyforge.org Wed Dec 27 12:14:13 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 12:14:13 -0500 (EST)
Subject: [Archipelago-submits] [158] trunk/oneliner/ext/superstring_ext.c:
made aux_decode use xor_string
Message-ID: <20061227171413.1B0A852415B2@rubyforge.org>
Revision: 158
Author: zond
Date: 2006-12-27 12:14:12 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
made aux_decode use xor_string
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:13:35 UTC (rev 157)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:14:12 UTC (rev 158)
@@ -500,9 +500,7 @@
char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
- for (tmp3 = 0; tmp3 < block_size; tmp3++) {
- xor_sum[tmp3] = xor_sum[tmp3] ^ this_value[tmp3];
- }
+ xor_string(xor_sum, xor_sum, this_value, block_size);
} else {
missing_block = block_nr;
}
From nobody at rubyforge.org Wed Dec 27 14:14:46 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 14:14:46 -0500 (EST)
Subject: [Archipelago-submits] [159] trunk/oneliner: lots of small fixes on
the way to block size agnosticism
Message-ID: <20061227191446.E895A52417C3@rubyforge.org>
Revision: 159
Author: zond
Date: 2006-12-27 14:14:46 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
lots of small fixes on the way to block size agnosticism
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 17:14:12 UTC (rev 158)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 19:14:46 UTC (rev 159)
@@ -44,18 +44,18 @@
AES_set_encrypt_key((unsigned char *) RANDOMNESS_AES_KEY, 128, &key);
AES_encrypt((unsigned char *) ctx + 4, (unsigned char *) ctx + 4, &key);
- ( (int *) ctx )[0] = 0;
+ ( (unsigned int *) ctx )[0] = 0;
}
//
// Get the int at the counter of ctx in the buffer of ctx.
//
-static int
+static unsigned int
aes_random(char *ctx)
{
- int *int_ctx = (int *) ctx;
+ unsigned int *int_ctx = (unsigned int *) ctx;
if (int_ctx[0] < (RANDOMNESS_BUFFER_SIZE / 4)) {
- int return_value = int_ctx[int_ctx[0] + 1];
+ unsigned int return_value = int_ctx[int_ctx[0] + 1];
int_ctx[0]++;
return return_value;
} else {
@@ -69,12 +69,12 @@
// Fill the buffer of ctx with seed and randomize it.
//
static void
-aes_seed_context(char *ctx, int seed)
+aes_seed_context(char *ctx, unsigned int seed)
{
- int tmp;
+ unsigned int tmp;
for (tmp = 1; tmp < ( (RANDOMNESS_BUFFER_SIZE / 4) + 1 ); tmp++) {
- ( (int *) ctx )[tmp] = seed;
+ ( (unsigned int *) ctx )[tmp] = seed;
}
aes_randomize_context(ctx);
}
@@ -93,21 +93,20 @@
//
#define SEED(ctx, s) aes_seed_context(ctx, s)
#define RAND(ctx) (((double) ((unsigned int) aes_random(ctx)))/((double)UINT_MAX))
-#define RANDOM(ctx, n) (( (unsigned int) aes_random(ctx)) % (n))
+#define RANDOM(ctx, n) (( (unsigned int) aes_random(ctx) ) % n)
#define N_DATA_BLOCKS(self, block_size) (RSTRING(self)->len / block_size)
#define N_AUX_BLOCKS(aux_blocks, block_size) (RSTRING(aux_blocks)->len / block_size)
#define N_BLOCKS(self, aux_blocks, block_size) ((RSTRING(self)->len + RSTRING(aux_blocks)->len) / block_size)
-
//
// Make dest into source1 ^ source2.
//
static void
xor_string(char *dest, char *source1, char *source2, int len)
{
- int tmp;
+ unsigned int tmp;
for (tmp = 0; tmp < (len / 4); tmp++) {
- ( (int *) dest )[tmp] = ( (int *) source1 )[tmp] ^ ( (int *) source2 )[tmp];
+ ( (unsigned int *) dest )[tmp] = ( (unsigned int *) source1 )[tmp] ^ ( (unsigned int *) source2 )[tmp];
}
for (tmp = 0; tmp < (len % 4); tmp++) {
dest[len - tmp - 1] = source1[len - tmp - 1] ^ source2[len - tmp - 1];
@@ -117,10 +116,10 @@
//
// Get a random degree for a check block.
//
-static int
-get_degree(int size, VALUE rnd_ctx)
+static unsigned int
+get_degree(unsigned int size, VALUE rnd_ctx)
{
- int rval = 1;
+ unsigned int rval = 1;
double d = RAND(RSTRING(rnd_ctx)->ptr) - P[rval];
while (d > 0.0) {
rval ++;
@@ -136,9 +135,9 @@
// Return whether the block_number is known according to the decode_status.
//
static char
-get_is_known(VALUE decode_status, int block_number)
+get_is_known(VALUE decode_status, unsigned int block_number)
{
- int byte_in_status = block_number / 8;
+ unsigned int byte_in_status = block_number / 8;
char bit_in_byte = 1 << (block_number % 8);
return ((RSTRING(decode_status)->ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
}
@@ -147,9 +146,9 @@
// Set that the block_number is known according to the decode_status.
//
static void
-set_is_known(VALUE decode_status, int block_number)
+set_is_known(VALUE decode_status, unsigned int block_number)
{
- int byte_in_status = block_number / 8;
+ unsigned int byte_in_status = block_number / 8;
char bit_in_byte = 1 << (block_number % 8);
rb_str_modify(decode_status);
RSTRING(decode_status)->ptr[byte_in_status] = RSTRING(decode_status)->ptr[byte_in_status] | bit_in_byte;
@@ -159,7 +158,7 @@
// Set the data or aux block with index to be value, and set it as known.
//
static void
-set_value(VALUE aux_blocks, int index, char *value, VALUE self, VALUE decode_status, int block_size)
+set_value(VALUE aux_blocks, unsigned int index, char *value, VALUE self, VALUE decode_status, unsigned int block_size)
{
if ((index * block_size) < RSTRING(self)->len) {
rb_str_modify(self);
@@ -176,7 +175,7 @@
// Get the value at index from data or aux blocks.
//
static char*
-get_value(VALUE aux_blocks, int index, VALUE self, int block_size)
+get_value(VALUE aux_blocks, unsigned int index, VALUE self, unsigned int block_size)
{
if ((index * block_size) < RSTRING(self)->len) {
return RSTRING(self)->ptr + (index * block_size);
@@ -189,26 +188,31 @@
// Get a random check block of block_size from our data and aux blocks and append it to chunk at index.
//
static void
-append_check_block(VALUE self, int seed, int index, VALUE aux_blocks, VALUE rnd_ctx, char *chunk, int block_size)
+append_check_block(VALUE self, unsigned int seed, unsigned int index, VALUE aux_blocks, VALUE rnd_ctx, char *chunk, unsigned int block_size)
{
- int degree;
- int empty_block = 1;
- int tmp;
+ unsigned int degree;
+ unsigned int empty_block = 1;
+ unsigned int tmp;
+ printf("creating check block at %d:", index);
// Find [degree] blocks.
for (degree = get_degree(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
- int block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
+ unsigned int block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
char *found_block = get_value(aux_blocks, block_number, self, block_size);
+ printf(" %d(%d %d)", block_number, found_block[0], found_block[1]);
+
// Create the block by xoring.
if (empty_block) {
memcpy(chunk + (index * block_size), found_block, block_size);
empty_block = 0;
} else {
- xor_string(chunk + index, chunk + index, found_block, block_size);
+ xor_string(chunk + (index * block_size), chunk + (index * block_size), found_block, block_size);
}
}
+ printf(" => (%d %d)\n", chunk[index * block_size], chunk[index * block_size + 1]);
+ fflush(NULL);
}
//
@@ -227,21 +231,21 @@
_aes_seed_context(VALUE self, VALUE _ctx, VALUE _s)
{
char * ctx = STR2CSTR(_ctx);
- int s = NUM2INT(_s);
+ unsigned int s = FIX2INT(_s);
aes_seed_context(ctx, s);
return Qnil;
}
//
-// Get a random int from the context, mainly for testing purposes.
+// Get a random unsigned int from the context, mainly for testing purposes.
//
static VALUE
_aes_random(VALUE self, VALUE _ctx)
{
char * ctx = STR2CSTR(_ctx);
- return INT2NUM(aes_random(ctx));
+ return INT2FIX(aes_random(ctx));
}
//
@@ -262,9 +266,9 @@
_macro_random(VALUE self, VALUE _ctx, VALUE _lim)
{
char * ctx = STR2CSTR(_ctx);
- int lim = NUM2INT(_lim);
+ unsigned int lim = FIX2INT(_lim);
- return INT2NUM(RANDOM(ctx, lim));
+ return INT2FIX(RANDOM(ctx, lim));
}
//
@@ -273,43 +277,42 @@
// Returns whether the decoding produced any new blocks.
//
static VALUE
-_decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks, VALUE block_size_value)
+_decode_chunk(VALUE self, VALUE _chunk, VALUE _decode_status, VALUE _aux_blocks, VALUE block_size_value, VALUE rnd_ctx)
{
VALUE chunk = (_chunk);
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
- int seed = ( (int *) RSTRING(chunk)->ptr )[0];
- int size = ( (int *) RSTRING(chunk)->ptr )[1];
- int tmp;
+ unsigned int seed = ( (unsigned int *) RSTRING(chunk)->ptr )[0];
+ unsigned int size = ( (unsigned int *) RSTRING(chunk)->ptr )[1];
+ unsigned int tmp;
char got_new_block = 0;
- VALUE rnd_ctx = get_aes_context();
- int block_size = NUM2INT(block_size_value);
+ unsigned int block_size = FIX2INT(block_size_value);
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp = tmp + block_size) {
- int degree;
+ unsigned int degree;
degree = get_degree(size, rnd_ctx);
if (degree == 1) {
- int block_nr;
+ unsigned int block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
}
} else {
- int missing_blocks;
- int missing_block = 0;
- int tmp2;
+ unsigned int missing_blocks;
+ unsigned int missing_block = 0;
+ unsigned int tmp2;
char xor_sum[block_size];
memcpy(xor_sum, RSTRING(chunk)->ptr + tmp, block_size);
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
- int block_nr;
+ unsigned int block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
if (get_is_known(decode_status, block_nr)) {
- int tmp3;
+ unsigned int tmp3;
char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
@@ -332,31 +335,35 @@
// Create the @_aux_blocks instance attribute with _size blocks and the given _q value.
//
static VALUE
-_fill_aux_blocks(VALUE self, VALUE _size, VALUE _q, VALUE block_size_value)
+_fill_aux_blocks(VALUE self, VALUE _size, VALUE _q, VALUE block_size_value, VALUE rnd_ctx)
{
- int size = NUM2INT(_size);
- int q = NUM2INT(_q);
- int block_size = NUM2INT(block_size_value);
+ unsigned int size = FIX2INT(_size);
+ unsigned int q = FIX2INT(_q);
+ unsigned int block_size = FIX2INT(block_size_value);
char aux_blocks[size * block_size];
char initialized_aux_blocks[size];
- int tmp, tmp2, tmp3;
- VALUE rnd_ctx = get_aes_context();
+ unsigned int tmp, tmp2, tmp3;
- for (tmp = 0; tmp < size; tmp++)
+ for (tmp = 0; tmp < (size * block_size); tmp++)
initialized_aux_blocks[tmp] = 0;
SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
for (tmp = 0; tmp < RSTRING(self)->len; tmp = tmp + block_size) {
+ printf("creating aux block for block at %d(%d %d):", tmp, RSTRING(self)->ptr[tmp], RSTRING(self)->ptr[tmp + 1]);
for (tmp2 = 0; tmp2 < q; tmp2++) {
- int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
+ unsigned int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
+ printf(" %d", aux_block_nr);
if (initialized_aux_blocks[aux_block_nr]) {
xor_string(aux_blocks + (aux_block_nr * block_size), aux_blocks + (aux_block_nr * block_size), RSTRING(self)->ptr + tmp, block_size);
} else {
memcpy(aux_blocks + (aux_block_nr * block_size), RSTRING(self)->ptr + tmp, block_size);
initialized_aux_blocks[aux_block_nr] = 1;
}
+ printf("=>(%d %d)", aux_blocks[aux_block_nr * block_size], aux_blocks[aux_block_nr * block_size + 1]);
}
+ printf("\n");
+ fflush(NULL);
}
rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size * block_size));
return Qnil;
@@ -366,23 +373,22 @@
// Return a chunk of check blocks that is _chunk_size big.
//
static VALUE
-_get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks, VALUE block_size_value)
+_get_chunk(VALUE self, VALUE _chunk_size, VALUE _aux_blocks, VALUE block_size_value, VALUE rnd_ctx)
{
- int chunk_size = NUM2INT(_chunk_size);
+ unsigned int chunk_size = FIX2INT(_chunk_size);
VALUE aux_blocks = (_aux_blocks);
- int block_size = NUM2INT(block_size_value);
+ unsigned int block_size = FIX2INT(block_size_value);
unsigned int tmp;
- int seed;
+ unsigned int seed;
struct timeval tmp_timeval;
char chunk[chunk_size];
- VALUE rnd_ctx = get_aes_context();
gettimeofday(&tmp_timeval, NULL);
srandom(tmp_timeval.tv_usec);
seed = random();
- ( (int *) chunk) [0] = seed;
- ( (int *) chunk) [1] = RSTRING(self)->len;
+ ( (unsigned int *) chunk) [0] = seed;
+ ( (unsigned int *) chunk) [1] = RSTRING(self)->len;
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < chunk_size; tmp = tmp + block_size) {
append_check_block(self, seed, tmp, aux_blocks, rnd_ctx, chunk, block_size);
@@ -395,42 +401,40 @@
// Create the instance attribute @_aux_hash containing the structure of our aux blocks.
//
static VALUE
-_fill_aux_hash(VALUE self, VALUE _q, VALUE _size, VALUE block_size_value)
+_fill_aux_hash(VALUE self, VALUE _q, VALUE _size, VALUE block_size_value, VALUE rnd_ctx)
{
- int q = NUM2INT(_q);
- int size = NUM2INT(_size);
- int block_size = NUM2INT(block_size_value);
-
- int tmp, tmp2;
+ unsigned int q = FIX2INT(_q);
+ unsigned int size = FIX2INT(_size);
+ unsigned int block_size = FIX2INT(block_size_value);
+ unsigned int tmp, tmp2;
VALUE aux_ary = rb_ary_new();
VALUE set_func = rb_intern("[]=");
VALUE get_func = rb_intern("[]");
VALUE push_func = rb_intern("<<");
- VALUE size_func = rb_intern("size");
- VALUE rnd_ctx = get_aes_context();
SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
- for (tmp = 0; tmp < RSTRING(self)->len; tmp++) {
+
+ for (tmp = 0; tmp < (RSTRING(self)->len / block_size); tmp++) {
for (tmp2 = 0; tmp2 < q; tmp2++) {
- int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
+ unsigned int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
VALUE data_blocks_for_this_aux_block;
- if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(aux_block_nr))) == Qnil)
- rb_funcall(aux_ary, set_func, 2, INT2NUM(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
- rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2NUM(tmp));
+ if ((data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2FIX(aux_block_nr))) == Qnil)
+ rb_funcall(aux_ary, set_func, 2, INT2FIX(aux_block_nr), (data_blocks_for_this_aux_block = rb_ary_new()));
+ rb_funcall(data_blocks_for_this_aux_block, push_func, 1, INT2FIX(tmp));
}
}
for (tmp = 0; tmp < size; tmp++) {
- VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2NUM(tmp));
- int number_of_data_blocks = NUM2INT(rb_funcall(data_blocks_for_this_aux_block, size_func, 0));
+ VALUE data_blocks_for_this_aux_block = rb_funcall(aux_ary, get_func, 1, INT2FIX(tmp));
+ unsigned int number_of_data_blocks = RARRAY(data_blocks_for_this_aux_block)->len;
VALUE data_block_string = rb_str_new(0, number_of_data_blocks * 4);
for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
rb_str_modify(data_block_string);
- ( (int *) RSTRING(data_block_string)->ptr )[tmp2] = (int) NUM2INT(rb_funcall(data_blocks_for_this_aux_block,
+ ( (unsigned int *) RSTRING(data_block_string)->ptr )[tmp2] = (unsigned int) FIX2INT(rb_funcall(data_blocks_for_this_aux_block,
get_func,
1,
- INT2NUM(tmp2)));
+ INT2FIX(tmp2)));
}
- rb_funcall(aux_ary, set_func, 2, INT2NUM(tmp), data_block_string);
+ rb_funcall(aux_ary, set_func, 2, INT2FIX(tmp), data_block_string);
}
rb_ivar_set(self, rb_intern("@_aux_hash"), aux_ary);
return Qnil;
@@ -442,10 +446,10 @@
static VALUE
_oneline_done(VALUE self, VALUE decode_status, VALUE block_size_value)
{
- int block_size = NUM2INT(block_size_value);
- int tmp;
- int number_of_ints = RSTRING(self)->len / 32;
- int number_of_chars = RSTRING(self)->len / 8;
+ unsigned int block_size = FIX2INT(block_size_value);
+ unsigned int tmp;
+ unsigned int number_of_ints = RSTRING(self)->len / 32;
+ unsigned int number_of_chars = RSTRING(self)->len / 8;
if (decode_status == Qnil)
return (Qfalse);
@@ -470,33 +474,33 @@
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
VALUE aux_hash = (_aux_hash);
- int block_size = NUM2INT(block_size_value);
+ unsigned int block_size = FIX2INT(block_size_value);
- int tmp;
+ unsigned int tmp;
char got_new_block = 0;
VALUE get_func = rb_intern("[]");
for (tmp = 0; tmp < RSTRING(aux_blocks)->len; tmp = tmp + block_size) {
if (get_is_known(decode_status, (RSTRING(self)->len + tmp) / block_size)) {
- VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2NUM(tmp));
+ VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2FIX(tmp));
if (RSTRING(data_block_string)->len == 4) {
- int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[0];
+ unsigned int block_nr = ( (unsigned int *) RSTRING(data_block_string)->ptr )[0];
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
} else {
}
} else {
- int missing_blocks;
- int missing_block = 0;
- int tmp2;
+ unsigned int missing_blocks;
+ unsigned int missing_block = 0;
+ unsigned int tmp2;
char xor_sum[block_size];
memcpy(xor_sum, RSTRING(aux_blocks)->ptr + tmp, block_size);
for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
- int block_nr = ( (int *) RSTRING(data_block_string)->ptr )[tmp2];
+ unsigned int block_nr = ( (unsigned int *) RSTRING(data_block_string)->ptr )[tmp2];
if (get_is_known(decode_status, block_nr)) {
- int tmp3;
+ unsigned int tmp3;
char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
@@ -527,11 +531,11 @@
rb_define_method(c, "_aes_random", (VALUE(*)(ANYARGS))_aes_random, 1);
rb_define_method(c, "_aes_seed_context", (VALUE(*)(ANYARGS))_aes_seed_context, 2);
rb_define_method(c, "_aux_decode", (VALUE(*)(ANYARGS))_aux_decode, 4);
- rb_define_method(c, "_decode_chunk", (VALUE(*)(ANYARGS))_decode_chunk, 4);
- rb_define_method(c, "_fill_aux_blocks", (VALUE(*)(ANYARGS))_fill_aux_blocks, 3);
- rb_define_method(c, "_fill_aux_hash", (VALUE(*)(ANYARGS))_fill_aux_hash, 3);
+ rb_define_method(c, "_decode_chunk", (VALUE(*)(ANYARGS))_decode_chunk, 5);
+ rb_define_method(c, "_fill_aux_blocks", (VALUE(*)(ANYARGS))_fill_aux_blocks, 4);
+ rb_define_method(c, "_fill_aux_hash", (VALUE(*)(ANYARGS))_fill_aux_hash, 4);
rb_define_method(c, "_get_aes_context", (VALUE(*)(ANYARGS))_get_aes_context, 0);
- rb_define_method(c, "_get_chunk", (VALUE(*)(ANYARGS))_get_chunk, 3);
+ rb_define_method(c, "_get_chunk", (VALUE(*)(ANYARGS))_get_chunk, 4);
rb_define_method(c, "_macro_rand", (VALUE(*)(ANYARGS))_macro_rand, 1);
rb_define_method(c, "_macro_random", (VALUE(*)(ANYARGS))_macro_random, 2);
rb_define_method(c, "_oneline_done", (VALUE(*)(ANYARGS))_oneline_done, 2);
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 17:14:12 UTC (rev 158)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 19:14:46 UTC (rev 159)
@@ -33,9 +33,11 @@
# result in errors.
#
def oneline_encode!(chunk_size)
- ensure_aux_blocks
- ensure_encode_size(get_block_size)
- return _get_chunk(chunk_size, @_aux_blocks, get_block_size)
+ ctx = _get_aes_context
+ block_size = get_block_size
+ ensure_aux_blocks(ctx, block_size)
+ ensure_encode_size(block_size)
+ return _get_chunk(chunk_size, @_aux_blocks, block_size, ctx)
end
#
@@ -57,12 +59,13 @@
@_known_chunks ||= []
@_aux_blocks ||= "\000" * get_aux_blocks
- found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks, block_size)
- do_decode(block_size) if found_new_block
+ ctx = _get_aes_context
+ found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks, block_size, ctx)
+ do_decode(block_size, ctx) if found_new_block
@_known_chunks.unshift(chunk)
- nil while do_decode(block_size)
+ nil while do_decode(block_size, ctx)
return oneline_done(block_size)
end
@@ -117,12 +120,12 @@
(self.size * (Q * E * 0.55)).ceil
end
- def do_decode(block_size)
+ def do_decode(block_size, ctx)
found_new_block = false
@_known_chunks.each do |known_chunk|
- found_new_block = _decode_chunk(known_chunk, @_decode_status, @_aux_blocks, block_size) || found_new_block
+ found_new_block = _decode_chunk(known_chunk, @_decode_status, @_aux_blocks, block_size, ctx) || found_new_block
end
- ensure_aux_hash
+ ensure_aux_hash(block_size, ctx)
found_new_block = _aux_decode(@_decode_status, @_aux_blocks, @_aux_hash, block_size) || found_new_block
return found_new_block
end
@@ -140,14 +143,14 @@
end
end
- def ensure_aux_blocks
+ def ensure_aux_blocks(ctx, block_size)
@_aux_blocks ||= nil
- _fill_aux_blocks(get_aux_blocks, Q, get_block_size) unless @_aux_blocks
+ _fill_aux_blocks(get_aux_blocks, Q, block_size, ctx) unless @_aux_blocks
end
- def ensure_aux_hash
+ def ensure_aux_hash(block_size, ctx)
@_aux_hash ||= nil
- _fill_aux_hash(Q, get_aux_blocks, get_block_size) unless @_aux_hash
+ _fill_aux_hash(Q, get_aux_blocks, block_size, ctx) unless @_aux_hash
end
end
From nobody at rubyforge.org Wed Dec 27 18:33:39 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 18:33:39 -0500 (EST)
Subject: [Archipelago-submits] [160] trunk/oneliner: one more step towards
block size agnosticism
Message-ID: <20061227233339.12D5E524187D@rubyforge.org>
Revision: 160
Author: zond
Date: 2006-12-27 18:33:38 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
one more step towards block size agnosticism
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 19:14:46 UTC (rev 159)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-27 23:33:38 UTC (rev 160)
@@ -195,23 +195,24 @@
unsigned int tmp;
printf("creating check block at %d:", index);
-
+ fflush(NULL);
// Find [degree] blocks.
for (degree = get_degree(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
unsigned int block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
char *found_block = get_value(aux_blocks, block_number, self, block_size);
printf(" %d(%d %d)", block_number, found_block[0], found_block[1]);
-
+ fflush(NULL);
+
// Create the block by xoring.
if (empty_block) {
- memcpy(chunk + (index * block_size), found_block, block_size);
+ memcpy(chunk + index, found_block, block_size);
empty_block = 0;
} else {
- xor_string(chunk + (index * block_size), chunk + (index * block_size), found_block, block_size);
+ xor_string(chunk + index, chunk + index, found_block, block_size);
}
}
- printf(" => (%d %d)\n", chunk[index * block_size], chunk[index * block_size + 1]);
+ printf(" => (%d %d)\n", chunk[index], chunk[index + 1]);
fflush(NULL);
}
@@ -287,18 +288,24 @@
unsigned int tmp;
char got_new_block = 0;
unsigned int block_size = FIX2INT(block_size_value);
-
+
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp = tmp + block_size) {
unsigned int degree;
+
+ printf("looking at block at %d:", tmp);
degree = get_degree(size, rnd_ctx);
if (degree == 1) {
unsigned int block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
+ printf(" [%d]", block_nr);
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
+ printf(" => (%d, %d)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
+ } else {
+ printf(" = (%d, %d)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
}
} else {
unsigned int missing_blocks;
@@ -307,25 +314,30 @@
char xor_sum[block_size];
memcpy(xor_sum, RSTRING(chunk)->ptr + tmp, block_size);
-
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
unsigned int block_nr;
block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
+ printf(" [%d]", block_nr);
if (get_is_known(decode_status, block_nr)) {
unsigned int tmp3;
char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
xor_string(xor_sum, xor_sum, this_value, block_size);
+ printf("!");
} else {
+ printf("?");
missing_block = block_nr;
}
}
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
+ printf(" => [%d](%d %d)", missing_block, xor_sum[0], xor_sum[1]);
}
}
+ printf("\n");
+ fflush(NULL);
}
return (got_new_block ? Qtrue : Qfalse);
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 19:14:46 UTC (rev 159)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 23:33:38 UTC (rev 160)
@@ -77,6 +77,7 @@
if @_decode_status
if _oneline_done(@_decode_status, block_size)
slice!(@_original_size..-1)
+ true
else
false
end
From nobody at rubyforge.org Wed Dec 27 19:48:47 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 19:48:47 -0500 (EST)
Subject: [Archipelago-submits] [161] trunk/oneliner: more comments,
and fixed a potential problem in decode_chunk
Message-ID: <20061228004847.5A4C25241886@rubyforge.org>
Revision: 161
Author: zond
Date: 2006-12-27 19:48:46 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
more comments, and fixed a potential problem in decode_chunk
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-27 23:33:38 UTC (rev 160)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-28 00:48:46 UTC (rev 161)
@@ -188,7 +188,13 @@
// Get a random check block of block_size from our data and aux blocks and append it to chunk at index.
//
static void
-append_check_block(VALUE self, unsigned int seed, unsigned int index, VALUE aux_blocks, VALUE rnd_ctx, char *chunk, unsigned int block_size)
+append_check_block(VALUE self,
+ unsigned int seed,
+ unsigned int index,
+ VALUE aux_blocks,
+ VALUE rnd_ctx,
+ char *chunk,
+ unsigned int block_size)
{
unsigned int degree;
unsigned int empty_block = 1;
@@ -284,7 +290,6 @@
VALUE decode_status = (_decode_status);
VALUE aux_blocks = (_aux_blocks);
unsigned int seed = ( (unsigned int *) RSTRING(chunk)->ptr )[0];
- unsigned int size = ( (unsigned int *) RSTRING(chunk)->ptr )[1];
unsigned int tmp;
char got_new_block = 0;
unsigned int block_size = FIX2INT(block_size_value);
@@ -293,12 +298,12 @@
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp = tmp + block_size) {
unsigned int degree;
- printf("looking at block at %d:", tmp);
+ printf("looking at block at %d(%d %d):", tmp, RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
- degree = get_degree(size, rnd_ctx);
+ degree = get_degree(RSTRING(self)->len, rnd_ctx);
if (degree == 1) {
unsigned int block_nr;
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (RSTRING(self)->len + RSTRING(aux_blocks)->len) / block_size);
printf(" [%d]", block_nr);
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
@@ -316,7 +321,7 @@
memcpy(xor_sum, RSTRING(chunk)->ptr + tmp, block_size);
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
unsigned int block_nr;
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (size + RSTRING(aux_blocks)->len) / block_size);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (RSTRING(self)->len + RSTRING(aux_blocks)->len) / block_size);
printf(" [%d]", block_nr);
if (get_is_known(decode_status, block_nr)) {
unsigned int tmp3;
@@ -324,7 +329,7 @@
missing_blocks--;
xor_string(xor_sum, xor_sum, this_value, block_size);
- printf("!");
+ printf("!(%d %d)", xor_sum[0], xor_sum[1]);
} else {
printf("?");
missing_block = block_nr;
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-27 23:33:38 UTC (rev 160)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-28 00:48:46 UTC (rev 161)
@@ -61,7 +61,7 @@
ctx = _get_aes_context
found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks, block_size, ctx)
- do_decode(block_size, ctx) if found_new_block
+ found_new_block = do_decode(block_size, ctx)
@_known_chunks.unshift(chunk)
From nobody at rubyforge.org Wed Dec 27 19:51:17 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Wed, 27 Dec 2006 19:51:17 -0500 (EST)
Subject: [Archipelago-submits] [162]
trunk/oneliner/lib/oneliner/superstring.rb: improved
efficiency in oneline_decode slightly
Message-ID: <20061228005117.10558524189F@rubyforge.org>
Revision: 162
Author: zond
Date: 2006-12-27 19:51:16 -0500 (Wed, 27 Dec 2006)
Log Message:
-----------
improved efficiency in oneline_decode slightly
Modified Paths:
--------------
trunk/oneliner/lib/oneliner/superstring.rb
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-28 00:48:46 UTC (rev 161)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-28 00:51:16 UTC (rev 162)
@@ -61,11 +61,12 @@
ctx = _get_aes_context
found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks, block_size, ctx)
- found_new_block = do_decode(block_size, ctx)
@_known_chunks.unshift(chunk)
- nil while do_decode(block_size, ctx)
+ if found_new_block
+ nil while do_decode(block_size, ctx)
+ end
return oneline_done(block_size)
end
From nobody at rubyforge.org Thu Dec 28 10:38:55 2006
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Thu, 28 Dec 2006 10:38:55 -0500 (EST)
Subject: [Archipelago-submits] [163] trunk/oneliner: now with almost working
variable block size, but with crap redundancy-performance :/
Message-ID: <20061228153856.0B5995241281@rubyforge.org>
Revision: 163
Author: zond
Date: 2006-12-28 10:38:55 -0500 (Thu, 28 Dec 2006)
Log Message:
-----------
now with almost working variable block size, but with crap redundancy-performance :/
Modified Paths:
--------------
trunk/oneliner/ext/superstring_ext.c
trunk/oneliner/lib/oneliner/superstring.rb
trunk/oneliner/tests/superstring_benchmark.rb
Modified: trunk/oneliner/ext/superstring_ext.c
===================================================================
--- trunk/oneliner/ext/superstring_ext.c 2006-12-28 00:51:16 UTC (rev 162)
+++ trunk/oneliner/ext/superstring_ext.c 2006-12-28 15:38:55 UTC (rev 163)
@@ -139,7 +139,8 @@
{
unsigned int byte_in_status = block_number / 8;
char bit_in_byte = 1 << (block_number % 8);
- return ((RSTRING(decode_status)->ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
+ char rval = ((RSTRING(decode_status)->ptr[byte_in_status]) & bit_in_byte) == bit_in_byte;
+ return rval;
}
//
@@ -189,7 +190,6 @@
//
static void
append_check_block(VALUE self,
- unsigned int seed,
unsigned int index,
VALUE aux_blocks,
VALUE rnd_ctx,
@@ -200,15 +200,15 @@
unsigned int empty_block = 1;
unsigned int tmp;
- printf("creating check block at %d:", index);
- fflush(NULL);
+ //DEBUGprintf("creating check block at %u:", index);
+ //DEBUGfflush(NULL);
// Find [degree] blocks.
for (degree = get_degree(RSTRING(self)->len, rnd_ctx); degree > 0; degree--) {
unsigned int block_number = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
char *found_block = get_value(aux_blocks, block_number, self, block_size);
- printf(" %d(%d %d)", block_number, found_block[0], found_block[1]);
- fflush(NULL);
+ //DEBUGprintf(" %u(%hhu %hhu)", block_number, found_block[0], found_block[1]);
+ //DEBUGfflush(NULL);
// Create the block by xoring.
if (empty_block) {
@@ -218,8 +218,8 @@
xor_string(chunk + index, chunk + index, found_block, block_size);
}
}
- printf(" => (%d %d)\n", chunk[index], chunk[index + 1]);
- fflush(NULL);
+ //DEBUGprintf(" => (%hhu %hhu)\n", chunk[index], chunk[index + 1]);
+ //DEBUGfflush(NULL);
}
//
@@ -298,19 +298,19 @@
for (tmp = 8; tmp < RSTRING(chunk)->len; tmp = tmp + block_size) {
unsigned int degree;
- printf("looking at block at %d(%d %d):", tmp, RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
+ //DEBUGprintf("looking at block at %u(%hhu %hhu):", tmp, RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
degree = get_degree(RSTRING(self)->len, rnd_ctx);
if (degree == 1) {
unsigned int block_nr;
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (RSTRING(self)->len + RSTRING(aux_blocks)->len) / block_size);
- printf(" [%d]", block_nr);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
+ //DEBUGprintf(" [%u]", block_nr);
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(chunk)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
- printf(" => (%d, %d)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
+ //DEBUGprintf(" => (%hhu %hhu)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
} else {
- printf(" = (%d, %d)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
+ //DEBUGprintf(" = (%hhu %hhu)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
}
} else {
unsigned int missing_blocks;
@@ -321,28 +321,28 @@
memcpy(xor_sum, RSTRING(chunk)->ptr + tmp, block_size);
for (missing_blocks = tmp2 = degree; tmp2 > 0; tmp2--) {
unsigned int block_nr;
- block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, (RSTRING(self)->len + RSTRING(aux_blocks)->len) / block_size);
- printf(" [%d]", block_nr);
+ block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, N_BLOCKS(self, aux_blocks, block_size));
+ //DEBUGprintf(" [%u]", block_nr);
if (get_is_known(decode_status, block_nr)) {
unsigned int tmp3;
char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
xor_string(xor_sum, xor_sum, this_value, block_size);
- printf("!(%d %d)", xor_sum[0], xor_sum[1]);
+ //DEBUGprintf("!(%hhu %hhu)", xor_sum[0], xor_sum[1]);
} else {
- printf("?");
+ //DEBUGprintf("?");
missing_block = block_nr;
}
}
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
- printf(" => [%d](%d %d)", missing_block, xor_sum[0], xor_sum[1]);
+ //DEBUGprintf(" => [%u](%hhu %hhu)", missing_block, xor_sum[0], xor_sum[1]);
}
}
- printf("\n");
- fflush(NULL);
+ //DEBUGprintf("\n");
+ //DEBUGfflush(NULL);
}
return (got_new_block ? Qtrue : Qfalse);
@@ -367,20 +367,20 @@
SEED(RSTRING(rnd_ctx)->ptr, RSTRING(self)->len);
for (tmp = 0; tmp < RSTRING(self)->len; tmp = tmp + block_size) {
- printf("creating aux block for block at %d(%d %d):", tmp, RSTRING(self)->ptr[tmp], RSTRING(self)->ptr[tmp + 1]);
+ //DEBUGprintf("creating aux block for block at %u(%hhu %hhu):", tmp, RSTRING(self)->ptr[tmp], RSTRING(self)->ptr[tmp + 1]);
for (tmp2 = 0; tmp2 < q; tmp2++) {
unsigned int aux_block_nr = RANDOM(RSTRING(rnd_ctx)->ptr, size);
- printf(" %d", aux_block_nr);
+ //DEBUGprintf(" %u", aux_block_nr);
if (initialized_aux_blocks[aux_block_nr]) {
xor_string(aux_blocks + (aux_block_nr * block_size), aux_blocks + (aux_block_nr * block_size), RSTRING(self)->ptr + tmp, block_size);
} else {
memcpy(aux_blocks + (aux_block_nr * block_size), RSTRING(self)->ptr + tmp, block_size);
initialized_aux_blocks[aux_block_nr] = 1;
}
- printf("=>(%d %d)", aux_blocks[aux_block_nr * block_size], aux_blocks[aux_block_nr * block_size + 1]);
+ //DEBUGprintf("=>(%hhu %hhu)", aux_blocks[aux_block_nr * block_size], aux_blocks[aux_block_nr * block_size + 1]);
}
- printf("\n");
- fflush(NULL);
+ //DEBUGprintf("\n");
+ //DEBUGfflush(NULL);
}
rb_ivar_set(self, rb_intern("@_aux_blocks"), rb_str_new(aux_blocks, size * block_size));
return Qnil;
@@ -408,7 +408,7 @@
( (unsigned int *) chunk) [1] = RSTRING(self)->len;
SEED(RSTRING(rnd_ctx)->ptr, seed);
for (tmp = 8; tmp < chunk_size; tmp = tmp + block_size) {
- append_check_block(self, seed, tmp, aux_blocks, rnd_ctx, chunk, block_size);
+ append_check_block(self, tmp, aux_blocks, rnd_ctx, chunk, block_size);
}
return (rb_str_new(chunk, chunk_size));
@@ -447,9 +447,9 @@
for (tmp2 = 0; tmp2 < number_of_data_blocks; tmp2++) {
rb_str_modify(data_block_string);
( (unsigned int *) RSTRING(data_block_string)->ptr )[tmp2] = (unsigned int) FIX2INT(rb_funcall(data_blocks_for_this_aux_block,
- get_func,
- 1,
- INT2FIX(tmp2)));
+ get_func,
+ 1,
+ INT2FIX(tmp2)));
}
rb_funcall(aux_ary, set_func, 2, INT2FIX(tmp), data_block_string);
}
@@ -465,8 +465,9 @@
{
unsigned int block_size = FIX2INT(block_size_value);
unsigned int tmp;
- unsigned int number_of_ints = RSTRING(self)->len / 32;
- unsigned int number_of_chars = RSTRING(self)->len / 8;
+ unsigned int number_of_ints = (RSTRING(self)->len / block_size) / 32;
+ unsigned int number_of_chars = (RSTRING(self)->len / block_size) / 8;
+ unsigned int number_of_bits = (RSTRING(self)->len / block_size);
if (decode_status == Qnil)
return (Qfalse);
@@ -476,7 +477,7 @@
for (tmp = (number_of_ints * 4); tmp < number_of_chars; tmp++)
if (( (unsigned char) RSTRING(decode_status)->ptr[tmp] ) != UCHAR_MAX)
return (Qfalse);
- for (tmp = 0; tmp < ((RSTRING(self)->len / block_size) % 8); tmp++)
+ for (tmp = 0; tmp < (number_of_bits % 8); tmp++)
if (! (( (unsigned char) RSTRING(decode_status)->ptr[RSTRING(decode_status)->len - 1] ) & (1 << tmp)))
return (Qfalse);
return (Qtrue);
@@ -498,13 +499,17 @@
VALUE get_func = rb_intern("[]");
for (tmp = 0; tmp < RSTRING(aux_blocks)->len; tmp = tmp + block_size) {
if (get_is_known(decode_status, (RSTRING(self)->len + tmp) / block_size)) {
- VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2FIX(tmp));
+ //DEBUGprintf("looking at aux block at %u(%hhu %hhu):", tmp, RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
+ VALUE data_block_string = rb_funcall(aux_hash, get_func, 1, INT2FIX(tmp / block_size));
if (RSTRING(data_block_string)->len == 4) {
unsigned int block_nr = ( (unsigned int *) RSTRING(data_block_string)->ptr )[0];
+ //DEBUGprintf(" [%u]", block_nr);
if (!get_is_known(decode_status, block_nr)) {
set_value(aux_blocks, block_nr, RSTRING(aux_blocks)->ptr + tmp, self, decode_status, block_size);
got_new_block = 1;
+ //DEBUGprintf(" => (%hhu %hhu)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
} else {
+ //DEBUGprintf(" = (%hhu %hhu)", RSTRING(aux_blocks)->ptr[tmp], RSTRING(aux_blocks)->ptr[tmp + 1]);
}
} else {
unsigned int missing_blocks;
@@ -516,21 +521,27 @@
for (missing_blocks = (tmp2 = ((RSTRING(data_block_string)->len / 4) - 1)) + 1; tmp2 > -1; tmp2--) {
unsigned int block_nr = ( (unsigned int *) RSTRING(data_block_string)->ptr )[tmp2];
+ //DEBUGprintf(" [%u]", block_nr);
if (get_is_known(decode_status, block_nr)) {
unsigned int tmp3;
char *this_value = get_value(aux_blocks, block_nr, self, block_size);
missing_blocks--;
xor_string(xor_sum, xor_sum, this_value, block_size);
+ //DEBUGprintf("!(%hhu %hhu)", this_value[0], this_value[1]);
} else {
missing_block = block_nr;
- }
+ //DEBUGprintf("?");
+ }
}
if (missing_blocks == 1) {
set_value(aux_blocks, missing_block, xor_sum, self, decode_status, block_size);
got_new_block = 1;
+ //DEBUGprintf(" => [%u](%hhu %hhu)", xor_sum[0], xor_sum[1]);
}
}
+ //DEBUGprintf("\n");
+ //DEBUGfflush(NULL);
}
}
Modified: trunk/oneliner/lib/oneliner/superstring.rb
===================================================================
--- trunk/oneliner/lib/oneliner/superstring.rb 2006-12-28 00:51:16 UTC (rev 162)
+++ trunk/oneliner/lib/oneliner/superstring.rb 2006-12-28 15:38:55 UTC (rev 163)
@@ -55,9 +55,9 @@
block_size = get_block_size
ensure_encode_size(block_size)
- @_decode_status ||= "\000" * (((size + get_aux_blocks) / 8) + 1)
+ @_decode_status ||= "\000" * ((((size + get_aux_blocks) / block_size) / 8) + 1)
@_known_chunks ||= []
- @_aux_blocks ||= "\000" * get_aux_blocks
+ @_aux_blocks ||= "\000" * (get_aux_blocks * block_size)
ctx = _get_aes_context
found_new_block = _decode_chunk(chunk, @_decode_status, @_aux_blocks, block_size, ctx)
@@ -98,12 +98,12 @@
#
# Returns the relative decode status of this entire String.
#
- def decode_level
+ def decode_level(block_size = get_block_size)
ones = 0
decode_status[0..(size + @_aux_blocks.size)].split(//).each do |s|
ones += 1 if s == "1"
end
- ones.to_f / (size + @_aux_blocks.size).to_f
+ ones.to_f / ((size + @_aux_blocks.size) / block_size).to_f
end
private
Modified: trunk/oneliner/tests/superstring_benchmark.rb
===================================================================
--- trunk/oneliner/tests/superstring_benchmark.rb 2006-12-28 00:51:16 UTC (rev 162)
+++ trunk/oneliner/tests/superstring_benchmark.rb 2006-12-28 15:38:55 UTC (rev 163)
@@ -4,11 +4,6 @@
class SuperStringTest < Test::Unit::TestCase
def test_decoding
- puts "required for 16 blocks: #{required(100, 16)}"
- puts "required for 32 blocks: #{required(100, 32)}"
- puts "required for 64 blocks: #{required(100, 64)}"
- puts "required for 128 blocks: #{required(100, 128)}"
- puts "required for 256 blocks: #{required(100, 256)}"
puts "required for 512 blocks: #{required(100, 512)}"
puts "required for 1024 blocks: #{required(100, 1024)}"
puts "required for 2048 blocks: #{required(100, 2048)}"
@@ -32,8 +27,8 @@
total = source.size.to_f
used = source.size.to_f
dest.oneline_decode!(source.oneline_encode!(source.size))
- while (!dest.oneline_decode!(source.oneline_encode!((source.size.to_f * 0.1) + 8)))
- used += (source.size.to_f * 0.1)
+ while (!dest.oneline_decode!(source.oneline_encode!((source.size.to_f * 0.01).to_i + 8)))
+ used += (source.size.to_f * 0.01)
end
return used/total
end