dodb.cr/src/dodb/index.cr

82 lines
1.7 KiB
Crystal
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

require "file_utils"
require "json"
require "./exceptions.cr"
require "./indexer.cr"
class DODB::Index(V) < DODB::Indexer(V)
property name : String
property key_proc : Proc(V, String)
getter storage_root : String
def initialize(@storage_root, @name, @key_proc)
Dir.mkdir_p dir_path_indices
end
def check!(key, value, old_value)
index_key = key_proc.call value
symlink = file_path_index index_key.to_s
# FIXME: Check its not pointing to “old_value”, if any, before raising.
if ::File.exists? symlink
if old_value
old_key = key_proc.call old_value
return if symlink == file_path_index old_key.to_s
end
raise IndexOverload.new "Index '#{@name}' is overloaded for key '#{key}'"
end
end
def index(key, value)
index_key = key_proc.call value
symlink = file_path_index index_key
Dir.mkdir_p ::File.dirname symlink
# FIXME: Now that this is done in check!, can we remove it?
if ::File.exists? symlink
raise Exception.new "symlink already exists: #{symlink}"
end
::File.symlink get_data_symlink_index(key), symlink
end
def deindex(key, value)
index_key = key_proc.call value
symlink = file_path_index index_key
::File.delete symlink
end
def get(index : String) : V
file_path = file_path_index index
raise MissingEntry.new(@name, index) unless ::File.exists? file_path
V.from_json ::File.read file_path
end
def get?(index : String) : V?
get index
rescue MissingEntry
nil
end
private def dir_path_indices
"#{@storage_root}/indices/by_#{@name}"
end
private def file_path_index(index_key : String)
"#{dir_path_indices}/#{index_key}.json"
end
private def get_data_symlink_index(key : String)
"../../data/#{key}.json"
end
end