InfoQ

InfoQ

News

My Bookmarks

Login or Register to enable bookmarks for unlimited time.

The content has been bookmarked!

There was an error bookmarking this content! Please retry.

MagLev Ruby VM Now Available, Brings GemStone's Persistence to Ruby

Posted by Werner Schuster on Nov 21, 2009

Sections
Architecture & Design,
Development,
Operations & Infrastructure
Topics
Database Design ,
Performance & Scalability ,
Ruby ,
Data Access ,
Runtimes
Tags
Object Databases ,
MagLev ,
Database ,
GemStone ,
Database Management ,
SmallTalk ,
Data Storage

MagLev is a Ruby implementation built by GemStone on their Smalltalk VM. GemStone/S, which is GemStone's Smalltalk product, been around for decades and is particularly known for it's mature distribution and persistence capabilities.

MagLev was announced in 2008, and the team has been busy working on it ever since. After a while in a private alpha, the cat is now out of the bag: a public version of MagLev is now available, which includes the MagLev source code which is hosted at GitHub.

To try MagLev, first get the source with a quick

git clone git://github.com/MagLev/maglev.git

followed by a

./install.sh

in the MagLev source directory and follow the instructions it provides.

To start MagLev use

rake maglev:start

which fires up the system. A quick way to run Ruby code is maglev-irb, which will connect to the common MagLev backend;  maglev-ruby and maglev-gem are also available.

A quick dig around the examples directory brings up the hat_trick example that Avi Bryant showed at the first MagLev demo. It showed off the persistence features, which allowed to ѕet up an object in one irb instance and then access it in another.

To reproduce it, simply fire up MagLev and two maglev-irb instances. To make an object execute this in one maglev-irb instance:

Maglev.persistent do
 Maglev::PERSISTENT_ROOT[:stuff] = ["hello world"]
end
Maglev.commit_transaction

Switch over to the other maglev-irb instance and execute:

Maglev::PERSISTENT_ROOT[:stuff]

which will return the string "hello world".

Obviously, this is a very simple demo of the persistence features; for more details of MagLev's persistence API see the docs.

A more slightly involved example is an implementation of Ruby's PStore using the persistence features. It shows how GemStone's persistence features make it easy to keep whole object graphs persistent without having to deal with an ORM.

While Rails is not yet supported on MagLev, working Rack and Sinatra examples are available.

A public Trac for MagLev is available to track the progress. For compatibility, this graph hows the number of passed RubySpecs, whereas links to detailed results are available too.

No details about licensing seem to be available on MagLev, but GemStone does offer free versions, eg of GemStone/S that bundles the web framework Seaside and is free up to 4 GB of data.

While there's a lot of buzz around the NoSQL databases these days, GemStone/S is a mature solution that's been around for decades. MagLev now tightly integrates these features with Ruby. What's your take - will you try MagLev?

