WIP for lock files and atomic operations.

This commit is contained in:
Luka Vandervelden 2020-06-24 21:45:45 +02:00
parent b413570d61
commit 800d139a3d
4 changed files with 71 additions and 0 deletions

View File

@ -396,6 +396,28 @@ describe "DODB::DataBase" do
end end
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 describe "tools" do
it "rebuilds indexes" do it "rebuilds indexes" do
db = DODB::SpecDataBase.new db = DODB::SpecDataBase.new

View File

@ -8,6 +8,7 @@ class DODB::DataBase(V)
def initialize(@directory_name : String) def initialize(@directory_name : String)
Dir.mkdir_p data_path Dir.mkdir_p data_path
Dir.mkdir_p locks_directory
begin begin
self.last_index self.last_index
@ -43,6 +44,22 @@ class DODB::DataBase(V)
end end
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. # name is the name that will be used on the file system.
def new_partition(name : String, &block : Proc(V, String)) def new_partition(name : String, &block : Proc(V, String))
@ -279,6 +296,14 @@ class DODB::DataBase(V)
"#{data_path}/%010i.json" % key "#{data_path}/%010i.json" % key
end 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) private def read(file_path : String)
V.from_json ::File.read file_path V.from_json ::File.read file_path
end end

View File

@ -68,6 +68,21 @@ class DODB::Index(V) < DODB::Indexer(V)
nil nil
end 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 def get_key(index : String) : Int32
file_path = file_path_index index file_path = file_path_index index

9
src/dodb/lib_c.cr Normal file
View File

@ -0,0 +1,9 @@
lib LibC
{% if flag?(:linux) %}
O_EXCL = 0o200
{% elsif flag?(:openbsd) %}
O_EXCL = 0x0800
{% end %}
end