diff --git a/src/cached.cr b/src/cached.cr index b3a88e7..a9617ac 100644 --- a/src/cached.cr +++ b/src/cached.cr @@ -56,7 +56,7 @@ class DODB::CachedDataBase(V) < DODB::Storage(V) # Removes any old indices or partitions pointing to a value about # to be replaced. if old_value - remove_partitions index, old_value + remove_indexes index, old_value end # 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 end - remove_partitions key, value + remove_indexes key, value @data.delete key value diff --git a/src/dodb.cr b/src/dodb.cr index f81f7ab..d80bc5d 100644 --- a/src/dodb.cr +++ b/src/dodb.cr @@ -270,7 +270,7 @@ abstract class DODB::Storage(V) end end - def remove_partitions(key : Int32, value : V) + def remove_indexes(key : Int32, value : V) @indexers.each &.deindex(stringify_key(key), value) end @@ -313,7 +313,7 @@ class DODB::DataBase(V) < DODB::Storage(V) # Removes any old indices or partitions pointing to a value about # to be replaced. if old_value - remove_partitions index, old_value + remove_indexes index, old_value end # 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 end - remove_partitions key, value + remove_indexes key, value value end diff --git a/src/dodb/index.cr b/src/dodb/index.cr index fff35df..b6e8c79 100644 --- a/src/dodb/index.cr +++ b/src/dodb/index.cr @@ -54,25 +54,26 @@ class DODB::Index(V) < DODB::Indexer(V) symlink = file_path_index index_key - ::File.delete symlink + begin + ::File.delete symlink + rescue File::NotFoundError + end end def get(index : String) : V - @storage[get_key index] + @storage[get_key_on_fs index] end def get?(index : String) : V? get index rescue MissingEntry nil - rescue KeyError - nil end # FIXME: Unlock on exception. def safe_get(index : String) : Nil @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 yield get index @@ -87,7 +88,7 @@ class DODB::Index(V) < DODB::Indexer(V) yield nil end - def get_key(index : String) : Int32 + def get_key_on_fs(index : String) : Int32 file_path = file_path_index index raise MissingEntry.new(@name, index) unless ::File.exists? file_path @@ -96,7 +97,7 @@ class DODB::Index(V) < DODB::Indexer(V) end def get_with_key(index : String) : Tuple(V, Int32) - key = get_key index + key = get_key_on_fs index value = @storage[key] @@ -125,7 +126,7 @@ class DODB::Index(V) < DODB::Indexer(V) end def delete(index : String) - key = get_key index + key = get_key_on_fs index @storage.delete key end @@ -181,6 +182,15 @@ class DODB::CachedIndex(V) < DODB::Index(V) end 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 diff --git a/src/dodb/partition.cr b/src/dodb/partition.cr index b1ffeeb..41e7a0e 100644 --- a/src/dodb/partition.cr +++ b/src/dodb/partition.cr @@ -55,7 +55,7 @@ class DODB::Partition(V) < DODB::Indexer(V) def get?(partition) : Array(V)? get partition - rescue KeyError + rescue MissingEntry nil end @@ -130,10 +130,20 @@ class DODB::CachedPartition(V) < DODB::Partition(V) def get(partition) r_value = Array(V).new - @data[partition].each do |data_key| - r_value << @storage[data_key] - end + if keys = @data[partition]? + keys.each do |data_key| + 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 end end diff --git a/src/dodb/tags.cr b/src/dodb/tags.cr index 02cab83..5ef7df0 100644 --- a/src/dodb/tags.cr +++ b/src/dodb/tags.cr @@ -33,7 +33,11 @@ class DODB::Tags(V) < DODB::Indexer(V) indices.each do |i| symlink = get_tagged_entry_path(i, key) - ::File.delete symlink + + begin + ::File.delete symlink + rescue File::NotFoundError + end end end @@ -66,7 +70,7 @@ class DODB::Tags(V) < DODB::Indexer(V) def get?(tag : String) : Array(V)? get tag - rescue KeyError + rescue MissingEntry nil end @@ -149,18 +153,20 @@ class DODB::CachedTags(V) < DODB::Tags(V) def get_with_indice(tag : String) : Array(Tuple(V, Int32)) r_value = Array(Tuple(V, Int32)).new - @data[tag].each do |data_key| - r_value << { @storage[data_key], data_key } - end + if keys = @data[tag]? + keys.each do |data_key| + 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 - end + Dir.each_child tag_directory do |child| + r_value << { @storage[get_key child], get_key child } + end - def get(tag : String) : Array(V) - r_value = Array(V).new - - @data[tag].each do |data_key| - r_value << @storage[data_key] + @data[tag] = r_value.map &.[1] end r_value