DpStmMap

Implementation of a distributed and persistent Map with Software Transactional Memory (STM) semantics.

Installation

Add this line to your application's Gemfile:

gem 'dp_stm_map'

And then execute:

$ bundle

Or install it yourself as:

$ gem install dp_stm_map

Comprehensive defintion

Implementation of a distributed and persistent Map with Software Transactional Memory (STM) semantics.

What is it?

Implementation of a hash map (dp_stm_map) with ACID transactional updates.

Offers a subset of map (Hash) operations

:[], :[]= and :has_key?

Persistent

Unlike data stored in the Hash, data stored in dp_stm_map will survive a restart of RVM.

Distributed

More than one RVM can connect to a central transaction manager (dp_stm_manager) that coordinates transactions for the same dp_stm_map. Every RVM can have its own local view of the current state of the map, making reading operations of dp_stm_map very scalable.

What is so special about it?

Every RVM will receive notification on changes in the map. This makes dp_stm_map great foundation for a distributed Event-driven architecture: Think of one RVM handling web traffic, another indexing persisted state and offering RESTful search service.

Usage

Manager

to start the central transaction manager execute:

$ dp_stm_manager.rb -s -p

Client

require 'dp_stm_map'

client=DpStmMap::DistributedPersistentStmMap.new host,port,'storage' client.start

Updating map within a transaction

client.atomic do |tx| tx['key'] = 'value' end

Read only transactions

value=client.atomic_read{ |tx| tx['key'] }

Adding a transaction listener

client.on_atomic do |change| # change is map containing all value transitions of one transaction: # e.g. => [nil,'value1'], 'key2' => ['old_value_2','new_value2'] change.each_pair do | k, (old_value, new_value) | update_index k, new_value end end

Adding a transaction validator - will be executed before transaction is passed on to transaction manager

client.validate_atomic do |change| # change is map containing all value transitions of one transaction: # e.g. => [nil,'value1'], 'key2' => ['old_value_2','new_value2'] change.each_pair do | k, (old_value, new_value) |

  # exception will abort (roll back) the transaction and will be raised as result of executing :atomic method
  raise "new value is invalid" if new_value != 'valid_new_value'
end

end

Using object store wrapper (stores Ruby objects in dp_stm_map by serializing as YAML strings)

object_client=DpStmMap::ObjectStore.new client

# all transaction, notification and validation methods from dp_stm_map are available to ObjectStore

object_client.atomic do |tx| user=User.new user.username="admin" tx[:user, "admin"]=user end

user=object_client.atomic_read { |tx| tx[:user, "admin"] }

object_client.validate_atomic do |change|

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request