Class: Archipelago::Hashish::BerkeleyHashish

Inherits:
Object
  • Object
show all
Includes:
Current::Synchronized
Defined in:
lib/archipelago/hashish.rb

Overview

In essence a Berkeley Database backed Hash.

Will cache all values having been written or read in a normal Hash cache for fast access.

Will save the last update timestamp for all keys in a separate Hash cache AND a separate Berkeley Database.

Instance Method Summary collapse

Methods included from Current::Synchronized

#lock_on, #mon_check_owner, #synchronize_on, #unlock_on

Constructor Details

#initialize(name, env) ⇒ BerkeleyHashish

Initialize an instance with the name and BDB::Env env.



42
43
44
45
46
47
48
49
# File 'lib/archipelago/hashish.rb', line 42

def initialize(name, env)
  super()
  @content_db = env.open_db(BDB::HASH, name, "content", BDB::CREATE)
  @content = {}
  @timestamps_db = env.open_db(BDB::HASH, name, "timestamps", BDB::CREATE | BDB::NOMMAP)
  @timestamps = {}
  @lock = Archipelago::Current::Lock.new
end

Instance Method Details

#[](key) ⇒ Object

Simply get the value for the key.



67
68
69
70
71
72
73
74
75
76
# File 'lib/archipelago/hashish.rb', line 67

def [](key)
  @lock.synchronize_on(key) do

    value = @content[key]
    return value if value
    
    return get_from_db(key)
 
  end
end

#[]=(key, value) ⇒ Object

Insert value under key.

Will call value.save_hook(old_value) and send it a block that does the actual saving if value.respond_to?(:save_hook).



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/archipelago/hashish.rb', line 84

def []=(key, value)
  @lock.synchronize_on(key) do

    @content[key] = value

    write_to_db(key, Marshal.dump(key), Marshal.dump(value), value)

    return value

  end
end

#close!Object

Close the @content_db and @timestamps_db behind this BerkeleyHashish



53
54
55
56
# File 'lib/archipelago/hashish.rb', line 53

def close!
  @content_db.close
  @timestamps_db.close
end

#delete(key) ⇒ Object

Delete key and its value and timestamp.



150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/archipelago/hashish.rb', line 150

def delete(key)
  @lock.synchronize_on(key) do

    serialized_key = Marshal.dump(key)

    @content.delete(key)
    @content_db[serialized_key] = nil
    @timestamps.delete(key)
    @timestamps_db[serialized_key] = nil
    
  end
end

#each(callable) ⇒ Object

Will do callable.call(key, value) for each key-and-value pair in this Hashish.

NB: This is totaly thread-unsafe, only do this for management or rescue!



141
142
143
144
145
146
# File 'lib/archipelago/hashish.rb', line 141

def each(callable)
  @content_db.each do |serialized_key, serialized_value|
    key = Marshal.load(serialized_key)
    callable.call(key, self.[](key))
  end
end

#get_deep_clone(key) ⇒ Object

Returns a deep ( Marshal.load(Marshal.dump(o)) ) clone of the object represented by key.



61
62
63
# File 'lib/archipelago/hashish.rb', line 61

def get_deep_clone(key)
  return Marshal.load(@content_db[Marshal.dump(key)])
end

#store_if_changed(key) ⇒ Object

Stores whatever is under key if it is not the same as whats in the persistent db.

Will call value.save_hook(old_value) and send it a block that does the actual saving if value.respond_to?(:save_hook) and a save is actually performed.



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/archipelago/hashish.rb', line 104

def store_if_changed(key)
  @lock.synchronize_on(key) do
    
    serialized_key = Marshal.dump(key)
    value = @content[key]
    serialized_value = Marshal.dump(value)
    
    write_to_db(key, serialized_key, serialized_value, value) if @content_db[serialized_key] != serialized_value

  end
end

#timestamp(key) ⇒ Object

Returns the last time the value under key was changed.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/archipelago/hashish.rb', line 118

def timestamp(key)
  @lock.synchronize_on(key) do
    
    timestamp = @timestamps[key]
    return timestamp if timestamp
    
    serialized_key = Marshal.dump(key)
    serialized_timestamp = @timestamps_db[serialized_key]
    return nil unless serialized_timestamp
    
    timestamp = Marshal.load(serialized_timestamp)
    @timestamps[key] = timestamp
    return timestamp

  end
end