daybreak 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/daybreak/db.rb +30 -4
- data/lib/daybreak/record.rb +31 -9
- data/lib/daybreak/version.rb +1 -1
- data/test/test.rb +34 -0
- metadata +2 -2
data/lib/daybreak/db.rb
CHANGED
@@ -28,8 +28,7 @@ module Daybreak
|
|
28
28
|
# @param [Boolean] sync if true, sync this value immediately
|
29
29
|
def []=(key, value, sync = false)
|
30
30
|
key = key.to_s
|
31
|
-
|
32
|
-
flush! if sync
|
31
|
+
write key, value, sync
|
33
32
|
@table[key] = value
|
34
33
|
end
|
35
34
|
alias_method :set, :"[]="
|
@@ -41,6 +40,21 @@ module Daybreak
|
|
41
40
|
set key, value, true
|
42
41
|
end
|
43
42
|
|
43
|
+
# Delete a key from the database
|
44
|
+
# @param [#to_s] key the key of the storage slot in the database
|
45
|
+
# @param [Boolean] sync if true, sync this deletion immediately
|
46
|
+
def delete(key, sync = false)
|
47
|
+
key = key.to_s
|
48
|
+
write key, '', sync, true
|
49
|
+
@table.delete key
|
50
|
+
end
|
51
|
+
|
52
|
+
# delete! immediately deletes the key on disk.
|
53
|
+
# @param [#to_s] key the key of the storage slot in the database
|
54
|
+
def delete!(key)
|
55
|
+
delete key, true
|
56
|
+
end
|
57
|
+
|
44
58
|
# Retrieve a value at key from the database. If the default value was specified
|
45
59
|
# when this database was created, that value will be set and returned. Aliased
|
46
60
|
# as <tt>get</tt>.
|
@@ -112,6 +126,7 @@ module Daybreak
|
|
112
126
|
@writer.truncate!
|
113
127
|
reset!
|
114
128
|
end
|
129
|
+
alias_method :clear, :empty!
|
115
130
|
|
116
131
|
# Force all queued commits to be written to disk.
|
117
132
|
def flush!
|
@@ -138,7 +153,7 @@ module Daybreak
|
|
138
153
|
copy_db = self.class.new tmp_file.path
|
139
154
|
|
140
155
|
# Copy the database key by key into the temporary table
|
141
|
-
each do |key
|
156
|
+
each do |key|
|
142
157
|
copy_db.set(key, get(key))
|
143
158
|
end
|
144
159
|
copy_db.close!
|
@@ -161,8 +176,19 @@ module Daybreak
|
|
161
176
|
# call this again.
|
162
177
|
def read!
|
163
178
|
@reader.read do |record|
|
164
|
-
|
179
|
+
if record.deleted?
|
180
|
+
@table.delete record.key
|
181
|
+
else
|
182
|
+
@table[record.key] = parse(record.data)
|
183
|
+
end
|
165
184
|
end
|
166
185
|
end
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
def write(key, value, sync = false, delete = false)
|
190
|
+
@writer.write(Record.new(key, serialize(value), delete))
|
191
|
+
flush! if sync
|
192
|
+
end
|
167
193
|
end
|
168
194
|
end
|
data/lib/daybreak/record.rb
CHANGED
@@ -9,11 +9,19 @@ module Daybreak
|
|
9
9
|
class CorruptDataError < Exception; end
|
10
10
|
include Locking
|
11
11
|
|
12
|
+
# The mask a record uses to check for deletion.
|
13
|
+
DELETION_MASK = (1 << 31)
|
14
|
+
|
12
15
|
attr_accessor :key, :data
|
13
16
|
|
14
|
-
def initialize(key = nil, data = nil)
|
17
|
+
def initialize(key = nil, data = nil, deleted = false)
|
15
18
|
@key = key
|
16
19
|
@data = data
|
20
|
+
if deleted
|
21
|
+
@deleted = DELETION_MASK
|
22
|
+
else
|
23
|
+
@deleted = 0
|
24
|
+
end
|
17
25
|
end
|
18
26
|
|
19
27
|
# Read a record from an open io source, check the CRC, and set <tt>@key</tt>
|
@@ -21,8 +29,8 @@ module Daybreak
|
|
21
29
|
# @param [#read] io an IO instance to read from
|
22
30
|
def read(io)
|
23
31
|
lock io do
|
24
|
-
@key =
|
25
|
-
@data =
|
32
|
+
@key = read_key(io)
|
33
|
+
@data = read_data(io)
|
26
34
|
crc = io.read(4)
|
27
35
|
raise CorruptDataError, "CRC mismatch #{crc} should be #{crc_string}" unless crc == crc_string
|
28
36
|
end
|
@@ -42,24 +50,38 @@ module Daybreak
|
|
42
50
|
new.read(io)
|
43
51
|
end
|
44
52
|
|
53
|
+
def deleted?
|
54
|
+
@deleted > 0
|
55
|
+
end
|
56
|
+
|
45
57
|
private
|
46
58
|
|
47
59
|
def byte_string
|
48
|
-
@byte_string ||= part(@key) + part(@data)
|
60
|
+
@byte_string ||= part(@key, @key.bytesize + @deleted) + part(@data, @data.bytesize)
|
49
61
|
end
|
50
62
|
|
51
63
|
def crc_string
|
52
64
|
[Zlib.crc32(byte_string, 0)].pack('N')
|
53
65
|
end
|
54
66
|
|
55
|
-
def
|
67
|
+
def read_data(io)
|
68
|
+
io.read read32(io)
|
69
|
+
end
|
70
|
+
|
71
|
+
def read_key(io)
|
72
|
+
masked = read32 io
|
73
|
+
@deleted = masked & DELETION_MASK
|
74
|
+
length = masked & (DELETION_MASK - 1)
|
75
|
+
io.read length
|
76
|
+
end
|
77
|
+
|
78
|
+
def read32(io)
|
56
79
|
raw = io.read(4)
|
57
|
-
|
58
|
-
io.read(length)
|
80
|
+
raw.unpack('N')[0]
|
59
81
|
end
|
60
82
|
|
61
|
-
def part(data)
|
62
|
-
[
|
83
|
+
def part(data, length)
|
84
|
+
[length].pack('N') + data
|
63
85
|
end
|
64
86
|
end
|
65
87
|
end
|
data/lib/daybreak/version.rb
CHANGED
data/test/test.rb
CHANGED
@@ -77,6 +77,40 @@ describe "database functions" do
|
|
77
77
|
assert_equal nil, db2['19']
|
78
78
|
end
|
79
79
|
|
80
|
+
it "should compact subclassed dbs" do
|
81
|
+
class StringDB < Daybreak::DB
|
82
|
+
def serialize(it)
|
83
|
+
it.to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse(it)
|
87
|
+
it
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
db = StringDB.new 'string.db'
|
92
|
+
db[1] = 'one'
|
93
|
+
db[2] = 'two'
|
94
|
+
db.delete 2
|
95
|
+
db.compact!
|
96
|
+
assert_equal db[1], 'one'
|
97
|
+
assert_equal db[2], nil
|
98
|
+
db.empty!
|
99
|
+
db.close!
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should handle deletions" do
|
103
|
+
@db[1] = 'one'
|
104
|
+
@db[2] = 'two'
|
105
|
+
@db.delete 'two'
|
106
|
+
assert !@db.has_key?('two')
|
107
|
+
assert_equal @db['two'], nil
|
108
|
+
|
109
|
+
db2 = Daybreak::DB.new DB_PATH
|
110
|
+
assert !db2.has_key?('two')
|
111
|
+
assert_equal db2['two'], nil
|
112
|
+
end
|
113
|
+
|
80
114
|
after do
|
81
115
|
@db.empty!
|
82
116
|
@db.close!
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: daybreak
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|