Skip to content

Commit

Permalink
It's now not neccessarly not start and stop Neo4j, it will be done fo…
Browse files Browse the repository at this point in the history
…r you automatically
  • Loading branch information
andreasronge committed Dec 4, 2008
1 parent f0aab33 commit 554460c
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 91 deletions.
21 changes: 2 additions & 19 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,6 @@ Neo properties and relationships are declared using the 'properties' and 'has_n'
In the example above a lucene index will be updated when the name or salary property changes.
The salary of all friends are also indexed which means we can query for people who has friends with a certain salary.

=== Start and stop

Before using neo it has to be configured and started

Neo4j::Config[:storage_path] = '/home/neo/neodb'
Neo4j.start

The neo database will be stored at '/home/neo/neodb' and the lucene index files be kept in memory by default.
The lucene index can be kept on disk:

Lucene::Config[:store_on_file] = true
Lucene::Config[:storage_path] => '/home/neo/lucene-db'
Neo4j.start

=== Creating a node

Creating a Person node instance
Expand Down Expand Up @@ -420,10 +406,6 @@ may return an not empty array. This is because Index.new is a singleton - a new

=== Start and Stop of the Neo Database

In order to use neo it has to be started first.

Neo4j.start

By default lucene indexes are kept in memory.
Keeping index in memory will increase the performance of lucene operations (such as updating the index).

Expand All @@ -436,10 +418,11 @@ Before using Neo4j the location where the database is stored on disk must be con

Neo4j::Config[:storage_path] = '/home/neo/neodb'

To stop the neo database:
To stop the neo database - you do not need to do this since it will be done automatically when the virtual machine exits.

Neo4j.stop


=== Neo4j::NodeMixin

Neo4j::NodeMixin is a mixin that lets instances to be stored as a node in the neo node space on disk.
Expand Down
1 change: 1 addition & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
== TODO - soon

* Loading nodes that does not exist generated a stack dump.
* identity map - http://www.martinfowler.com/eaaCatalog/identityMap.html
* the Neo4j::Node find method should use the Neo4j traversal if there are no lucene index available
* performance tests and check for memory leaks
Expand Down
25 changes: 18 additions & 7 deletions lib/neo4j/neo.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Neo4j


# Starts neo.
# Starts neo unless it is not already started.
# Before using neo it has to be started and the location of the Neo database on the filesystem must
# have been configured, Neo4j::Config[:storage_path].
#
Expand All @@ -12,23 +12,27 @@ module Neo4j
# ==== Returns
# The neo instance
#
# @raise [StandardError] if Neo already has been started
# :api: public
def self.start
raise StandardError.new("Already started neo") if @instance
return if @instance
@instance = Neo.new
@instance.start
at_exit do
Neo4j.stop
end
@instance
end

#
# Return the started neo instance or nil if not started
# Return a started neo instance.
# It will be started if this has not already been done.
#
# ==== Returns
# The neo instance
#
# :api: public
def self.instance
@instance
@instance ||= start
end

# Stops the current instance unless it is not started.
Expand Down Expand Up @@ -60,14 +64,21 @@ class Neo
#
# ref_node : the reference, ReferenceNode, node, wraps a org.neo4j.api.core.NeoService#getReferenceNode
#
attr_reader :ref_node
attr_reader :ref_node, :placebo_tx

def start
@neo = org.neo4j.api.core.EmbeddedNeo.new(Neo4j::Config[:storage_path])
Transaction.run { @ref_node = ReferenceNode.new(@neo.getReferenceNode()) }
$NEO_LOGGER.info{ "Started neo. Database storage located at '#{@db_storage}'"}

# get the placebo transaction
# the second time we create an transaction the placebo transaction will
# be returned from neo. We need to know if we are using real transaction or a placebo.
tx = begin_transaction
@placebo_tx = begin_transaction
tx.finish
end

#
# Create an internal neo node (returns a java object)
# Don't use this method - only for internal use.
Expand Down
92 changes: 61 additions & 31 deletions lib/neo4j/transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ module Neo4j
#
# Raised when an operation was called without a running transaction.
#
class NotInTransactionError < StandardError; end
class NotInTransactionError < StandardError
def initialize
# puts "NOT IN TRANSACTION ERROR"
# puts caller
end
end


