Fix cached indexes not working when databases aren't reindexed on start.

paper
Philippe PITTOLI 2024-05-06 23:52:17 +02:00
parent 7404411ec5
commit 8dfbe28986
5 changed files with 56 additions and 30 deletions

View File

@ -56,7 +56,7 @@ class DODB::CachedDataBase(V) < DODB::Storage(V)
# Removes any old indices or partitions pointing to a value about # Removes any old indices or partitions pointing to a value about
# to be replaced. # to be replaced.
if old_value if old_value
remove_partitions index, old_value remove_indexes index, old_value
end end
# Avoids corruption in case the application crashes while writing. # Avoids corruption in case the application crashes while writing.
@ -98,7 +98,7 @@ class DODB::CachedDataBase(V) < DODB::Storage(V)
# FIXME: Only intercept “no such file" errors # FIXME: Only intercept “no such file" errors
end end
remove_partitions key, value remove_indexes key, value
@data.delete key @data.delete key
value value

View File

@ -270,7 +270,7 @@ abstract class DODB::Storage(V)
end end
end end
def remove_partitions(key : Int32, value : V) def remove_indexes(key : Int32, value : V)
@indexers.each &.deindex(stringify_key(key), value) @indexers.each &.deindex(stringify_key(key), value)
end end
@ -313,7 +313,7 @@ class DODB::DataBase(V) < DODB::Storage(V)
# Removes any old indices or partitions pointing to a value about # Removes any old indices or partitions pointing to a value about
# to be replaced. # to be replaced.
if old_value if old_value
remove_partitions index, old_value remove_indexes index, old_value
end end
# Avoids corruption in case the application crashes while writing. # Avoids corruption in case the application crashes while writing.
@ -340,7 +340,7 @@ class DODB::DataBase(V) < DODB::Storage(V)
# FIXME: Only intercept “no such file" errors # FIXME: Only intercept “no such file" errors
end end
remove_partitions key, value remove_indexes key, value
value value
end end

View File

@ -54,25 +54,26 @@ class DODB::Index(V) < DODB::Indexer(V)
symlink = file_path_index index_key symlink = file_path_index index_key
::File.delete symlink begin
::File.delete symlink
rescue File::NotFoundError
end
end end
def get(index : String) : V def get(index : String) : V
@storage[get_key index] @storage[get_key_on_fs index]
end end
def get?(index : String) : V? def get?(index : String) : V?
get index get index
rescue MissingEntry rescue MissingEntry
nil nil
rescue KeyError
nil
end end
# FIXME: Unlock on exception. # FIXME: Unlock on exception.
def safe_get(index : String) : Nil def safe_get(index : String) : Nil
@storage.request_lock @name, index @storage.request_lock @name, index
internal_key = get_key(index).to_s internal_key = get_key_on_fs(index).to_s
@storage.request_lock internal_key @storage.request_lock internal_key
yield get index yield get index
@ -87,7 +88,7 @@ class DODB::Index(V) < DODB::Indexer(V)
yield nil yield nil
end end
def get_key(index : String) : Int32 def get_key_on_fs(index : String) : Int32
file_path = file_path_index index file_path = file_path_index index
raise MissingEntry.new(@name, index) unless ::File.exists? file_path raise MissingEntry.new(@name, index) unless ::File.exists? file_path
@ -96,7 +97,7 @@ class DODB::Index(V) < DODB::Indexer(V)
end end
def get_with_key(index : String) : Tuple(V, Int32) def get_with_key(index : String) : Tuple(V, Int32)
key = get_key index key = get_key_on_fs index
value = @storage[key] value = @storage[key]
@ -125,7 +126,7 @@ class DODB::Index(V) < DODB::Indexer(V)
end end
def delete(index : String) def delete(index : String)
key = get_key index key = get_key_on_fs index
@storage.delete key @storage.delete key
end end
@ -181,6 +182,15 @@ class DODB::CachedIndex(V) < DODB::Index(V)
end end
def get(index : String) : V def get(index : String) : V
@storage[@data[index]] # Get the key from the database representation on the file-system.
key = if k = @data[index]?
k
elsif k = get_key_on_fs(index)
@data[index] = k
k
else
raise MissingEntry.new(@name, index)
end
@storage[key]
end end
end end

View File

@ -55,7 +55,7 @@ class DODB::Partition(V) < DODB::Indexer(V)
def get?(partition) : Array(V)? def get?(partition) : Array(V)?
get partition get partition
rescue KeyError rescue MissingEntry
nil nil
end end
@ -130,10 +130,20 @@ class DODB::CachedPartition(V) < DODB::Partition(V)
def get(partition) def get(partition)
r_value = Array(V).new r_value = Array(V).new
@data[partition].each do |data_key| if keys = @data[partition]?
r_value << @storage[data_key] keys.each do |data_key|
end r_value << @storage[data_key]
end
else
# Get the key from the database representation on the file-system.
partition_directory = indexing_directory partition
raise MissingEntry.new(@name, partition) unless Dir.exists? partition_directory
Dir.each_child partition_directory do |child|
r_value << @storage[get_key child]
end
@data[partition] = r_value
end
r_value r_value
end end
end end

View File

@ -33,7 +33,11 @@ class DODB::Tags(V) < DODB::Indexer(V)
indices.each do |i| indices.each do |i|
symlink = get_tagged_entry_path(i, key) symlink = get_tagged_entry_path(i, key)
::File.delete symlink
begin
::File.delete symlink
rescue File::NotFoundError
end
end end
end end
@ -66,7 +70,7 @@ class DODB::Tags(V) < DODB::Indexer(V)
def get?(tag : String) : Array(V)? def get?(tag : String) : Array(V)?
get tag get tag
rescue KeyError rescue MissingEntry
nil nil
end end
@ -149,18 +153,20 @@ class DODB::CachedTags(V) < DODB::Tags(V)
def get_with_indice(tag : String) : Array(Tuple(V, Int32)) def get_with_indice(tag : String) : Array(Tuple(V, Int32))
r_value = Array(Tuple(V, Int32)).new r_value = Array(Tuple(V, Int32)).new
@data[tag].each do |data_key| if keys = @data[tag]?
r_value << { @storage[data_key], data_key } keys.each do |data_key|
end r_value << { @storage[data_key], data_key }
end
else
# Get the key from the database representation on the file-system.
tag_directory = indexing_directory tag
raise MissingEntry.new(@name, tag) unless Dir.exists? tag_directory
r_value Dir.each_child tag_directory do |child|
end r_value << { @storage[get_key child], get_key child }
end
def get(tag : String) : Array(V) @data[tag] = r_value.map &.[1]
r_value = Array(V).new
@data[tag].each do |data_key|
r_value << @storage[data_key]
end end
r_value r_value