First implementation of FIFO/Stacked.

This commit is contained in:
Philippe PITTOLI 2024-05-23 09:20:58 +02:00
parent d46e0d2ddf
commit b38e3f31ba
3 changed files with 46 additions and 8 deletions

View File

@ -1,4 +1,5 @@
require "file_utils"
require "json"
require "./fifo.cr" # FIFO class to implement a cache policy.
require "./dodb/*" # Databases and indexes (basic indexes, partitions, tags, etc.).

View File

@ -57,19 +57,18 @@ class DODB::Storage::Cached(V) < DODB::Storage(V)
end
end
# Getting data from the hash in RAM.
# Gets data from the hash in RAM.
def []?(key : Int32) : V?
@data[key]
rescue e
# FIXME: rescues any error the same way.
return nil
self[key] rescue nil
end
# :inherit:
# Gets the data with the *key*.
# In case the data is missing, returns an exception `DODB::MissingEntry`.
#
# Data needs to be cloned in case it will be modified, otherwise it will mess with indexes.
#
# WARNING: data isn't cloned.
# WARNING: may raise a MissingEntry exception.
def [](key : Int32) : V
@data[key] rescue raise MissingEntry.new(key)
end

View File

@ -1,15 +1,53 @@
# Stacked database: only recently requested entries are kept in memory.
#
# Most recently used entries are in cache and put on the top of the stack.
# Least recently used entries may be removed from the cache in order to keep the amount of memory used reasonable.
#
# This database is relevant for high demand applications;
# which means both a high number of entries (data cannot fit entirely in RAM),
# and a high number of requests.
# Typically a retail website.
# In such applications, the "keep the most recently used data in cache" policy works since new users
# constantly push commonly requested data on top of the stack.
#
# ```
# # Creates a DODB stacked database.
# car_database = DODB::Storage::Stacked.new "/path/to/db"
#
# # Creates a (cached) index.
# cars_by_name = car_database.new_index "name", &.name
#
# # Add a value in the database.
# car_database << Car.new "Corvet"
# ```
# On the file-system:
# ```plain
# storage
# ├── data
# │   └── 0000000000
# ├── indices
# │   └── by_name <- the "name" basic index
# │   └── Corvet -> ../../data/0000000000
# ```
#
# NOTE: fast for frequently requested data and requires a stable (and configurable) amount of memory.
# TODO: not yet implemented.
class DODB::Storage::Stacked(V) < DODB::Storage::Cached(V)
# The maximum number of accepted entries in the cache.
property max_entries : Int32
# The *stack* a simple FIFO instance where the key of the requested data is pushed.
# In case the number of stored entries exceeds what is allowed, the least recently used entry is removed.
property stack : FIFO(Int32)
# Initializes the `StackedDataBase` with a maximum number of entries in the cache.
def initialize(directory_name : String, @max_entries : Int32 = 100_000)
super directory_name
@stack = FIFO(Int32).new @max_entries
end
def [](key : Int32) : V
val = @data[key] rescue raise MissingEntry.new(key)
if entry_to_remove = @stack << key
@data.delete entry_to_remove
end
val
end
end