#
# Raised when an operation was called when an transaction was already running.
#
class AlreadyInTransactionError < StandardError; end
class AlreadyInTransactionError < StandardError
def initialize
# puts "AlreadyInTransactionError"
# puts caller
end
end


#
Expand Down Expand Up @@ -45,7 +55,21 @@ def called
end
res
end


def placebo?(tx)
Neo4j.instance.placebo_tx == tx
end

def new
neo_tx= Neo4j.instance.begin_transaction #org.neo4j.api.core.Transaction.begin
if placebo?(neo_tx)
raise StandardError.new("Neo4j created a placebo transaction but an real transaction did not exist yet") if !Transaction.running?
Transaction.current.placebo
else
super(neo_tx)
end
end

#
# Runs a block in a Neo4j transaction
#
Expand Down Expand Up @@ -73,15 +97,17 @@ def run
raise ArgumentError.new("Expected a block to run in Transaction.run") unless block_given?

tx = nil
tx = Neo4j::Transaction.new
#tx.start

# reuse existing transaction ?
if !Transaction.running?
tx = Neo4j::Transaction.new
tx.start
else
$NEO_LOGGER.info("Start chained transaction for #{Transaction.current}")
tx = ChainedTransaction.new(Transaction.current) # TODO this will not work since the we call finish on the parent transaction !
end
# if !Transaction.running?
# tx = Neo4j::Transaction.new
# tx.start
# else
# $NEO_LOGGER.info("Start chained transaction for #{Transaction.current}")
# tx = ChainedTransaction.new(Transaction.current) # TODO this will not work since the we call finish on the parent transaction !
# end
ret = nil

begin
Expand Down Expand Up @@ -117,37 +143,45 @@ def failure?
#


def initialize
# Transaction.synchronize do
def initialize(neo_tx)
raise AlreadyInTransactionError.new if Transaction.running?
@@counter += 1
@neo_tx = neo_tx
@@counter += 1
@id = @@counter
@failure = false
@nodes_to_be_reindexed = {}
Thread.current[:transaction] = self
# end
$NEO_LOGGER.debug{"create #{self.to_s}"}
end

def to_s
"Transaction: #{@id} failure: #{failure?}, running #{Transaction.running?}, thread: #{Thread.current.to_s} #{@neo_tx}"
"Transaction: placebo: #{placebo?}, #{@id} failure: #{failure?}, running #{Transaction.running?}, thread: #{Thread.current.to_s} #{@neo_tx}"
end


def failure?
@failure == true
end

#
# Starts a new transaction
#
def start
@neo_tx= Neo4j.instance.begin_transaction #org.neo4j.api.core.Transaction.begin
@failure = false

$NEO_LOGGER.info{"started #{self.to_s}"}
self

def placebo?
@neo_tx == Neo4j.instance.placebo_tx
end

def placebo
@placebo ||= PlaceboTransaction.new(self)
end

# #
# # Starts a new transaction
# #
# def start
# @neo_tx= Neo4j.instance.begin_transaction #org.neo4j.api.core.Transaction.begin
# @failure = false
#
# $NEO_LOGGER.info{"started #{self.to_s}"}
# self
# end


#
# Marks this transaction as successful, which means that it will be commited
Expand All @@ -165,7 +199,6 @@ def success
#
def finish
raise NotInTransactionError.new unless Transaction.running?

unless failure?
@nodes_to_be_reindexed.each_value {|node| node.reindex!}
@nodes_to_be_reindexed.clear
Expand Down Expand Up @@ -210,23 +243,20 @@ def reindex(node)
end

#
# This is returned when trying to create a new transaction while a transaction is arleady running
# This is returned when trying to create a new transaction while a transaction is already running
# There is no real support for chained transaction since Neo4j does not support chained transactions.
# This class will do nothing when the finish method is called.
# Finish will only be called when the 'main' transaction does it.
#
# TODO investigate if Neo already does this ???
#
class ChainedTransaction < DelegateClass(Transaction)
class PlaceboTransaction < DelegateClass(Transaction)

def initialize(tx)
super(tx)
@tx = tx # store it only for logging purpose
end

