class Rex::JSONHashFile
Attributes
path[RW]
Public Class Methods
new(path)
click to toggle source
# File lib/rex/json_hash_file.rb, line 13 def initialize(path) self.path = path @lock = Mutex.new @hash = {} @last = 0 end
Public Instance Methods
[](k)
click to toggle source
# File lib/rex/json_hash_file.rb, line 20 def [](k) synced_update @hash[k] end
[]=(k,v)
click to toggle source
# File lib/rex/json_hash_file.rb, line 25 def []=(k,v) synced_update do @hash[k] = v end end
clear()
click to toggle source
# File lib/rex/json_hash_file.rb, line 42 def clear synced_update do @hash.clear end end
delete(k)
click to toggle source
# File lib/rex/json_hash_file.rb, line 36 def delete(k) synced_update do @hash.delete(k) end end
keys()
click to toggle source
# File lib/rex/json_hash_file.rb, line 31 def keys synced_update @hash.keys end
Private Instance Methods
parse_data(data)
click to toggle source
# File lib/rex/json_hash_file.rb, line 82 def parse_data(data) return {} if data.to_s.strip.length == 0 begin JSON.parse(data) rescue JSON::ParserError => e # elog("JSONHashFile @ #{path} was corrupt: #{e.class} #{e}" {} end end
synced_update(&block)
click to toggle source
Save the file, but prevent thread & process contention
# File lib/rex/json_hash_file.rb, line 51 def synced_update(&block) @lock.synchronize do ::FileUtils.mkdir_p(::File.dirname(path)) ::File.open(path, ::File::RDWR|::File::CREAT) do |fd| fd.flock(::File::LOCK_EX) # Reload and merge if the file has changed recently if fd.stat.mtime.to_f > @last parse_data(fd.read).merge(@hash).each_pair do |k,v| @hash[k] = v end end res = nil # Update the file on disk if new data is written if block_given? res = block.call fd.rewind fd.write(JSON.pretty_generate(@hash)) fd.sync fd.truncate(fd.pos) end @last = fd.stat.mtime.to_f res end end end