From ffce08b36cc52b3493dd2dcac2ca1fcc65c83213 Mon Sep 17 00:00:00 2001 From: Karchnu Date: Sun, 15 Nov 2020 03:07:02 +0100 Subject: [PATCH] WIP: CBOR implementation. --- shard.yml | 4 ++++ spec/test-data.cr | 6 +++--- src/cached.cr | 4 ++-- src/dodb.cr | 12 ++++++++---- src/dodb/directed_graph.cr | 18 +++++++++--------- src/dodb/index.cr | 10 +++++----- src/dodb/partition.cr | 12 ++++++------ src/dodb/tags.cr | 10 +++++----- 8 files changed, 42 insertions(+), 34 deletions(-) diff --git a/shard.yml b/shard.yml index 124b49b..7aa40fd 100644 --- a/shard.yml +++ b/shard.yml @@ -8,4 +8,8 @@ authors: description: | Simple, embeddable Document-Oriented DataBase in Crystal. +dependencies: + cbor: + git: https://git.baguette.netlib.re/Baguette/crystal-cbor + license: MIT diff --git a/spec/test-data.cr b/spec/test-data.cr index 2df42ed..97655e0 100644 --- a/spec/test-data.cr +++ b/spec/test-data.cr @@ -1,10 +1,10 @@ require "uuid" -require "json" +require "cbor" # FIXME: Split the test data in separate files. We don’t care about those here. class Ship - include JSON::Serializable + include CBOR::Serializable def_clone @@ -65,7 +65,7 @@ end # This will be used for migration testing, but basically it’s a variant of # the class above, a few extra fields, a few missing ones. class PrimitiveShip - include JSON::Serializable + include CBOR::Serializable property id : String property name : String diff --git a/src/cached.cr b/src/cached.cr index f2a7569..26a822f 100644 --- a/src/cached.cr +++ b/src/cached.cr @@ -1,5 +1,5 @@ require "file_utils" -require "json" +require "cbor" class Hash(K,V) def reverse @@ -63,7 +63,7 @@ class DODB::CachedDataBase(V) < DODB::Storage(V) # Avoids corruption in case the application crashes while writing. file_path(index).tap do |path| - ::File.write "#{path}.new", value.to_json + ::File.write "#{path}.new", value.to_cbor ::FileUtils.mv "#{path}.new", path end diff --git a/src/dodb.cr b/src/dodb.cr index 0e22ad6..6331dfd 100644 --- a/src/dodb.cr +++ b/src/dodb.cr @@ -1,8 +1,12 @@ require "file_utils" -require "json" +require "cbor" require "./dodb/*" +module DODB + class_property file_extension = ".cbor" +end + abstract class DODB::Storage(V) property directory_name : String @@ -200,7 +204,7 @@ abstract class DODB::Storage(V) end private def file_path(key : Int32) - "#{data_path}/%010i.json" % key + "#{data_path}/%010i#{DODB.file_extension}" % key end private def locks_directory : String @@ -216,7 +220,7 @@ abstract class DODB::Storage(V) end private def read(file_path : String) - V.from_json ::File.read file_path + V.from_cbor ::File.read(file_path).to_slice end private def remove_data! @@ -294,7 +298,7 @@ class DODB::DataBase(V) < DODB::Storage(V) # Avoids corruption in case the application crashes while writing. file_path(index).tap do |path| - ::File.write "#{path}.new", value.to_json + ::File.write "#{path}.new", value.to_cbor ::FileUtils.mv "#{path}.new", path end diff --git a/src/dodb/directed_graph.cr b/src/dodb/directed_graph.cr index 6c39c74..37b0f78 100644 --- a/src/dodb/directed_graph.cr +++ b/src/dodb/directed_graph.cr @@ -1,5 +1,5 @@ require "file_utils" -require "json" +require "cbor" require "./indexer.cr" @@ -78,7 +78,7 @@ class DODB::DirectedGraph(V) < DODB::Indexer(V) return r_value unless Dir.exists? incoming_links_directory Dir.each_child incoming_links_directory do |child| - r_value << V.from_json ::File.read "#{incoming_links_directory}/#{child}" + r_value << V.from_cbor ::File.read("#{incoming_links_directory}/#{child}").to_slice end r_value @@ -91,7 +91,7 @@ class DODB::DirectedGraph(V) < DODB::Indexer(V) return r_value unless Dir.exists? incoming_links_directory Dir.each_child incoming_links_directory do |child| - r_value << child.sub /.json$/, "" + r_value << child.sub /#{DODB.file_extension}$/, "" end r_value @@ -107,7 +107,7 @@ class DODB::DirectedGraph(V) < DODB::Indexer(V) return r_value unless Dir.exists? outgoing_links_directory Dir.each_child outgoing_links_directory do |child| - r_value << V.from_json ::File.read "#{outgoing_links_directory}/#{child}" + r_value << V.from_cbor ::File.read("#{outgoing_links_directory}/#{child}").to_slice end r_value @@ -120,7 +120,7 @@ class DODB::DirectedGraph(V) < DODB::Indexer(V) return r_value unless Dir.exists? outgoing_links_directory Dir.each_child outgoing_links_directory do |child| - r_value << child.sub /.json$/, "" + r_value << child.sub /#{DODB.file_extension}$/, "" end r_value @@ -132,7 +132,7 @@ class DODB::DirectedGraph(V) < DODB::Indexer(V) private def get_key(path : String) : Int32 ::File.readlink(path) - .sub(/\.json$/, "") + .sub(/#{DODB.file_extension}$/, "") .sub(/^.*\//, "") .to_i end @@ -142,7 +142,7 @@ class DODB::DirectedGraph(V) < DODB::Indexer(V) end private def get_node_symlink(node : String, key : String) - "#{indexing_directory node}/#{key}.json" + "#{indexing_directory node}/#{key}#{DODB.file_extension}" end private def get_outgoing_links_directory(node) @@ -162,13 +162,13 @@ class DODB::DirectedGraph(V) < DODB::Indexer(V) end private def get_data_symlink(key : String) - "../../../../data/#{key}.json" + "../../../../data/#{key}#{DODB.file_extension}" end # Roughly matches Index#file_path_index, but works if @storage_root # is an absolute path as well. private def get_cross_index_data_symlink(node : String) - "../../../../indices/by_#{@index.name}/#{node}.json" + "../../../../indices/by_#{@index.name}/#{node}#{DODB.file_extension}" end end diff --git a/src/dodb/index.cr b/src/dodb/index.cr index 89d28de..e601e2d 100644 --- a/src/dodb/index.cr +++ b/src/dodb/index.cr @@ -1,5 +1,5 @@ require "file_utils" -require "json" +require "cbor" require "./exceptions.cr" require "./indexer.cr" @@ -63,7 +63,7 @@ class DODB::Index(V) < DODB::Indexer(V) raise MissingEntry.new(@name, index) unless ::File.exists? file_path - V.from_json ::File.read file_path + V.from_cbor ::File.read(file_path).to_slice end def get?(index : String) : V? @@ -96,7 +96,7 @@ class DODB::Index(V) < DODB::Indexer(V) raise MissingEntry.new(@name, index) unless ::File.exists? file_path ::File.readlink(file_path) - .sub(/\.json$/, "") + .sub(/#{DODB.file_extension}$/, "") .sub(/^.*\//, "") .to_i end @@ -142,11 +142,11 @@ class DODB::Index(V) < DODB::Indexer(V) # FIXME: Now that it’s being used outside of this class, name it properly. def file_path_index(index_key : String) - "#{indexing_directory}/#{index_key}.json" + "#{indexing_directory}/#{index_key}#{DODB.file_extension}" end private def get_data_symlink_index(key : String) - "../../data/#{key}.json" + "../../data/#{key}#{DODB.file_extension}" end end diff --git a/src/dodb/partition.cr b/src/dodb/partition.cr index d0d4954..c5c69fc 100644 --- a/src/dodb/partition.cr +++ b/src/dodb/partition.cr @@ -1,5 +1,5 @@ require "file_utils" -require "json" +require "cbor" require "./indexer.cr" @@ -47,7 +47,7 @@ class DODB::Partition(V) < DODB::Indexer(V) return r_value unless Dir.exists? partition_directory Dir.each_child partition_directory do |child| - r_value << V.from_json ::File.read "#{partition_directory}/#{child}" + r_value << V.from_cbor ::File.read("#{partition_directory}/#{child}").to_slice end r_value @@ -64,7 +64,7 @@ class DODB::Partition(V) < DODB::Indexer(V) Dir.each_child partition_directory do |child| path = "#{partition_directory}/#{child}" - item = V.from_json ::File.read path + item = V.from_cbor ::File.read(path).to_slice if yield item key = get_key path @@ -80,7 +80,7 @@ class DODB::Partition(V) < DODB::Indexer(V) private def get_key(path : String) : Int32 ::File.readlink(path) - .sub(/\.json$/, "") + .sub(/#{DODB.file_extension}$/, "") .sub(/^.*\//, "") .to_i end @@ -90,11 +90,11 @@ class DODB::Partition(V) < DODB::Indexer(V) end private def get_partition_symlink(partition : String, key : String) - "#{indexing_directory partition}/#{key}.json" + "#{indexing_directory partition}/#{key}#{DODB.file_extension}" end private def get_data_symlink(key : String) - "../../../data/#{key}.json" + "../../../data/#{key}#{DODB.file_extension}" end end diff --git a/src/dodb/tags.cr b/src/dodb/tags.cr index f7b0e85..63bd013 100644 --- a/src/dodb/tags.cr +++ b/src/dodb/tags.cr @@ -1,5 +1,5 @@ require "file_utils" -require "json" +require "cbor" class DODB::Tags(V) < DODB::Indexer(V) property name : String @@ -76,8 +76,8 @@ class DODB::Tags(V) < DODB::Indexer(V) Dir.each_child partition_directory do |child| r_value << { - V.from_json(::File.read("#{partition_directory}/#{child}")), - File.basename(child).gsub(/\.json$/, "").to_i + V.from_cbor(::File.read("#{partition_directory}/#{child}").to_slice), + File.basename(child).gsub(/#{DODB.file_extension}$/, "").to_i } end @@ -104,10 +104,10 @@ class DODB::Tags(V) < DODB::Indexer(V) end private def get_tagged_entry_path(key : String, indices : Array(String)) - "#{indexing_directory}#{indices.map { |i| "/other-tags/#{i}" }.join}/data/#{key}.json" + "#{indexing_directory}#{indices.map { |i| "/other-tags/#{i}" }.join}/data/#{key}#{DODB.file_extension}" end private def get_data_symlink(key : String, indices : Array(String)) - "../../../#{indices.map { "../../" }.join}/data/#{key}.json" + "../../../#{indices.map { "../../" }.join}/data/#{key}#{DODB.file_extension}" end end