daybreak 0.1.3 → 0.2.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/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/LICENSE +2 -2
- data/README +1 -3
- data/Rakefile +6 -9
- data/daybreak.gemspec +4 -4
- data/lib/daybreak.rb +3 -5
- data/lib/daybreak/db.rb +308 -114
- data/lib/daybreak/format.rb +52 -0
- data/lib/daybreak/queue.rb +107 -0
- data/lib/daybreak/serializer.rb +39 -0
- data/lib/daybreak/version.rb +3 -2
- data/script/bench +95 -0
- data/script/converter +390 -0
- data/test/test.rb +251 -57
- data/test/test_helper.rb +0 -3
- metadata +12 -11
- data/lib/daybreak/record.rb +0 -62
- data/lib/daybreak/writer.rb +0 -127
- data/test/bench.rb +0 -28
- data/test/compare.rb +0 -47
data/lib/daybreak/writer.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
module Daybreak
|
2
|
-
# Writer's handle the actually fiddly task of committing data to disk.
|
3
|
-
# They have a Worker instance that writes in a select loop.
|
4
|
-
class Writer
|
5
|
-
# Open up the file, ready it for binary and nonblocking writing.
|
6
|
-
def initialize(file)
|
7
|
-
@file = file
|
8
|
-
open!
|
9
|
-
@worker = Worker.new(@fd)
|
10
|
-
end
|
11
|
-
|
12
|
-
# Send a record to the workers queue.
|
13
|
-
def write(record)
|
14
|
-
@worker.enqueue record
|
15
|
-
end
|
16
|
-
|
17
|
-
# Finish writing
|
18
|
-
def finish!
|
19
|
-
@worker.finish!
|
20
|
-
end
|
21
|
-
|
22
|
-
# Flush pending commits, and restart the worker.
|
23
|
-
def flush!
|
24
|
-
@worker.flush!
|
25
|
-
end
|
26
|
-
|
27
|
-
# Finish writing and close the file descriptor.
|
28
|
-
def close!
|
29
|
-
finish!
|
30
|
-
@fd.close
|
31
|
-
end
|
32
|
-
|
33
|
-
# Truncate the file.
|
34
|
-
def truncate!
|
35
|
-
finish!
|
36
|
-
@fd.truncate(0)
|
37
|
-
@fd.pos = 0
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def open!
|
43
|
-
@fd = File.open @file, 'ab'
|
44
|
-
|
45
|
-
if defined?(Fcntl::O_NONBLOCK)
|
46
|
-
f = @fd.fcntl(Fcntl::F_GETFL, 0)
|
47
|
-
@fd.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK | f)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Workers handle the actual fiddly bits of asynchronous io and
|
52
|
-
# and handle background writes.
|
53
|
-
class Worker
|
54
|
-
def initialize(fd)
|
55
|
-
@queue = Queue.new
|
56
|
-
@fd = fd
|
57
|
-
@thread = Thread.new { work }
|
58
|
-
at_exit { finish! }
|
59
|
-
end
|
60
|
-
|
61
|
-
# Queue up a write to be committed later.
|
62
|
-
def enqueue(record)
|
63
|
-
@queue << record
|
64
|
-
end
|
65
|
-
|
66
|
-
# Loop and block if we don't have work to do or if
|
67
|
-
# the file isn't ready for another write just yet.
|
68
|
-
def work
|
69
|
-
buf, finished = '', false
|
70
|
-
until finished && buf.empty?
|
71
|
-
record = @queue.pop
|
72
|
-
if record
|
73
|
-
buf << Record.serialize(record)
|
74
|
-
else
|
75
|
-
finished = true
|
76
|
-
end
|
77
|
-
read, write = IO.select [], [@fd]
|
78
|
-
if write and fd = write.first
|
79
|
-
lock(fd) { buf = try_write fd, buf }
|
80
|
-
end
|
81
|
-
end
|
82
|
-
@fd.flush
|
83
|
-
end
|
84
|
-
|
85
|
-
# Try and write the buffer to the file via non blocking file writes.
|
86
|
-
# If the write fails try again.
|
87
|
-
def try_write(fd, buf)
|
88
|
-
if defined?(Fcntl::O_NONBLOCK)
|
89
|
-
s = fd.write_nonblock(buf)
|
90
|
-
else
|
91
|
-
s = fd.write(buf)
|
92
|
-
end
|
93
|
-
if s < buf.length
|
94
|
-
buf = buf[s..-1] # didn't finish
|
95
|
-
else
|
96
|
-
buf = ""
|
97
|
-
end
|
98
|
-
buf
|
99
|
-
rescue Errno::EAGAIN
|
100
|
-
buf
|
101
|
-
end
|
102
|
-
|
103
|
-
# Lock a file with the type <tt>lock</tt>
|
104
|
-
def lock(fd)
|
105
|
-
fd.flock File::LOCK_EX
|
106
|
-
begin
|
107
|
-
yield
|
108
|
-
ensure
|
109
|
-
fd.flock File::LOCK_UN
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# finish! and start up another worker thread.
|
114
|
-
def flush!
|
115
|
-
finish!
|
116
|
-
@thread = Thread.new { work }
|
117
|
-
true
|
118
|
-
end
|
119
|
-
|
120
|
-
# Push a nil through the queue and block until the write loop is finished.
|
121
|
-
def finish!
|
122
|
-
@queue.push nil
|
123
|
-
@thread.join
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
data/test/bench.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)) + '/test_helper.rb'
|
2
|
-
|
3
|
-
describe "benchmarks" do
|
4
|
-
before do
|
5
|
-
@db = Daybreak::DB.new DB_PATH
|
6
|
-
1000.times {|i| @db[i] = i }
|
7
|
-
@db.flush!
|
8
|
-
end
|
9
|
-
|
10
|
-
bench_performance_constant "keys with sync" do |n|
|
11
|
-
n.times {|i| @db.set(i, 'i' * i, true) }
|
12
|
-
end
|
13
|
-
|
14
|
-
bench_performance_constant "inserting keys" do |n|
|
15
|
-
n.times {|i| @db[i] = 'i' * i }
|
16
|
-
end
|
17
|
-
|
18
|
-
bench_performance_constant "reading keys" do |n|
|
19
|
-
n.times {|i| assert_equal i % 1000, @db[i % 1000] }
|
20
|
-
end
|
21
|
-
|
22
|
-
after do
|
23
|
-
@db.empty!
|
24
|
-
@db.close!
|
25
|
-
File.unlink(DB_PATH)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
data/test/compare.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__)) + '/test_helper.rb'
|
2
|
-
require 'pstore'
|
3
|
-
|
4
|
-
describe "compare with pstore" do
|
5
|
-
before do
|
6
|
-
@pstore = PStore.new(File.join(HERE, "test.pstore"))
|
7
|
-
end
|
8
|
-
|
9
|
-
bench_performance_constant "pstore bulk performance" do |n|
|
10
|
-
@pstore.transaction do
|
11
|
-
n.times do |i|
|
12
|
-
@pstore[i] = 'i' * i
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
after do
|
18
|
-
File.unlink File.join(HERE, "test.pstore")
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
require 'dbm'
|
23
|
-
|
24
|
-
describe "compare with dbm" do
|
25
|
-
before do
|
26
|
-
@dbm = DBM.open(File.join(HERE, "test-dbm"), 666, DBM::WRCREAT)
|
27
|
-
1000.times {|i| @dbm[i.to_s] = i }
|
28
|
-
end
|
29
|
-
|
30
|
-
bench_performance_constant "DBM write performance" do |n|
|
31
|
-
n.times do |i|
|
32
|
-
@dbm[i.to_s] = 'i' * i
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
bench_performance_constant "DBM read performance" do |n|
|
37
|
-
n.times do |i|
|
38
|
-
assert_equal (i % 1000).to_s, @dbm[(i % 1000).to_s]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
after do
|
43
|
-
@dbm.close
|
44
|
-
|
45
|
-
File.unlink File.join(HERE, "test-dbm.db")
|
46
|
-
end
|
47
|
-
end
|