Class: PureCDB::Reader
- Includes:
- Enumerable
- Defined in:
- lib/purecdb/reader.rb
Overview
Read 32 bit or 64 bit CDB files.
Constant Summary
Constants inherited from Base
Base::CDB64_MAGIC, Base::DEFAULT_HASHPTR_SIZE, Base::DEFAULT_LENGTH_SIZE, Base::DEFAULT_NUM_HASHES
Instance Attribute Summary
Attributes inherited from Base
#hashptr_size, #length_size, #mode, #num_hashes
Class Method Summary collapse
-
.open(target, *options, &block) ⇒ Object
Alternative to PureCDB::Reader.new(target,options) ..
Instance Method Summary collapse
-
#close ⇒ Object
Close the CDB file.
-
#each ⇒ Object
Iterate over all key/value pairs in the order they occur in the file.
-
#initialize(target, *options) ⇒ Reader
constructor
Open a CDB file for reading.
-
#mmap? ⇒ Boolean
Is the file mmap’ed? Note that this may in theory return true right after opening the file, but return false after attempting to read if the attempt to read from the mmap object fails for whatever reason.
-
#values(key) ⇒ Object
Returns all values for
keyin an array.
Methods inherited from Base
#hash, #hash_size, #hashref_size, #set_mode, #set_stream
Constructor Details
#initialize(target, *options) ⇒ Reader
Open a CDB file for reading.
:call-seq:
r = PureCDB::Reader.new(file)
r = PureCDB::Reader.new(file, )
PureCDB::Reader.new(file) {|r| ... }
PureCDB::Reader.new(file, ) {|r| ... }
file can be a String or any object that meets the minimum requirements, which means having #sysseek, #sysopen to and #sysclose which does not arbitrarily sttop access ot it.
If Mmap is available, the code will attempt to use it if target is a filename
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/purecdb/reader.rb', line 29 def initialize target, * if target.is_a?(String) @name = target @io = File.new(target,"rb") raise "Unable to open file #{target}" if !@io else set_stream(target) end @io.sysseek(-8,IO::SEEK_END) tail = @io.sysread(8) raise "Unable to read trailing 8 bytes for magic cookie" if tail.size != 8 mode = tail == CDB64_MAGIC ? 64 : 32 super * if @mode == :detect set_mode(mode) elsif @mode != mode raise "#{mode}bit mode detected in file; options request #{@mode}bit mode" end @m = FFI::Mmap.new(target,"r", FFI::Mmap::MAP_SHARED) rescue nil read_hashes raise "Invalid File (Hashes are all empty)" if @hashes.uniq == [0] if block_given? yield(self) close else end end |
Class Method Details
.open(target, *options, &block) ⇒ Object
Alternative to PureCDB::Reader.new(target,options) ..
77 78 79 |
# File 'lib/purecdb/reader.rb', line 77 def self.open(target, *, &block) Reader.new(target, *, &block) end |
Instance Method Details
#close ⇒ Object
Close the CDB file
84 85 86 87 88 89 |
# File 'lib/purecdb/reader.rb', line 84 def close @io.close if @io @m.unmap if @m @m = nil @io = nil end |
#each ⇒ Object
Iterate over all key/value pairs in the order they occur in the file. This is not sorted or insertion order.
each will yield each key,value pair separately even when a key is duplicate.
96 97 98 99 100 101 102 103 104 |
# File 'lib/purecdb/reader.rb', line 96 def each pos = hash_size hoff0 = @hashes[0] while pos < hoff0 key, value = *read_entry(pos) yield(key,value) pos += key.length + value.length + hashref_size end end |
#mmap? ⇒ Boolean
Is the file mmap’ed? Note that this may in theory return true right after opening the file, but return false after attempting to read if the attempt to read from the mmap object fails for whatever reason.
I’m not sure that can ever happen, but to be 100% sure, check after a lookup
70 71 72 |
# File 'lib/purecdb/reader.rb', line 70 def mmap? @m.nil? == false end |
#values(key) ⇒ Object
Returns all values for key in an array
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/purecdb/reader.rb', line 107 def values(key) h = hash(key) hoff = @hashes[(h % 256)*2] hlen = @hashes[(h % 256)*2 + 1] return [] if hlen == 0 off = (h / 256) % hlen vals = [] # FIXME: Is this potentially an infinite loop (if full)? # Easy to avoid by exiting if off reaches the same value twice. while (slot = read(hoff + off * hashref_size .. hoff + off * hashref_size + hashref_size - 1)) && (dslot = ary_unpack(slot,2)) && dslot[1] != 0 if dslot[0] == h pos = dslot[1] rkey, value = read_entry(pos) if rkey == key vals << value end end off = (off + 1) % hlen end return vals end |