daybreak 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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