# def success
# end

#
# Do nothing since Neo4j does not support chained transactions.
#
Expand Down
31 changes: 2 additions & 29 deletions neo4j.gemspec
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# WARNING : RAKE AUTO-GENERATED FILE. DO NOT MANUALLY EDIT!
# LAST UPDATED : Wed Dec 03 18:47:49 +0100 2008
# LAST UPDATED : Wed Dec 03 19:02:20 +0100 2008
#
# RUN : 'rake gem:update_gemspec'

Expand Down Expand Up @@ -76,34 +76,7 @@ Gem::Specification.new do |s|
"examples/imdb/model.rb",
"examples/imdb/find_actors.rb",
"examples/imdb/create_neo_db.rb",
"examples/imdb/db",
"examples/imdb/load_test.rb",
"examples/imdb/data",
"examples/imdb/db/neo",
"examples/imdb/db/neo/neostore.propertystore.db.strings",
"examples/imdb/db/neo/neostore.propertystore.db.index.id",
"examples/imdb/db/neo/neostore.propertystore.db.index.keys.id",
"examples/imdb/db/neo/neostore.relationshiptypestore.db",
"examples/imdb/db/neo/neostore.propertystore.db.index.keys",
"examples/imdb/db/neo/neostore.id",
"examples/imdb/db/neo/neostore.relationshiptypestore.db.id",
"examples/imdb/db/neo/neostore.relationshipstore.db",
"examples/imdb/db/neo/neostore.propertystore.db.strings.id",
"examples/imdb/db/neo/neostore.relationshipstore.db.id",
"examples/imdb/db/neo/neostore.propertystore.db.arrays.id",
"examples/imdb/db/neo/neostore.nodestore.db.id",
"examples/imdb/db/neo/tm_tx_log.1",
"examples/imdb/db/neo/neostore.propertystore.db.arrays",
"examples/imdb/db/neo/neostore.relationshiptypestore.db.names.id",
"examples/imdb/db/neo/neostore.relationshiptypestore.db.names",
"examples/imdb/db/neo/neostore.propertystore.db.index",
"examples/imdb/db/neo/neostore.propertystore.db",
"examples/imdb/db/neo/neostore.propertystore.db.id",
"examples/imdb/db/neo/active_tx_log",
"examples/imdb/db/neo/neostore.nodestore.db",
"examples/imdb/db/neo/neostore",
"examples/imdb/data/test-movies.list",
"examples/imdb/data/test-actors.list"]
"examples/imdb/load_test.rb"]
s.rubygems_version = "1.3.1"
s.platform = "ruby"
s.date = "Wed Dec 03 00:00:00 +0100 2008"
Expand Down
35 changes: 30 additions & 5 deletions test/neo4j/neo_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,30 @@

#$NEO_LOGGER.level = Logger::DEBUG

describe "Neo4j" do
before(:all) do
FileUtils.rm_rf '/tmp/neo4j'
Neo4j::Config[:storage_path] = NEO_STORAGE
end


it "should not need to be started or stopped before using it" do
undefine_class :Foo
class Foo
include Neo4j::NodeMixin
properties :name
index :name
end
res = Foo.find(:name => 'kalle')
res.size.should == 0
f = Foo.new
f.name = 'kalle'
res = Foo.find(:name => 'kalle')
res.size.should == 1
res[0].name.should == 'kalle'
end
end

describe Neo4j::Neo do
before(:each) do
start
Expand All @@ -21,9 +45,10 @@
stop
end

it "should not be possible to get an instance if neo is stopped" do
it "should return a new neo instance if neo has been stopped" do
x = Neo4j.instance
Neo4j.stop
Neo4j.instance.should be_nil
Neo4j.instance.should_not == x
end

it "should have a reference node" do
Expand All @@ -37,14 +62,14 @@ class TestNode
include Neo4j::NodeMixin
end
t1 = TestNode.new

# when
t2 = Neo4j.instance.find_node(t1.neo_node_id)

# then
t1.should == t2
end

it "should not find a node that does not exist" do
n = Neo4j.instance.find_node(10)
n.should be_nil
Expand Down

0 comments on commit 554460c

Please sign in to comment.