forked from Baguette/dodb.cr
Some tests and extra code for parallelization of DODB.
parent
9990a3ac1b
commit
2dd42f3a30
64
spec/test.cr
64
spec/test.cr
|
@ -482,5 +482,69 @@ describe "DODB::DataBase" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "parallel support" do
|
||||||
|
# Not sure how many forks would be safe in a test like that.
|
||||||
|
fork_count = 25
|
||||||
|
entries_per_fork = 100
|
||||||
|
|
||||||
|
it "works for pushing values" do
|
||||||
|
db = DODB::SpecDataBase.new
|
||||||
|
|
||||||
|
processes = [] of Process
|
||||||
|
|
||||||
|
fork_count.times do |fork_id|
|
||||||
|
processes << Process.fork do
|
||||||
|
entries_per_fork.times do |entry_id|
|
||||||
|
db << Ship.new("entry-#{fork_id}-#{entry_id}", "???")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
processes.each &.wait
|
||||||
|
|
||||||
|
dump = db.to_a
|
||||||
|
|
||||||
|
dump.size.should eq fork_count * entries_per_fork
|
||||||
|
end
|
||||||
|
|
||||||
|
it "works for updating values" do
|
||||||
|
db = DODB::SpecDataBase.new
|
||||||
|
db_entries_by_name = db.new_index "name", &.name
|
||||||
|
|
||||||
|
# First pass, creating data.
|
||||||
|
processes = [] of Process
|
||||||
|
fork_count.times do |fork_id|
|
||||||
|
processes << Process.fork do
|
||||||
|
entries_per_fork.times do |entry_id|
|
||||||
|
db << Ship.new("entry-#{fork_id}-#{entry_id}", "???")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
processes.each &.wait
|
||||||
|
|
||||||
|
# Second pass, updating data.
|
||||||
|
processes = [] of Process
|
||||||
|
fork_count.times do |fork_id|
|
||||||
|
processes << Process.fork do
|
||||||
|
entries_per_fork.times do |entry_id|
|
||||||
|
db_entries_by_name.update Ship.new("entry-#{fork_id}-#{entry_id}", "???", tags: ["updated"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
processes.each &.wait
|
||||||
|
|
||||||
|
# Third pass, testing database content.
|
||||||
|
dump = db.to_a
|
||||||
|
|
||||||
|
fork_count.times do |fork_id|
|
||||||
|
entries_per_fork.times do |entry_id|
|
||||||
|
entry = db_entries_by_name.get "entry-#{fork_id}-#{entry_id}"
|
||||||
|
|
||||||
|
entry.tags.should eq ["updated"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
26
src/dodb.cr
26
src/dodb.cr
|
@ -44,9 +44,9 @@ class DODB::DataBase(V)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_lock(name)
|
def request_lock(name, subname = nil)
|
||||||
r = -1
|
r = -1
|
||||||
file_path = get_lock_file_path name
|
file_path = get_lock_file_path name, subname
|
||||||
file_perms = 0o644
|
file_perms = 0o644
|
||||||
|
|
||||||
flags = LibC::O_EXCL | LibC::O_CREAT
|
flags = LibC::O_EXCL | LibC::O_CREAT
|
||||||
|
@ -56,8 +56,8 @@ class DODB::DataBase(V)
|
||||||
|
|
||||||
LibC.close r
|
LibC.close r
|
||||||
end
|
end
|
||||||
def release_lock(name)
|
def release_lock(name, subname = nil)
|
||||||
File.delete get_lock_file_path name
|
File.delete get_lock_file_path name, subname
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -107,11 +107,17 @@ class DODB::DataBase(V)
|
||||||
end
|
end
|
||||||
|
|
||||||
def <<(item : V)
|
def <<(item : V)
|
||||||
|
request_lock "index"
|
||||||
|
|
||||||
index = last_index + 1
|
index = last_index + 1
|
||||||
|
|
||||||
self[index] = item
|
self[index] = item
|
||||||
|
|
||||||
self.last_index = index
|
self.last_index = index
|
||||||
|
|
||||||
|
release_lock "index"
|
||||||
|
|
||||||
|
index # FIXME: Should we really return the internal key?
|
||||||
end
|
end
|
||||||
|
|
||||||
def []?(key : Int32) : V?
|
def []?(key : Int32) : V?
|
||||||
|
@ -160,6 +166,8 @@ class DODB::DataBase(V)
|
||||||
end
|
end
|
||||||
|
|
||||||
def pop
|
def pop
|
||||||
|
request_lock "index"
|
||||||
|
|
||||||
index = last_index
|
index = last_index
|
||||||
|
|
||||||
# Some entries may have been removed. We’ll skip over those.
|
# Some entries may have been removed. We’ll skip over those.
|
||||||
|
@ -178,6 +186,8 @@ class DODB::DataBase(V)
|
||||||
|
|
||||||
last_index = index - 1
|
last_index = index - 1
|
||||||
|
|
||||||
|
release_lock "index"
|
||||||
|
|
||||||
poped
|
poped
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -306,8 +316,12 @@ class DODB::DataBase(V)
|
||||||
"#{@directory_name}/locks"
|
"#{@directory_name}/locks"
|
||||||
end
|
end
|
||||||
|
|
||||||
private def get_lock_file_path(name : String)
|
private def get_lock_file_path(name : String, subname : String? = nil)
|
||||||
"#{locks_directory}/#{name}.lock"
|
if subname
|
||||||
|
"#{locks_directory}/#{name}-#{subname}.lock" # FIXME: Separator that causes less collisions?
|
||||||
|
else
|
||||||
|
"#{locks_directory}/#{name}.lock"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def read(file_path : String)
|
private def read(file_path : String)
|
||||||
|
|
Loading…
Reference in New Issue