WIP for lock files and atomic operations.
parent
b413570d61
commit
800d139a3d
22
spec/test.cr
22
spec/test.cr
|
@ -396,6 +396,28 @@ describe "DODB::DataBase" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "atomic operations" do
|
||||
it "safe_get and safe_get?" do
|
||||
db = DODB::SpecDataBase.new
|
||||
|
||||
db_ships_by_name = db.new_index "name", &.name
|
||||
|
||||
Ship.all_ships.each do |ship|
|
||||
db << ship
|
||||
end
|
||||
|
||||
Ship.all_ships.each do |ship|
|
||||
db_ships_by_name.safe_get ship.name do |results|
|
||||
results.should eq(ship)
|
||||
end
|
||||
|
||||
db_ships_by_name.safe_get? ship.name do |results|
|
||||
results.should eq(ship)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "tools" do
|
||||
it "rebuilds indexes" do
|
||||
db = DODB::SpecDataBase.new
|
||||
|
|
25
src/dodb.cr
25
src/dodb.cr
|
@ -8,6 +8,7 @@ class DODB::DataBase(V)
|
|||
|
||||
def initialize(@directory_name : String)
|
||||
Dir.mkdir_p data_path
|
||||
Dir.mkdir_p locks_directory
|
||||
|
||||
begin
|
||||
self.last_index
|
||||
|
@ -43,6 +44,22 @@ class DODB::DataBase(V)
|
|||
end
|
||||
end
|
||||
|
||||
def request_lock(name)
|
||||
r = -1
|
||||
file_path = get_lock_file_path name
|
||||
file_perms = 0o644
|
||||
|
||||
flags = LibC::O_EXCL | LibC::O_CREAT
|
||||
while (r = LibC.open file_path, flags, file_perms) == -1
|
||||
sleep 1.milliseconds
|
||||
end
|
||||
|
||||
LibC.close r
|
||||
end
|
||||
def release_lock(name)
|
||||
File.delete get_lock_file_path name
|
||||
end
|
||||
|
||||
##
|
||||
# name is the name that will be used on the file system.
|
||||
def new_partition(name : String, &block : Proc(V, String))
|
||||
|
@ -279,6 +296,14 @@ class DODB::DataBase(V)
|
|||
"#{data_path}/%010i.json" % key
|
||||
end
|
||||
|
||||
private def locks_directory : String
|
||||
"#{@directory_name}/locks"
|
||||
end
|
||||
|
||||
private def get_lock_file_path(name : String)
|
||||
"#{locks_directory}/#{name}.lock"
|
||||
end
|
||||
|
||||
private def read(file_path : String)
|
||||
V.from_json ::File.read file_path
|
||||
end
|
||||
|
|
|
@ -68,6 +68,21 @@ class DODB::Index(V) < DODB::Indexer(V)
|
|||
nil
|
||||
end
|
||||
|
||||
def safe_get(index : String) : Nil
|
||||
internal_key = get_key(index).to_s
|
||||
@storage.request_lock internal_key
|
||||
|
||||
yield get index
|
||||
|
||||
@storage.release_lock internal_key
|
||||
end
|
||||
|
||||
def safe_get?(index : String, &block : Proc(V | Nil, Nil)) : Nil
|
||||
safe_get index, &block
|
||||
rescue MissingEntry
|
||||
yield nil
|
||||
end
|
||||
|
||||
def get_key(index : String) : Int32
|
||||
file_path = file_path_index index
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
lib LibC
|
||||
{% if flag?(:linux) %}
|
||||
O_EXCL = 0o200
|
||||
{% elsif flag?(:openbsd) %}
|
||||
O_EXCL = 0x0800
|
||||
{% end %}
|
||||
end
|
||||
|
Loading…
Reference in New Issue