Class: Redis::Bitops::SparseBitmap

Inherits:
Bitmap
  • Object
show all
Defined in:
lib/redis/bitops/sparse_bitmap.rb

Overview

A sparse bitmap using multiple key to store its data to save memory.

Note: When adding new public methods, revise the LazyEvaluation module.

Instance Method Summary collapse

Methods inherited from Bitmap

#<<, #[], #[]=, #root_key

Constructor Details

#initialize(root_key, redis, bytes_per_chunk = nil) ⇒ SparseBitmap

Creates a new sparse bitmap stored in ‘redis’ under ‘root_key’.



14
15
16
17
# File 'lib/redis/bitops/sparse_bitmap.rb', line 14

def initialize(root_key, redis, bytes_per_chunk = nil)
  @bytes_per_chunk = bytes_per_chunk || Redis::Bitops.configuration.default_bytes_per_chunk
  super(root_key, redis)
end

Instance Method Details

#bitcountObject

Returns the number of set bits.



21
22
23
# File 'lib/redis/bitops/sparse_bitmap.rb', line 21

def bitcount
  chunk_keys.map { |key| @redis.bitcount(key) }.reduce(:+) || 0
end

#bitmap_factoryObject

Returns lambda creating SparseBitmap objects using @redis as the connection.



62
63
64
# File 'lib/redis/bitops/sparse_bitmap.rb', line 62

def bitmap_factory
  lambda { |key| @redis.sparse_bitmap(key, @bytes_per_chunk) }
end

#bitop(op, *operands, result) ⇒ Object

Redis BITOP operator ‘op’ (one of :and, :or, :xor or :not) on operands (bitmaps). The result is stored in ‘result’.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/redis/bitops/sparse_bitmap.rb', line 37

def bitop(op, *operands, result)
  # TODO: Optimization is possible for AND. We can use an intersection of each operand
  # chunk numbers to minimize the number of database accesses.

  all_keys = self.chunk_keys + (operands.map(&:chunk_keys).flatten! || [])
  unique_chunk_numbers = Set.new(chunk_numbers(all_keys))

  maybe_multi(level: :bitmap, watch: all_keys) do
    unique_chunk_numbers.each do |i|
      @redis.bitop(op, result.chunk_key(i), self.chunk_key(i), *operands.map { |o| o.chunk_key(i) })
    end
  end
  result
end

#chunk_key(i) ⇒ Object



56
57
58
# File 'lib/redis/bitops/sparse_bitmap.rb', line 56

def chunk_key(i)
  "#{@root_key}:chunk:#{i}"
end

#chunk_keysObject



52
53
54
# File 'lib/redis/bitops/sparse_bitmap.rb', line 52

def chunk_keys
  @redis.keys("#{@root_key}:chunk:*")
end

#copy_to(dest) ⇒ Object

Copy this bitmap to ‘dest’ bitmap.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/redis/bitops/sparse_bitmap.rb', line 68

def copy_to(dest)

  # Copies all source chunks to destination chunks and deletes remaining destination chunk keys.

  source_keys = self.chunk_keys
  dest_keys = dest.chunk_keys

  maybe_multi(level: :bitmap, watch: source_keys + dest_keys) do
    source_chunks = Set.new(chunk_numbers(source_keys))
    source_chunks.each do |i|
      copy(chunk_key(i), dest.chunk_key(i))
    end
    dest_chunks = Set.new(chunk_numbers(dest_keys))
    (dest_chunks - source_chunks).each do |i|
      @redis.del(dest.chunk_key(i))
    end
  end
end

#delete!Object

Deletes the bitmap and all its keys.



27
28
29
30
31
32
# File 'lib/redis/bitops/sparse_bitmap.rb', line 27

def delete!
  chunk_keys.each do |key|
    @redis.del(key)
  end
  super
end