Class: Rubcask::Directory
- Inherits:
-
Object
- Object
- Rubcask::Directory
- Extended by:
- Forwardable
- Defined in:
- lib/rubcask/directory.rb
Class Method Summary collapse
-
.with_directory(dir, config: Config.new) {|directory| ... } ⇒ void
yields directory to the block and closes it after the block is terminated.
Instance Method Summary collapse
-
#[](key) ⇒ String?
Gets value associated with the key.
-
#[]=(key, value) ⇒ String
Set value associated with given key.
-
#clear_files ⇒ Object
Removes files that are not needed after the merge.
-
#close ⇒ Object
Closes all the files and the worker.
-
#delete(key) ⇒ Object
Remove entry associated with the key.
-
#each {|key, value| ... } ⇒ Object
Enumerator if block not given.
-
#each_key {|key| ... } ⇒ Object
Enumerator if block not given.
-
#generate_missing_hint_files! ⇒ Object
Generate hint files for data files that do not have hint files.
-
#initialize(dir, config: Config.new) ⇒ Directory
constructor
A new instance of Directory.
-
#key_count ⇒ Integer
Returns number of keys in the store.
-
#keys ⇒ Array<String>
Returns array of keys in store.
-
#merge ⇒ Object
Starts the merge operation.
-
#regenerate_hint_files! ⇒ Object
Generate hint files for all the data files.
-
#set_with_ttl(key, value, ttl) ⇒ String
Set value associated with given key with given ttl.
Constructor Details
#initialize(dir, config: Config.new) ⇒ Directory
Returns a new instance of Directory.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/rubcask/directory.rb', line 59 def initialize(dir, config: Config.new) @dir = dir @config = check_config(config) max_id = 0 files = dir_data_files @files = files.each_with_object({}) do |file, hash| next if File.executable?(file) if file.equal?(files.last) && File.size(file) < config.max_file_size hinted_file = open_write_file(file) @active = hinted_file else hinted_file = open_read_only_file(file) end id = hinted_file.id hash[id] = hinted_file max_id = id # dir_data_files returns an already sorted collection end @max_id = (config.threadsafe ? Concurrent::AtomicFixnum : Concurrency::FakeAtomicFixnum).new(max_id) @lock = config.threadsafe ? Concurrent::ReentrantReadWriteLock.new : Concurrency::FakeLock.new @worker = Worker::Factory.new_worker(@config.worker) @logger = Logger.new($stdin) @logger.level = Logger::INFO @merge_mutex = Thread::Mutex.new load_keydir! create_new_file! unless @active end |
Class Method Details
.with_directory(dir, config: Config.new) {|directory| ... } ⇒ void
This method returns an undefined value.
yields directory to the block and closes it after the block is terminated
36 37 38 39 40 41 42 43 |
# File 'lib/rubcask/directory.rb', line 36 def self.with_directory(dir, config: Config.new) directory = new(dir, config: config) begin yield directory ensure directory.close end end |
Instance Method Details
#[](key) ⇒ String?
key is always treated as byte array, encoding is ignored
Gets value associated with the key
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/rubcask/directory.rb', line 121 def [](key) key = normalize_key(key) entry = nil data_file = nil @lock.with_read_lock do entry = @keydir[key] return nil unless entry if entry.expired? return nil end data_file = @files[entry.file_id] data_file.synchronize do value = data_file[entry.value_pos, entry.value_size].value return nil if Tombstone.is_tombstone?(value) return value end end end |
#[]=(key, value) ⇒ String
key is always treated as byte array, encoding is ignored
Set value associated with given key.
97 98 99 100 |
# File 'lib/rubcask/directory.rb', line 97 def []=(key, value) put(key, value, NO_EXPIRE_TIMESTAMP) value # rubocop:disable Lint/Void end |
#clear_files ⇒ Object
Removes files that are not needed after the merge
249 250 251 |
# File 'lib/rubcask/directory.rb', line 249 def clear_files worker.push(Rubcask::Task::CleanDirectory.new(@dir)) end |
#close ⇒ Object
Closes all the files and the worker
179 180 181 182 183 184 185 186 187 |
# File 'lib/rubcask/directory.rb', line 179 def close @lock.with_write_lock do @files.each_value(&:close) if active.write_pos == 0 File.delete(active.path) end end worker.close end |
#delete(key) ⇒ Object
key is always treated as byte array, encoding is ignored
Remove entry associated with the key.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/rubcask/directory.rb', line 147 def delete(key) key = normalize_key(key) @lock.with_write_lock do prev_val = @keydir[key] if prev_val.nil? return false end if prev_val.expired? @keydir.delete(key) return false end do_delete(key, prev_val.file_id) true end end |
#each {|key, value| ... } ⇒ Object
This method blocks writes for the entire iteration
Keys might be in any order
Returns Enumerator if block not given.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/rubcask/directory.rb', line 194 def each return to_enum(__method__) unless block_given? @lock.with_read_lock do @keydir.each do |key, entry| file = @files[entry.file_id] file.mon_enter begin value = file[entry.value_pos, entry.value_size].value next if Tombstone.is_tombstone?(value) yield [key, value] ensure file.mon_exit end end end end |
#each_key {|key| ... } ⇒ Object
It might include deleted keys
Keys might be in any order
This method blocks writes for the entire iteration
Returns Enumerator if block not given.
217 218 219 220 221 222 223 |
# File 'lib/rubcask/directory.rb', line 217 def each_key(&block) return to_enum(__method__) unless block @lock.with_read_lock do @keydir.each_key(&block) end end |
#generate_missing_hint_files! ⇒ Object
Generate hint files for data files that do not have hint files
226 227 228 229 230 231 232 233 234 235 |
# File 'lib/rubcask/directory.rb', line 226 def generate_missing_hint_files! @lock.with_read_lock do @files.each_value do |data_file| next if data_file.has_hint_file? && !data_file.dirty? data_file.synchronize do data_file.save_hint_file end end end end |
#key_count ⇒ Integer
It might count some deleted keys
Returns number of keys in the store
256 257 258 259 260 |
# File 'lib/rubcask/directory.rb', line 256 def key_count @lock.with_read_lock do @keydir.size end end |
#keys ⇒ Array<String>
It might include deleted keys
Keys might be in any order
Returns array of keys in store
266 267 268 269 270 |
# File 'lib/rubcask/directory.rb', line 266 def keys @lock.with_read_lock do @keydir.keys end end |
#merge ⇒ Object
Starts the merge operation.
165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/rubcask/directory.rb', line 165 def merge unless @merge_mutex.try_lock raise MergeAlreadyInProgressError, "Merge is already in progress" end begin non_synced_merge rescue => ex logger.error("Error while merging #{ex}") ensure @merge_mutex.unlock end end |
#regenerate_hint_files! ⇒ Object
Generate hint files for all the data files
238 239 240 241 242 243 244 245 246 |
# File 'lib/rubcask/directory.rb', line 238 def regenerate_hint_files! @lock.with_read_lock do @files.each_value do |data_file| data_file.synchronize do data_file.save_hint_file end end end end |
#set_with_ttl(key, value, ttl) ⇒ String
key is always treated as byte array, encoding is ignored
Set value associated with given key with given ttl
110 111 112 113 114 |
# File 'lib/rubcask/directory.rb', line 110 def set_with_ttl(key, value, ttl) raise ArgumentError, "Negative ttl" if ttl.negative? put(key, value, Time.now.to_i + ttl) value # rubocop:disable Lint/Void end |