Re: MagLev Ruby VM Now Available, Brings GemStone's Persistence to Ruby by Conrad Taylor Posted
Re: MagLev Ruby VM Now Available, Brings GemStone's Persistence to Ruby by Werner Schuster Posted
  1. Back to top

    Re: MagLev Ruby VM Now Available, Brings GemStone's Persistence to Ruby

    by Conrad Taylor

    First, an easier way to implement the above example would be to do the following:

    replace


    Maglev.persistent do
    Maglev::PERSISTENT_ROOT[:stuff] = ["hello world"]
    end
    Maglev.commit_transaction


    with


    Maglev::PERSISTENT_ROOT[:stuff] = ["hello world"]
    Maglev.commit_transaction


    BTW, Maglev::PERSISTENT_ROOT Hash is the persistent root for objects within Maglev.

    Thus, in order to access a persistent object within the Maglev system, it needs to be reachable from

    this persistent root. A cool example of Maglev would be to create a module that can be included in

    our model(s) for enabling this persistent goodness. For example,

    maglev_model.rb:

    module MaglevModel

    # these methods will be defined as class methods of the class that
    # includes this module.
    module ClassMethods

    # returns an array of all the posts
    def all

    # set the values including its state to current for all persistent objects.
    # i.e. give me the current state of the last commit.
    Maglev.abort_transaction

    # retrieve all the Post instance as a collection hash.
    Maglev::PERSISTENT_ROOT[self].values

    end

    end

    # save current Post instance to the set of persisted objects.
    def save

    # store the current Post instance as a child of the Post class.
    Maglev::PERSISTENT_ROOT[self.class][self.__id__] = self

    # save the current state back to the repository.
    Maglev.commit_transaction

    end

    def self.included( klass )

    # create a space in the PERSISTENT_ROOT to hold persistent Post objects.
    # note: the statement below refreshing our repository each time it's ran
    # but it's cool for something simple that's used for instructional purposes.
    Maglev::PERSISTENT_ROOT[ klass ] = Hash.new

    # stage the Post class for persistence.
    klass.maglev_persistable = true

    # stage the MaglevModel module for persistence.
    self.maglev_persistable = true

    # extend the Post class with the ClassMethods (i.e. after this statement is executed, the methods within
    # ClassMethods module become class methods on our Post class.)
    klass.extend ClassMethods
    end

    end


    Now, let's create the Post model and this will be a snap because we have done most of the work by

    creating a reusable module, MaglevModel, for enabling persistence within the Post class:

    post.rb:

    require 'maglev_model'

    class Post

    # let's include our MaglevModel for enabling persistence within the Post class.
    include MaglevModel

    # let's create some accessors for the
    attr_accessor :title, :description

    # initialize the Post instance.
    # note: this instance method is called indirectly when the new class method is invoked.
    def initialize( params = {} )

    @title = params[:title]
    @description = params[:description]

    end

    # output a string representation of this Post instance.
    def to_s
    "title => #{@title}\ndescription => #{@description}\n"
    end

    end
    Maglev.commit_transaction

    # let's create and save a couple of posts.
    post_one = Post.new( :title => "This is post 1", :description => "This is post 1 description." )
    post_one.save

    post_two = Post.new( :title => "This is post 2", :description => "This is post 2 description." )
    post_two.save

    # let's output all the persistent Post instances from the repository.
    Post.all.each { |post| puts post }



    Now, if we were to run the above code, one should see the following:


    $ maglev-ruby post.rb

    title => "This is post 1
    description => "This is post 1 description.
    title => "This is post 2
    description => "This is post 2 description.


    Now, you should have noticed in the above that there was no database schema, SQL, or other

    things that one would normally see in regards to setting up a relational database. Thus, the only

    thing that I needed to do was include the MaglevModel, and define an initialize and to_s instance

    methods on my Post class. That's all to it. BTW, MaglevModel module is a user created module and

    one can customize and name as necessary for your project. Lastly, if you're a Rubyist, then I would

    recommend taking a look Maglev.

    Happy coding,

    -Conrad

  2. Back to top

    Re: MagLev Ruby VM Now Available, Brings GemStone's Persistence to Ruby

    by Werner Schuster

    @Conrad: Great - thanks for the comment & sample.
    And I agree - it's great to see MagLev available to everyone;

Educational Content

Attila Szegedi on JVM and GC Performance Tuning at Twitter

Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.

10 tips on how to prevent business value risk

One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.

Interview: Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives

InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.

Beauty Is in the Eye of the Beholder

Alex Papadimoulis discusses ugly code, where it comes from, how to avoid it, and how to get rid of it.

Architecting Visa for Massive Scale and Continuous Innovation

John Davies examines Visa’s architecture and shows how enterprises have architected complex integrations incorporating Hadoop, memcached, Ruby on Rails, and others to deliver innovative solutions.

Max Protect: Scalability and Caching at ESPN.com

Sean Comerford unveils ESPN.com’s architecture, what components are used and why, and the current changes the website goes through.

The Seven Deadly Sins of Enterprise Agile Adoption

Are there repeated patterns of failure on Enterprise Agile Enablement efforts? Sanjiv and Arlen discuss Seven Deadly Sins to avoid when adopting Agile in an enterprise.

Questions for an Enterprise Architect

Erik Dörnenburg answers: What is Enterprise and Evolutionary Architecture?, discussing 4 issues: Turning strategy into execution, Ensuring conformance, Where do the architects sit? Buying or building?