From 48cf3c23be67c5abde2f40d62a75e9441f0629cb Mon Sep 17 00:00:00 2001 From: Luka Vandervelden Date: Mon, 20 Jul 2020 15:04:17 +0200 Subject: [PATCH] Fixes issues related to parallel updates. --- spec/test.cr | 25 +++++++++++++++++++++++++ src/dodb/index.cr | 3 +++ 2 files changed, 28 insertions(+) diff --git a/spec/test.cr b/spec/test.cr index 31c5778..8371edf 100644 --- a/spec/test.cr +++ b/spec/test.cr @@ -545,6 +545,31 @@ describe "DODB::DataBase" do end end end + + it "does parallel-safe updates" do + db = DODB::SpecDataBase.new + db_entries_by_name = db.new_index "name", &.name + + # We’ll be storing an integer in the "klass" field, and incrementing + # it in forks in a second time. + db << Ship.new("test", "0") + + processes = [] of Process + fork_count.times do |fork_id| + processes << Process.fork do + entries_per_fork.times do |entry_id| + db_entries_by_name.safe_get "test" do |entry| + entry.klass = (entry.klass.to_i + 1).to_s + + db_entries_by_name.update "test", entry + end + end + end + end + processes.each &.wait + + db_entries_by_name.get("test").klass.should eq((fork_count * entries_per_fork).to_s) + end end end diff --git a/src/dodb/index.cr b/src/dodb/index.cr index bb0ac0b..6fb6c68 100644 --- a/src/dodb/index.cr +++ b/src/dodb/index.cr @@ -72,13 +72,16 @@ class DODB::Index(V) < DODB::Indexer(V) nil end + # FIXME: Unlock on exception. def safe_get(index : String) : Nil + @storage.request_lock @name, index internal_key = get_key(index).to_s @storage.request_lock internal_key yield get index @storage.release_lock internal_key + @storage.release_lock @name, index end def safe_get?(index : String, &block : Proc(V | Nil, Nil)) : Nil