Removes a lot of duplicated code.
This commit is contained in:
parent
2b24fbc8a0
commit
7a342f8391
@ -96,28 +96,45 @@ class DODB::Partition(V) < DODB::Indexer(V)
|
||||
# WARNING: throws an exception if no value is found.
|
||||
# NOTE: for a safe version, use `#get?`.
|
||||
def get(partition : String) : Array(V)
|
||||
partition_directory = indexing_directory partition
|
||||
raise MissingEntry.new(@name, partition) unless Dir.exists? partition_directory
|
||||
|
||||
r_value = Array(V).new
|
||||
|
||||
Dir.each_child partition_directory do |child|
|
||||
r_value << @storage[get_key child]
|
||||
get_with_keys(partition).map &.[0]
|
||||
end
|
||||
|
||||
r_value
|
||||
end
|
||||
|
||||
# Safe version of `#get`, gets data and returns a *nil* value in case of
|
||||
# Safe version of `#get`, gets data and returns *an empty array* in case of
|
||||
# a missing entry instead of an exception.
|
||||
#
|
||||
# ```
|
||||
# red_cars = cars_by_color.get? "red" # No red cars = nil.
|
||||
# red_cars = cars_by_color.get? "red"
|
||||
# ```
|
||||
def get?(partition : String) : Array(V)?
|
||||
get partition
|
||||
rescue MissingEntry
|
||||
nil
|
||||
Array(V).new
|
||||
end
|
||||
|
||||
# Gets partition entries (and their keys) from the file-system representation.
|
||||
#
|
||||
# ```
|
||||
# # Gets all red cars.
|
||||
# cars_by_color.get "red"
|
||||
# # Returns something like:
|
||||
# # [ (@storage[42], 42)
|
||||
# # , (@storage[91], 91)
|
||||
# # ]
|
||||
# # Each tuple is composed of a car and its key in the database.
|
||||
# ```
|
||||
# WARNING: throws a MissingEntry exception on non-existing partition.
|
||||
def get_with_keys(partition : String) : Array(Tuple(V, Int32))
|
||||
partition_directory = indexing_directory partition
|
||||
raise MissingEntry.new(@name, partition) unless Dir.exists? partition_directory
|
||||
|
||||
r_value = Array(Tuple(V, Int32)).new
|
||||
|
||||
Dir.each_child partition_directory do |child|
|
||||
key = get_key child
|
||||
r_value << { @storage[key], key }
|
||||
end
|
||||
|
||||
r_value
|
||||
end
|
||||
|
||||
# Deletes all entries within the provided partition.
|
||||
@ -125,6 +142,7 @@ class DODB::Partition(V) < DODB::Indexer(V)
|
||||
# ```
|
||||
# cars_by_color.delete "red" # Deletes all red cars.
|
||||
# ```
|
||||
# WARNING: throws a MissingEntry exception on non-existing partition.
|
||||
def delete(partition : String)
|
||||
delete partition, do true end
|
||||
end
|
||||
@ -137,17 +155,10 @@ class DODB::Partition(V) < DODB::Indexer(V)
|
||||
# car.name == "Corvet"
|
||||
# end
|
||||
# ```
|
||||
# TODO: in case the partition is left empty, should the partition's directory be removed?
|
||||
def delete(partition, &matcher : Proc(V, Bool))
|
||||
partition_directory = indexing_directory partition
|
||||
|
||||
return unless Dir.exists? partition_directory
|
||||
|
||||
Dir.each_child partition_directory do |child|
|
||||
key = get_key child
|
||||
item = @storage[key]
|
||||
|
||||
if yield item
|
||||
# WARNING: throws a MissingEntry exception on non-existing partition.
|
||||
def delete(partition : String, &matcher : Proc(V, Bool))
|
||||
get_with_keys(partition).each do |entry, key|
|
||||
if yield entry
|
||||
@storage.delete key
|
||||
end
|
||||
end
|
||||
@ -213,12 +224,6 @@ class DODB::CachedPartition(V) < DODB::Partition(V)
|
||||
# WARNING: used for internal operations, do not change its content or access it directly.
|
||||
property data = Hash(String, Array(Int32)).new
|
||||
|
||||
# Clears the cache and removes the `#indexing_directory`.
|
||||
def nuke_index
|
||||
super
|
||||
data.clear
|
||||
end
|
||||
|
||||
# Indexes the value on the file-system as `DODB::Partition#index` but also puts the index in a cache.
|
||||
#
|
||||
# NOTE: used for internal operations.
|
||||
@ -253,6 +258,9 @@ class DODB::CachedPartition(V) < DODB::Partition(V)
|
||||
end
|
||||
|
||||
# Gets partition entries and the database key for each entry.
|
||||
# In `DODB::CachedPartition`, `#get_with_keys(partition : String)` is modified to retrieve data keys from
|
||||
# the index cache.
|
||||
# In case the data isn't already in the cache, it is retrieved from the file-system.
|
||||
#
|
||||
# ```
|
||||
# # For example, get all red cars.
|
||||
@ -263,6 +271,7 @@ class DODB::CachedPartition(V) < DODB::Partition(V)
|
||||
# # ]
|
||||
# # Each tuple is composed of a car and its key in the database.
|
||||
# ```
|
||||
# WARNING: throws a MissingEntry exception on non-existing partition.
|
||||
def get_with_keys(partition : String) : Array(Tuple(V, Int32))
|
||||
r_value = Array(Tuple(V, Int32)).new
|
||||
|
||||
@ -272,73 +281,17 @@ class DODB::CachedPartition(V) < DODB::Partition(V)
|
||||
r_value << { @storage[data_key], 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], get_key child }
|
||||
end
|
||||
|
||||
# Gets data from the database representation on the file-system.
|
||||
r_value = super(partition)
|
||||
@data[partition] = r_value.map &.[1]
|
||||
end
|
||||
r_value
|
||||
end
|
||||
|
||||
# Gets partition entries from the cache or the file-system representation.
|
||||
#
|
||||
# ```
|
||||
# # For example, get all red cars.
|
||||
# cars_by_color.get "red"
|
||||
# ```
|
||||
# NOTE: returns an empty list on empty or non-existing partition.
|
||||
def get(partition : String) : Array(V)
|
||||
r_value = Array(V).new
|
||||
|
||||
# In case the partition is cached.
|
||||
if keys = @data[partition]?
|
||||
keys.each do |data_key|
|
||||
r_value << @storage[data_key]
|
||||
end
|
||||
else
|
||||
# The keys to put in the partition.
|
||||
p_value = Array(Int32).new
|
||||
|
||||
# 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|
|
||||
key = get_key child
|
||||
r_value << @storage[key]
|
||||
p_value << key
|
||||
end
|
||||
|
||||
@data[partition] = p_value
|
||||
end
|
||||
r_value
|
||||
end
|
||||
|
||||
# Deletes entries within the provided partition and matching the provided block of code,
|
||||
# both from the file-system representation and from the cache.
|
||||
#
|
||||
# ```
|
||||
# # Deletes all red Corvets.
|
||||
# cars_by_color.delete "red", do |car|
|
||||
# car.name == "Corvet"
|
||||
# end
|
||||
# ```
|
||||
# TODO: in case the partition is left empty, should the partition be removed from the cache?
|
||||
def delete(partition : String, &matcher : Proc(V, Bool))
|
||||
# Use `get_with_keys` to retrieve data on-disk, if necessary.
|
||||
new_partition = get_with_keys(partition).map(&.[1]).select do |key|
|
||||
item = @storage[key]
|
||||
! yield item
|
||||
end
|
||||
|
||||
@data[partition] = new_partition
|
||||
|
||||
super(partition, &matcher)
|
||||
# Clears the cache and removes the `#indexing_directory`.
|
||||
def nuke_index
|
||||
super
|
||||
data.clear
|
||||
end
|
||||
end
|
||||
|
||||
@ -393,52 +346,19 @@ class DODB::RAMOnlyPartition(V) < DODB::CachedPartition(V)
|
||||
# # ]
|
||||
# # Each tuple is composed of a car and its key in the database.
|
||||
# ```
|
||||
# WARNING: FOR CONSISTENCY, throws a MissingEntry exception on non-existing partition.
|
||||
def get_with_keys(partition : String) : Array(Tuple(V, Int32))
|
||||
r_value = Array(Tuple(V, Int32)).new
|
||||
if keys = @data[partition]?
|
||||
keys.each do |data_key|
|
||||
r_value << { @storage[data_key], data_key }
|
||||
end
|
||||
else
|
||||
raise MissingEntry.new(@name, partition)
|
||||
end
|
||||
r_value
|
||||
end
|
||||
|
||||
# Gets partition entries from the in-memory partition cache.
|
||||
#
|
||||
# ```
|
||||
# # Get all red cars.
|
||||
# cars_by_color.get "red"
|
||||
# ```
|
||||
# NOTE: returns an empty list on empty or non-existing partition.
|
||||
def get(partition : String) : Array(V)
|
||||
r_value = Array(V).new
|
||||
if keys = @data[partition]?
|
||||
keys.each do |data_key|
|
||||
r_value << @storage[data_key]
|
||||
end
|
||||
end
|
||||
r_value
|
||||
end
|
||||
|
||||
# Deletes entries within the provided partition and matching the provided block of code.
|
||||
#
|
||||
# ```
|
||||
# # Deletes all red Corvets.
|
||||
# cars_by_color.delete "red", do |car|
|
||||
# car.name == "Corvet"
|
||||
# end
|
||||
# ```
|
||||
# TODO: in case the partition is left empty, should it be removed from the cache?
|
||||
def delete(partition : String, &matcher : Proc(V, Bool))
|
||||
if keys = @data[partition]?
|
||||
new_partition = keys.select do |key|
|
||||
item = @storage[key]
|
||||
! yield item
|
||||
end
|
||||
@data[partition] = new_partition
|
||||
end
|
||||
end
|
||||
|
||||
# Clears the cache.
|
||||
def nuke_index
|
||||
data.clear
|
||||
|
@ -64,14 +64,12 @@ class DODB::Tags(V) < DODB::Indexer(V)
|
||||
end
|
||||
|
||||
def index(key : String, value : V)
|
||||
indices = key_proc.call(value)
|
||||
return if indices.is_a? NoIndex
|
||||
tags = key_proc.call(value)
|
||||
return if tags.is_a? NoIndex
|
||||
|
||||
indices.each do |i|
|
||||
symlink = get_tagged_entry_path(i, key)
|
||||
tags.each do |tag|
|
||||
symlink = get_tagged_entry_path(tag, key)
|
||||
Dir.mkdir_p ::File.dirname symlink
|
||||
# FIXME: Should not happen anymore. Should we remove this?
|
||||
::File.delete symlink if ::File.exists? symlink
|
||||
::File.symlink get_data_symlink(key), symlink
|
||||
end
|
||||
end
|
||||
@ -79,11 +77,11 @@ class DODB::Tags(V) < DODB::Indexer(V)
|
||||
# :inherit:
|
||||
# TODO: in case the tag is left empty, should the tag directory be removed?
|
||||
def deindex(key : String, value : V)
|
||||
indices = key_proc.call(value)
|
||||
return if indices.is_a? NoIndex
|
||||
tags = key_proc.call(value)
|
||||
return if tags.is_a? NoIndex
|
||||
|
||||
indices.each do |i|
|
||||
symlink = get_tagged_entry_path(i, key)
|
||||
tags.each do |tag|
|
||||
symlink = get_tagged_entry_path(tag, key)
|
||||
|
||||
begin
|
||||
::File.delete symlink
|
||||
@ -95,7 +93,7 @@ class DODB::Tags(V) < DODB::Indexer(V)
|
||||
# Gets tag entries (and their keys) from the file-system representation of the tag.
|
||||
#
|
||||
# ```
|
||||
# # Get all slow cars.
|
||||
# # Gets all slow cars.
|
||||
# cars_by_keywords.get "slow"
|
||||
# # Returns something like:
|
||||
# # [ (@storage[42], 42)
|
||||
@ -273,11 +271,11 @@ class DODB::CachedTags(V) < DODB::Tags(V)
|
||||
property data = Hash(String, Array(Int32)).new
|
||||
|
||||
def index(key : String, value : V)
|
||||
indices = key_proc.call value
|
||||
return if indices.is_a? NoIndex
|
||||
tags = key_proc.call value
|
||||
return if tags.is_a? NoIndex
|
||||
super(key, value)
|
||||
|
||||
indices.each do |tag|
|
||||
tags.each do |tag|
|
||||
array = if v = @data[tag]?
|
||||
v
|
||||
else
|
||||
@ -292,11 +290,11 @@ class DODB::CachedTags(V) < DODB::Tags(V)
|
||||
# :inherit:
|
||||
# TODO: in case the tag is left empty, should it be removed from the cache?
|
||||
def deindex(key : String, value : V)
|
||||
indices = key_proc.call value
|
||||
return if indices.is_a? NoIndex
|
||||
tags = key_proc.call value
|
||||
return if tags.is_a? NoIndex
|
||||
super(key, value)
|
||||
|
||||
indices.each do |tag|
|
||||
tags.each do |tag|
|
||||
if v = @data[tag]?
|
||||
v.delete key.to_i
|
||||
@data[tag] = v
|
||||
@ -320,22 +318,16 @@ class DODB::CachedTags(V) < DODB::Tags(V)
|
||||
def get_with_keys(tag : String) : Array(Tuple(V, Int32))
|
||||
r_value = Array(Tuple(V, Int32)).new
|
||||
|
||||
# In case the tag is cached.
|
||||
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
|
||||
|
||||
Dir.each_child tag_directory do |child|
|
||||
r_value << { @storage[get_key child], get_key child }
|
||||
end
|
||||
|
||||
# Gets data from the database representation on the file-system.
|
||||
r_value = super(tag)
|
||||
@data[tag] = r_value.map &.[1]
|
||||
end
|
||||
|
||||
r_value
|
||||
end
|
||||
|
||||
@ -363,10 +355,10 @@ end
|
||||
# NOTE: for an fs representation but still fast for retrieval, see `CachedTags`.
|
||||
class DODB::RAMOnlyTags(V) < DODB::CachedTags(V)
|
||||
def index(key : String, value : V)
|
||||
indices = key_proc.call value
|
||||
return if indices.is_a? NoIndex
|
||||
tags = key_proc.call value
|
||||
return if tags.is_a? NoIndex
|
||||
|
||||
indices.each do |tag|
|
||||
tags.each do |tag|
|
||||
array = if v = @data[tag]?
|
||||
v
|
||||
else
|
||||
@ -379,10 +371,10 @@ class DODB::RAMOnlyTags(V) < DODB::CachedTags(V)
|
||||
end
|
||||
|
||||
def deindex(key : String, value : V)
|
||||
indices = key_proc.call value
|
||||
return if indices.is_a? NoIndex
|
||||
tags = key_proc.call value
|
||||
return if tags.is_a? NoIndex
|
||||
|
||||
indices.each do |tag|
|
||||
tags.each do |tag|
|
||||
if v = @data[tag]?
|
||||
v.delete key.to_i
|
||||
@data[tag] = v
|
||||
@ -414,23 +406,6 @@ class DODB::RAMOnlyTags(V) < DODB::CachedTags(V)
|
||||
r_value
|
||||
end
|
||||
|
||||
# Gets tag entries from the in-memory tag cache.
|
||||
#
|
||||
# ```
|
||||
# # Get all slow cars.
|
||||
# cars_by_keywords.get "slow"
|
||||
# ```
|
||||
# NOTE: returns an empty list on empty or non-existing tag.
|
||||
def get(tag : String) : Array(V)
|
||||
r_value = Array(V).new
|
||||
if keys = @data[tag]?
|
||||
keys.each do |data_key|
|
||||
r_value << @storage[data_key]
|
||||
end
|
||||
end
|
||||
r_value
|
||||
end
|
||||
|
||||
# Clears the cache.
|
||||
def nuke_index
|
||||
data.clear
|
||||
|
Loading…
Reference in New Issue
Block a user