HEX
Server: Apache
System: Linux pdx1-shared-a1-38 6.6.104-grsec-jammy+ #3 SMP Tue Sep 16 00:28:11 UTC 2025 x86_64
User: mmickelson (3396398)
PHP: 8.1.31
Disabled: NONE
Upload Files
File: //lib/ruby/vendor_ruby/moneta/adapters/lruhash.rb
module Moneta
  module Adapters
    # LRUHash backend
    #
    # Based on Hashery::LRUHash but simpler and measures both memory usage and hash size.
    #
    # @api public
    class LRUHash
      include Defaults
      include IncrementSupport
      include CreateSupport

      DEFAULT_MAX_SIZE = 1024000
      DEFAULT_MAX_COUNT = 10240

      # @param [Hash] options
      # @option options [Integer] :max_size (1024000) Maximum byte size of all values, nil disables the limit
      # @option options [Integer] :max_value (options[:max_size]) Maximum byte size of one value, nil disables the limit
      # @option options [Integer] :max_count (10240) Maximum number of values, nil disables the limit
      def initialize(options = {})
        @max_size = options.fetch(:max_size) { DEFAULT_MAX_SIZE }
        @max_count = options.fetch(:max_count) { DEFAULT_MAX_COUNT }
        @max_value = [options[:max_value], @max_size].compact.min
        clear
      end

      # (see Proxy#key?)
      def key?(key, options = {})
        @entry.key?(key)
      end

      # (see Proxy#load)
      def load(key, options = {})
        if entry = @entry[key]
          entry.insert_after(@list)
          entry.value
        end
      end

      # (see Proxy#store)
      def store(key, value, options = {})
        if @max_value && value.bytesize > @max_value
          delete(key)
        else
          if entry = @entry[key]
            @size -= entry.value.bytesize if @max_size
          else
            @entry[key] = entry = Entry.new
            entry.key = key
          end
          entry.value = value
          @size += entry.value.bytesize if @max_size
          entry.insert_after(@list)
          delete(@list.prev.key) while @list.next != @list.prev && (@max_size && @size > @max_size || @max_count && @entry.size > @max_count)
        end
        value
      end

      # (see Proxy#delete)
      def delete(key, options = {})
        if entry = @entry.delete(key)
          @size -= entry.value.bytesize if @max_size
          entry.unlink
          entry.value
        end
      end

      # (see Proxy#clear)
      def clear(options = {})
        @entry, @size = {}, 0
        @list = Entry.new
        @list.prev = @list.next = @list
        self
      end

      private

      class Entry
        attr_accessor :key, :value, :prev, :next

        def unlink
          @prev.next = @next if @prev
          @next.prev = @prev if @next
          @prev = @next = nil
        end

        def insert_after(entry)
          if entry.next != self
            unlink
            @next = entry.next
            @prev = entry
            entry.next.prev = self
            entry.next = self
          end
        end
      end
    end
  end
end