redisk 0.1.0 → 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 +2 -1
- data/HISTORY +14 -0
- data/README.rdoc +18 -0
- data/examples/rails.rb +4 -0
- data/examples/yajl.rb +24 -0
- data/lib/redisk/io.rb +215 -39
- data/lib/redisk.rb +18 -1
- data/redisk.gemspec +8 -3
- data/spec/redisk_io_spec.rb +291 -25
- metadata +7 -2
data/.gitignore
CHANGED
data/HISTORY
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
=== 0.2.0 [2009-12-22]
|
2
|
+
|
3
|
+
* Almost complete support for both line and byte operations on Redisk::IO
|
4
|
+
* New special extensions to the base IO class:
|
5
|
+
* .from_file and .to_file for writing/reading to disk
|
6
|
+
* .unlink for deleting contents
|
7
|
+
* .all lists the IO's created by Redisk::IO
|
8
|
+
* New examples folder
|
9
|
+
|
10
|
+
=== 0.1.0
|
11
|
+
|
12
|
+
* Initial Release.
|
13
|
+
* Basic support for line operations in Redisk::IO
|
14
|
+
* Redisk::Logger
|
data/README.rdoc
CHANGED
@@ -41,6 +41,24 @@ By default, Redisk uses the Redis on localhost:6379, but you can change that by
|
|
41
41
|
|
42
42
|
Redisk.redis = 'myhost:myport'
|
43
43
|
|
44
|
+
Check out the small but growing list of examples in examples/
|
45
|
+
|
46
|
+
== INSTALL (NOW!)
|
47
|
+
|
48
|
+
Proudly tested and working on Ruby 1.8.6, 1.8.7, and 1.9.1
|
49
|
+
|
50
|
+
Gems are on gemcutter:
|
51
|
+
|
52
|
+
gem install redisk
|
53
|
+
|
54
|
+
Dependencies:
|
55
|
+
|
56
|
+
redis running somewhere
|
57
|
+
|
58
|
+
gems:
|
59
|
+
redis
|
60
|
+
redis-namespace
|
61
|
+
|
44
62
|
== Note on Patches/Pull Requests
|
45
63
|
|
46
64
|
* Fork the project.
|
data/examples/rails.rb
ADDED
data/examples/yajl.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'yajl'
|
3
|
+
require 'redisk'
|
4
|
+
|
5
|
+
hash = {'something' => 'for nothing', 'and_the_rest' => 'for free', 'i' => {'want' => {'my' => 'mtv'}}}
|
6
|
+
|
7
|
+
io_name = 'test.json'
|
8
|
+
Redisk::IO.unlink(io_name)
|
9
|
+
|
10
|
+
puts 'The hash:'
|
11
|
+
puts hash.inspect
|
12
|
+
|
13
|
+
puts 'write the hash as json to redis'
|
14
|
+
io = Redisk::IO.new(io_name)
|
15
|
+
Yajl::Encoder.encode(hash, io)
|
16
|
+
|
17
|
+
puts 'read it back out'
|
18
|
+
io.rewind
|
19
|
+
puts io.read.inspect
|
20
|
+
|
21
|
+
io.rewind
|
22
|
+
|
23
|
+
puts 'parse it back to ruby'
|
24
|
+
puts Yajl::Parser.parse(io).inspect
|
data/lib/redisk/io.rb
CHANGED
@@ -6,16 +6,24 @@ module Redisk
|
|
6
6
|
|
7
7
|
class NotImplementedError < RuntimeError; end
|
8
8
|
class EOFError < ::EOFError; end
|
9
|
+
class IOError < ::IOError; end
|
9
10
|
|
10
11
|
attr_reader :name, :mode, :_
|
11
12
|
|
12
|
-
def initialize(name, mode = '
|
13
|
-
@name
|
14
|
-
@mode
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
13
|
+
def initialize(name, mode = 'r')
|
14
|
+
@name = name
|
15
|
+
@mode = mode # we're going to just ignore this for now
|
16
|
+
@read_open = true
|
17
|
+
@write_open = true
|
18
|
+
@write_buffer = nil
|
19
|
+
@read_buffer = nil
|
20
|
+
@sync = false
|
21
|
+
@pos = 0
|
22
|
+
@lineno = 0
|
23
|
+
@size = stat.size > 0 ? stat.size : true_size
|
24
|
+
# add io to the list of ios
|
25
|
+
redis.sadd dir, name
|
26
|
+
rewind
|
19
27
|
end
|
20
28
|
alias :for_fd :initialize
|
21
29
|
|
@@ -26,7 +34,19 @@ module Redisk
|
|
26
34
|
def list_key
|
27
35
|
self.class.list_key(name)
|
28
36
|
end
|
37
|
+
|
38
|
+
def self.all
|
39
|
+
redis.smembers dir
|
40
|
+
end
|
29
41
|
|
42
|
+
def self.dir
|
43
|
+
"__ios__"
|
44
|
+
end
|
45
|
+
|
46
|
+
def dir
|
47
|
+
self.class.dir
|
48
|
+
end
|
49
|
+
|
30
50
|
# Executes the block for every line in the named I/O port, where lines are
|
31
51
|
# separated by sep_string.
|
32
52
|
#
|
@@ -38,8 +58,9 @@ module Redisk
|
|
38
58
|
# GOT This is line three
|
39
59
|
# GOT And so on...
|
40
60
|
def self.foreach(name, &block)
|
41
|
-
|
42
|
-
|
61
|
+
io = new(name)
|
62
|
+
io.each_line(&block)
|
63
|
+
io.close
|
43
64
|
end
|
44
65
|
|
45
66
|
# With no associated block, open is a synonym for IO::new. If the optional
|
@@ -48,7 +69,9 @@ module Redisk
|
|
48
69
|
# instance, IO::open returns the value of the block.
|
49
70
|
def self.open(name, mode = 'r')
|
50
71
|
io = new(name, mode)
|
51
|
-
block_given? ? yield(io) : io
|
72
|
+
returned = block_given? ? yield(io) : io
|
73
|
+
io.close
|
74
|
+
returned
|
52
75
|
end
|
53
76
|
|
54
77
|
# IO.pipe → array
|
@@ -92,12 +115,21 @@ module Redisk
|
|
92
115
|
# IO.read("testfile", 20) #=> "This is line one\nThi"
|
93
116
|
# IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
|
94
117
|
def self.read(name, length = nil, offset = nil)
|
118
|
+
io = new(name)
|
119
|
+
io.seek(offset) if offset
|
120
|
+
returned = io.read(length)
|
121
|
+
io.close
|
122
|
+
returned
|
123
|
+
end
|
124
|
+
|
125
|
+
# Works similarly to IO.read, but operates on lines instead of bytes
|
126
|
+
def self.read_lines(name, length = nil, offset = nil)
|
95
127
|
start_i = offset || 0
|
96
128
|
end_i = length ? start_i + (length - 1) : -1
|
97
129
|
values = redis.lrange(list_key(name), start_i, end_i)
|
98
|
-
values.join
|
130
|
+
values.join
|
99
131
|
end
|
100
|
-
|
132
|
+
|
101
133
|
# Reads the entire file specified by name as individual lines, and returns
|
102
134
|
# those lines in an array. Lines are separated by sep_string.
|
103
135
|
#
|
@@ -125,6 +157,31 @@ module Redisk
|
|
125
157
|
raise NotImplementedError, ".sysopen is not implemented"
|
126
158
|
end
|
127
159
|
|
160
|
+
# Removes all references to the io at name
|
161
|
+
def self.unlink(name)
|
162
|
+
redis.keys("#{name}:*").each do |key|
|
163
|
+
redis.del key.gsub('redisk:','')
|
164
|
+
end
|
165
|
+
redis.srem dir, name
|
166
|
+
nil
|
167
|
+
end
|
168
|
+
|
169
|
+
# Reads the contents of file into the IO.
|
170
|
+
# If file is not a File its taken as a path and passed to File.open
|
171
|
+
def self.from_file(name, file)
|
172
|
+
io = new(name)
|
173
|
+
io.from_file(file)
|
174
|
+
io
|
175
|
+
end
|
176
|
+
|
177
|
+
# Writes the contents of IO into file.
|
178
|
+
# If file is not a File its taken as a path and passed to File.open
|
179
|
+
def self.to_file(name, file)
|
180
|
+
io = new(name)
|
181
|
+
io.to_file(file)
|
182
|
+
io
|
183
|
+
end
|
184
|
+
|
128
185
|
# String Output—Writes obj to ios. obj will be converted to a string using
|
129
186
|
# to_s.
|
130
187
|
#
|
@@ -133,10 +190,10 @@ module Redisk
|
|
133
190
|
#
|
134
191
|
# Hello world!
|
135
192
|
def <<(text)
|
136
|
-
@
|
137
|
-
@
|
193
|
+
@write_buffer ||= ''
|
194
|
+
@write_buffer << text
|
138
195
|
flush if sync
|
139
|
-
@
|
196
|
+
@write_buffer
|
140
197
|
end
|
141
198
|
|
142
199
|
# ios.binmode => ios
|
@@ -154,7 +211,9 @@ module Redisk
|
|
154
211
|
#
|
155
212
|
# If ios is opened by IO.popen, close sets $?.
|
156
213
|
def close
|
157
|
-
|
214
|
+
flush
|
215
|
+
close_read
|
216
|
+
close_write
|
158
217
|
end
|
159
218
|
|
160
219
|
# ios.close_read => nil
|
@@ -170,7 +229,8 @@ module Redisk
|
|
170
229
|
# prog.rb:3:in `readlines': not opened for reading (IOError)
|
171
230
|
# from prog.rb:3
|
172
231
|
def close_read
|
173
|
-
|
232
|
+
@read_open = false
|
233
|
+
nil
|
174
234
|
end
|
175
235
|
|
176
236
|
# ios.close_write => nil
|
@@ -187,7 +247,8 @@ module Redisk
|
|
187
247
|
# from prog.rb:3:in `print'
|
188
248
|
# from prog.rb:3
|
189
249
|
def close_write
|
190
|
-
|
250
|
+
@write_open = false
|
251
|
+
nil
|
191
252
|
end
|
192
253
|
|
193
254
|
# ios.closed? => true or false
|
@@ -202,8 +263,8 @@ module Redisk
|
|
202
263
|
# f.closed? #=> false
|
203
264
|
# f.close_read #=> nil
|
204
265
|
# f.closed? #=> true
|
205
|
-
def closed
|
206
|
-
|
266
|
+
def closed?
|
267
|
+
!(@write_open || @read_open)
|
207
268
|
end
|
208
269
|
|
209
270
|
# ios.each(sep_string=$/) {|line| block } => ios
|
@@ -238,7 +299,11 @@ module Redisk
|
|
238
299
|
# f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
|
239
300
|
# checksum #=> 12
|
240
301
|
def each_byte
|
241
|
-
|
302
|
+
rewind
|
303
|
+
while !eof?
|
304
|
+
yield getc
|
305
|
+
end
|
306
|
+
self
|
242
307
|
end
|
243
308
|
|
244
309
|
# ios.eof => true or false
|
@@ -266,7 +331,7 @@ module Redisk
|
|
266
331
|
# Note that IO#eof? reads data to a input buffer. So IO#sysread doesn‘t
|
267
332
|
# work with IO#eof?.
|
268
333
|
def eof
|
269
|
-
lineno >= length
|
334
|
+
lineno >= length || pos >= size
|
270
335
|
end
|
271
336
|
alias :eof? :eof
|
272
337
|
|
@@ -302,13 +367,13 @@ module Redisk
|
|
302
367
|
#
|
303
368
|
# no newline
|
304
369
|
def flush
|
305
|
-
if @
|
306
|
-
redis.rpush list_key, @
|
307
|
-
@size += @
|
370
|
+
if @write_buffer && @write_buffer != ''
|
371
|
+
redis.rpush list_key, @write_buffer
|
372
|
+
@size += @write_buffer.length
|
308
373
|
stat.write_attribute(:size, @size)
|
309
374
|
stat.write_attribute(:mtime, Time.now)
|
310
375
|
end
|
311
|
-
@
|
376
|
+
@write_buffer = nil
|
312
377
|
end
|
313
378
|
|
314
379
|
# ios.fsync => 0 or nil
|
@@ -318,6 +383,31 @@ module Redisk
|
|
318
383
|
# from Ruby‘s buffers, but doesn‘t not guarantee that the underlying
|
319
384
|
# operating system actually writes it to disk.
|
320
385
|
def fsync
|
386
|
+
false
|
387
|
+
end
|
388
|
+
|
389
|
+
# Reads the contents of file into the IO.
|
390
|
+
# If file is not a File its taken as a path and passed to File.open
|
391
|
+
# Returns the IO
|
392
|
+
def from_file(file)
|
393
|
+
file = File.open(file, 'r') if !file.is_a?(File)
|
394
|
+
file.each_line do |l|
|
395
|
+
write l
|
396
|
+
end
|
397
|
+
file.close
|
398
|
+
self
|
399
|
+
end
|
400
|
+
|
401
|
+
# Writes the contents of IO into file.
|
402
|
+
# If file is not a File its taken as a path and passed to File.open
|
403
|
+
# Returns the IO
|
404
|
+
def to_file(file)
|
405
|
+
file = File.open(file, 'w') if !file.is_a?(File)
|
406
|
+
each_line do |l|
|
407
|
+
file.write l
|
408
|
+
end
|
409
|
+
file.close
|
410
|
+
self
|
321
411
|
end
|
322
412
|
|
323
413
|
# ios.getc => fixnum or nil
|
@@ -328,6 +418,7 @@ module Redisk
|
|
328
418
|
# f.getc #=> 84
|
329
419
|
# f.getc #=> 104
|
330
420
|
def getc
|
421
|
+
read(1).to_s.ord
|
331
422
|
end
|
332
423
|
|
333
424
|
# ios.gets(sep_string=$/) => string or nil
|
@@ -342,11 +433,14 @@ module Redisk
|
|
342
433
|
# File.new("testfile").gets #=> "This is line one\n"
|
343
434
|
# $_ #=> "This is line one\n"
|
344
435
|
def gets
|
436
|
+
check_stream_open!(:read)
|
345
437
|
flush
|
438
|
+
return nil if eof?
|
346
439
|
val = redis.lrange(list_key, lineno, lineno + 1)
|
347
440
|
if val = val.first
|
348
441
|
self.lineno += 1
|
349
442
|
$_ = @_ = val
|
443
|
+
@pos += val.length
|
350
444
|
val
|
351
445
|
end
|
352
446
|
end
|
@@ -387,6 +481,10 @@ module Redisk
|
|
387
481
|
@size
|
388
482
|
end
|
389
483
|
|
484
|
+
def true_size
|
485
|
+
readlines.join.length
|
486
|
+
end
|
487
|
+
|
390
488
|
# ios.lineno => integer
|
391
489
|
# Returns the current line number in ios. The stream must be opened for
|
392
490
|
# reading. lineno counts the number of times gets is called, rather than
|
@@ -416,7 +514,15 @@ module Redisk
|
|
416
514
|
# f.gets #=> "This is line two\n"
|
417
515
|
# $. # lineno of last read #=> 1001
|
418
516
|
def lineno=(num)
|
419
|
-
@lineno = num
|
517
|
+
@lineno = num.to_i
|
518
|
+
end
|
519
|
+
|
520
|
+
def open?(stream = nil)
|
521
|
+
if stream
|
522
|
+
instance_variable_get("@#{stream}_open")
|
523
|
+
else
|
524
|
+
@write_open && @read_open
|
525
|
+
end
|
420
526
|
end
|
421
527
|
|
422
528
|
# ios.pid => fixnum
|
@@ -434,7 +540,7 @@ module Redisk
|
|
434
540
|
# In child, pid is 26209
|
435
541
|
# In parent, child pid is 26209
|
436
542
|
def pid
|
437
|
-
|
543
|
+
Process.pid
|
438
544
|
end
|
439
545
|
|
440
546
|
# ios.pos => integer
|
@@ -446,7 +552,7 @@ module Redisk
|
|
446
552
|
# f.gets #=> "This is line one\n"
|
447
553
|
# f.pos #=> 17
|
448
554
|
def pos
|
449
|
-
|
555
|
+
@pos
|
450
556
|
end
|
451
557
|
alias :tell :pos
|
452
558
|
|
@@ -457,7 +563,13 @@ module Redisk
|
|
457
563
|
# f.pos = 17
|
458
564
|
# f.gets #=> "This is line two\n"
|
459
565
|
def pos=(num)
|
460
|
-
|
566
|
+
current_pos = @pos
|
567
|
+
if num < current_pos
|
568
|
+
@pos = 0
|
569
|
+
else
|
570
|
+
num -= current_pos
|
571
|
+
end
|
572
|
+
read(num)
|
461
573
|
end
|
462
574
|
|
463
575
|
# ios.print() => nil
|
@@ -497,7 +609,7 @@ module Redisk
|
|
497
609
|
#
|
498
610
|
# AA
|
499
611
|
def putc(obj)
|
500
|
-
|
612
|
+
self << obj.is_a?(Fixnum) ? obj : obj.to_s[0]
|
501
613
|
end
|
502
614
|
|
503
615
|
# ios.puts(obj, ...) => nil
|
@@ -516,8 +628,11 @@ module Redisk
|
|
516
628
|
# test
|
517
629
|
def puts(*args)
|
518
630
|
args.empty? ?
|
519
|
-
write(
|
520
|
-
args.each {|a|
|
631
|
+
write("\n") :
|
632
|
+
args.each {|a|
|
633
|
+
a += "\n" if a !~ /\n$/
|
634
|
+
write(a)
|
635
|
+
}
|
521
636
|
nil
|
522
637
|
end
|
523
638
|
|
@@ -532,8 +647,30 @@ module Redisk
|
|
532
647
|
#
|
533
648
|
# f = File.new("testfile")
|
534
649
|
# f.read(16) #=> "This is line one"
|
535
|
-
def read
|
536
|
-
|
650
|
+
def read(length = nil, buffer = nil)
|
651
|
+
check_stream_open!(:read)
|
652
|
+
if eof
|
653
|
+
length ? nil : ""
|
654
|
+
else
|
655
|
+
if length
|
656
|
+
@read_buffer ||= ""
|
657
|
+
fetched = false
|
658
|
+
while @read_buffer.length < length && !eof?
|
659
|
+
@read_buffer << gets.to_s
|
660
|
+
fetched = true
|
661
|
+
end
|
662
|
+
result = @read_buffer[0...length]
|
663
|
+
@read_buffer = @read_buffer[length..-1] || ""
|
664
|
+
if fetched
|
665
|
+
@pos -= @read_buffer.length
|
666
|
+
else
|
667
|
+
@pos += result.length
|
668
|
+
end
|
669
|
+
else
|
670
|
+
result = readlines.join
|
671
|
+
end
|
672
|
+
buffer ? buffer.replace(buffer + result) : result
|
673
|
+
end
|
537
674
|
end
|
538
675
|
|
539
676
|
# ios.read_nonblock(maxlen) => string
|
@@ -566,7 +703,14 @@ module Redisk
|
|
566
703
|
# read data is obtainable via its data method.
|
567
704
|
#
|
568
705
|
def readbytes(n)
|
569
|
-
|
706
|
+
result = read(n)
|
707
|
+
if result && result.length < n
|
708
|
+
raise TruncatedDataError, result
|
709
|
+
elsif result.nil?
|
710
|
+
raise EOFError, "You have reached the end of the IO stream"
|
711
|
+
else
|
712
|
+
result
|
713
|
+
end
|
570
714
|
end
|
571
715
|
|
572
716
|
# ios.readchar => fixnum
|
@@ -595,6 +739,7 @@ module Redisk
|
|
595
739
|
# f = File.new("testfile")
|
596
740
|
# f.readlines[0] #=> "This is line one\n"
|
597
741
|
def readlines
|
742
|
+
check_stream_open!(:read)
|
598
743
|
self.class.readlines(name)
|
599
744
|
end
|
600
745
|
|
@@ -678,6 +823,7 @@ module Redisk
|
|
678
823
|
# f.readline #=> "This is line one\n"
|
679
824
|
def rewind
|
680
825
|
self.lineno = 0
|
826
|
+
self.pos = 0
|
681
827
|
end
|
682
828
|
|
683
829
|
# scanf(str,&b)
|
@@ -727,6 +873,19 @@ module Redisk
|
|
727
873
|
# f.seek(-13, IO::SEEK_END) #=> 0
|
728
874
|
# f.readline #=> "And so on...\n"
|
729
875
|
def seek(offset, whence = SEEK_SET)
|
876
|
+
case whence
|
877
|
+
when SEEK_SET
|
878
|
+
self.pos = offset
|
879
|
+
when SEEK_END
|
880
|
+
self.pos = size + offset
|
881
|
+
when SEEK_CUR
|
882
|
+
self.pos += offset
|
883
|
+
end
|
884
|
+
0
|
885
|
+
end
|
886
|
+
|
887
|
+
# works just like seek, but seeks by lineno instead of pos
|
888
|
+
def seek_lines(offset, whence = SEEK_SET)
|
730
889
|
case whence
|
731
890
|
when SEEK_SET
|
732
891
|
self.lineno = offset
|
@@ -815,6 +974,7 @@ module Redisk
|
|
815
974
|
else
|
816
975
|
redis.ltrim list_key, -size, -1
|
817
976
|
end
|
977
|
+
stat.write_attribute(:size, @size = true_size)
|
818
978
|
length
|
819
979
|
end
|
820
980
|
|
@@ -829,10 +989,20 @@ module Redisk
|
|
829
989
|
# c = f.getc #=> 84
|
830
990
|
# f.ungetc(c) #=> nil
|
831
991
|
# f.getc #=> 84
|
832
|
-
def ungetc(
|
833
|
-
|
992
|
+
def ungetc(integer)
|
993
|
+
check_stream_open!(:write)
|
994
|
+
char = ("" << integer)
|
995
|
+
self << char
|
996
|
+
nil
|
834
997
|
end
|
835
998
|
|
999
|
+
# Removes all references to the IO and closes it for reading and writing
|
1000
|
+
def unlink
|
1001
|
+
close
|
1002
|
+
self.class.unlink(name)
|
1003
|
+
end
|
1004
|
+
alias :delete :unlink
|
1005
|
+
|
836
1006
|
# ios.write(string) => integer
|
837
1007
|
# Writes the given string to ios. The stream must be opened for writing.
|
838
1008
|
# If the argument is not a string, it will be converted to a string using
|
@@ -845,8 +1015,9 @@ module Redisk
|
|
845
1015
|
# This is a test
|
846
1016
|
# That was 15 bytes of data
|
847
1017
|
def write(string)
|
1018
|
+
check_stream_open!(:write)
|
848
1019
|
string = string.to_s
|
849
|
-
|
1020
|
+
self << string
|
850
1021
|
flush
|
851
1022
|
string.length
|
852
1023
|
end
|
@@ -863,5 +1034,10 @@ module Redisk
|
|
863
1034
|
def write_nonblock(string)
|
864
1035
|
end
|
865
1036
|
|
1037
|
+
private
|
1038
|
+
def check_stream_open!(stream = :read)
|
1039
|
+
raise(IOError, "#{self} is not open for #{stream}ing") unless open?(stream)
|
1040
|
+
end
|
1041
|
+
|
866
1042
|
end
|
867
1043
|
end
|
data/lib/redisk.rb
CHANGED
@@ -6,7 +6,7 @@ require 'redisk/io'
|
|
6
6
|
require 'redisk/logger'
|
7
7
|
|
8
8
|
module Redisk
|
9
|
-
VERSION = '0.
|
9
|
+
VERSION = '0.2.0'
|
10
10
|
|
11
11
|
extend self
|
12
12
|
|
@@ -33,5 +33,22 @@ module Redisk
|
|
33
33
|
self.redis
|
34
34
|
end
|
35
35
|
|
36
|
+
def io(*args)
|
37
|
+
Redisk::IO.new(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def logger(*args)
|
41
|
+
Redisk::Logger.new(*args)
|
42
|
+
end
|
43
|
+
|
36
44
|
end
|
37
45
|
|
46
|
+
class String
|
47
|
+
|
48
|
+
if !method_defined?(:ord)
|
49
|
+
def ord
|
50
|
+
self[0]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/redisk.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{redisk}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aaron Quint"]
|
12
|
-
s.date = %q{2009-12-
|
12
|
+
s.date = %q{2009-12-22}
|
13
13
|
s.description = %q{Redisk includes Redisk::IO which is ~ Ruby's stdlib IO. It can be used with stdlib's Logger to log directly to redis}
|
14
14
|
s.email = %q{aaron@quirkey.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -19,9 +19,12 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
21
|
".gitignore",
|
22
|
+
"HISTORY",
|
22
23
|
"LICENSE",
|
23
24
|
"README.rdoc",
|
24
25
|
"Rakefile",
|
26
|
+
"examples/rails.rb",
|
27
|
+
"examples/yajl.rb",
|
25
28
|
"lib/redisk.rb",
|
26
29
|
"lib/redisk/helper.rb",
|
27
30
|
"lib/redisk/io.rb",
|
@@ -45,7 +48,9 @@ Gem::Specification.new do |s|
|
|
45
48
|
"spec/redisk_io_spec.rb",
|
46
49
|
"spec/redisk_logger_spec.rb",
|
47
50
|
"spec/redisk_stat_spec.rb",
|
48
|
-
"spec/spec_helper.rb"
|
51
|
+
"spec/spec_helper.rb",
|
52
|
+
"examples/rails.rb",
|
53
|
+
"examples/yajl.rb"
|
49
54
|
]
|
50
55
|
|
51
56
|
if s.respond_to? :specification_version then
|
data/spec/redisk_io_spec.rb
CHANGED
@@ -2,6 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe Redisk::IO do
|
4
4
|
before do
|
5
|
+
FileUtils.mkdir_p('tmp')
|
5
6
|
# load a file into an IO object
|
6
7
|
@io_name = 'rails.log'
|
7
8
|
@key = Redisk::IO.list_key(@io_name)
|
@@ -14,7 +15,9 @@ describe Redisk::IO do
|
|
14
15
|
end
|
15
16
|
|
16
17
|
after do
|
17
|
-
Redisk.redis.
|
18
|
+
Redisk.redis.keys(@key.gsub(':_list', '*')).each do |key|
|
19
|
+
Redisk.redis.del key.gsub('redisk:', '')
|
20
|
+
end
|
18
21
|
end
|
19
22
|
|
20
23
|
describe 'new' do
|
@@ -29,6 +32,15 @@ describe Redisk::IO do
|
|
29
32
|
it 'stores the name of the key' do
|
30
33
|
@io.name.should == @io_name
|
31
34
|
end
|
35
|
+
|
36
|
+
it 'should be open' do
|
37
|
+
@io.closed?.should == false
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should add to the list of ios' do
|
41
|
+
Redisk::IO.all.should include(@io_name)
|
42
|
+
end
|
43
|
+
|
32
44
|
end
|
33
45
|
|
34
46
|
describe 'foreach' do
|
@@ -45,6 +57,45 @@ describe Redisk::IO do
|
|
45
57
|
|
46
58
|
end
|
47
59
|
|
60
|
+
describe 'from_file' do
|
61
|
+
before(:each) do
|
62
|
+
Redisk::IO.unlink('dump_test.log')
|
63
|
+
File.open('tmp/dump_test.log', 'w+') {|f| f << "This is a file" }
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should write into io at name from file' do
|
67
|
+
@io = Redisk::IO.from_file('dump_test.log', 'tmp/dump_test.log')
|
68
|
+
@io.rewind
|
69
|
+
@io.gets.should == "This is a file"
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should write into io at name from File' do
|
73
|
+
@io = Redisk::IO.from_file('dump_test.log', File.new('tmp/dump_test.log'))
|
74
|
+
@io.rewind
|
75
|
+
@io.gets.should == "This is a file"
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'to_file' do
|
81
|
+
before(:each) do
|
82
|
+
Redisk::IO.unlink('dump_test.log')
|
83
|
+
File.unlink('tmp/dump_test.log')
|
84
|
+
Redisk::IO.open('dump_test.log') {|io| io << 'This is an IO' }
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should write into file from io' do
|
88
|
+
Redisk::IO.to_file('dump_test.log', 'tmp/dump_test.log')
|
89
|
+
File.read('tmp/dump_test.log').should == 'This is an IO'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should write into File from io' do
|
93
|
+
Redisk::IO.to_file('dump_test.log', File.open('tmp/dump_test.log', 'w'))
|
94
|
+
File.read('tmp/dump_test.log').should == 'This is an IO'
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
48
99
|
describe 'open' do
|
49
100
|
|
50
101
|
it 'should return an IO object if no block is given' do
|
@@ -68,15 +119,32 @@ describe Redisk::IO do
|
|
68
119
|
describe 'read' do
|
69
120
|
|
70
121
|
it 'should return the entire contents without arguments' do
|
71
|
-
Redisk::IO.read(@io_name).should == @file_as_array.join("
|
122
|
+
Redisk::IO.read(@io_name).should == @file_as_array.join("")
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should return the first [length] bytes' do
|
126
|
+
Redisk::IO.read(@io_name, 2).should == @file_as_array[0][0..1]
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should return [length] contents starting at [offset]' do
|
130
|
+
Redisk::IO.read(@io_name, 2, 2).should == @file_as_array[0][2..3]
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
describe 'read_lines' do
|
137
|
+
|
138
|
+
it 'should return the entire contents without arguments' do
|
139
|
+
Redisk::IO.read_lines(@io_name).should == @file_as_array.join("")
|
72
140
|
end
|
73
141
|
|
74
142
|
it 'should return the first [length] contents' do
|
75
|
-
Redisk::IO.
|
143
|
+
Redisk::IO.read_lines(@io_name, 2).should == @file_as_array[0..1].join("")
|
76
144
|
end
|
77
145
|
|
78
146
|
it 'should return [length] contents starting at [offset]' do
|
79
|
-
Redisk::IO.
|
147
|
+
Redisk::IO.read_lines(@io_name, 2, 2).should == @file_as_array[2..3].join("")
|
80
148
|
end
|
81
149
|
|
82
150
|
end
|
@@ -99,7 +167,7 @@ describe Redisk::IO do
|
|
99
167
|
it 'should append a line to the io' do
|
100
168
|
@io << 'whu'
|
101
169
|
@io.lineno = 100
|
102
|
-
@io.gets.should ==
|
170
|
+
@io.gets.should == "whu"
|
103
171
|
end
|
104
172
|
|
105
173
|
it 'should return the text' do
|
@@ -109,10 +177,56 @@ describe Redisk::IO do
|
|
109
177
|
it 'should be able to chain' do
|
110
178
|
@io << 'whu ' << 'zuh'
|
111
179
|
@io.lineno = 100
|
112
|
-
@io.gets.should ==
|
180
|
+
@io.gets.should == "whu zuh"
|
113
181
|
end
|
114
182
|
|
115
183
|
end
|
184
|
+
|
185
|
+
describe '#close_read' do
|
186
|
+
|
187
|
+
it 'should close the io for reading' do
|
188
|
+
@io.close_read
|
189
|
+
lambda {
|
190
|
+
@io.gets
|
191
|
+
}.should raise_error(IOError)
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '#close_write' do
|
197
|
+
it 'should close the io for writing' do
|
198
|
+
@io.close_write
|
199
|
+
lambda {
|
200
|
+
@io.puts
|
201
|
+
}.should raise_error(IOError)
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
describe '#close' do
|
207
|
+
|
208
|
+
it 'should close for reading and writing' do
|
209
|
+
@io.close
|
210
|
+
lambda {
|
211
|
+
@io.puts
|
212
|
+
}.should raise_error(IOError)
|
213
|
+
lambda {
|
214
|
+
@io.gets
|
215
|
+
}.should raise_error(IOError)
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
describe '#closed?' do
|
221
|
+
|
222
|
+
it 'should only return true if both streams are closed' do
|
223
|
+
@io.close_read
|
224
|
+
@io.closed?.should == false
|
225
|
+
@io.close_write
|
226
|
+
@io.closed?.should == true
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
116
230
|
|
117
231
|
describe '#each' do
|
118
232
|
|
@@ -136,7 +250,29 @@ describe Redisk::IO do
|
|
136
250
|
end
|
137
251
|
|
138
252
|
end
|
139
|
-
|
253
|
+
|
254
|
+
describe '#each_byte' do
|
255
|
+
|
256
|
+
it 'should yield each byte as a fixnum to a block' do
|
257
|
+
i = 0
|
258
|
+
all_bytes = @file_as_array.join('')
|
259
|
+
@io.each_byte {|b|
|
260
|
+
b.should be_kind_of(Fixnum)
|
261
|
+
b.should == all_bytes[i].ord
|
262
|
+
i+=1
|
263
|
+
}
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'should advance the pos of the io' do
|
267
|
+
i = 0
|
268
|
+
@io.each_byte {|b|
|
269
|
+
i+=1
|
270
|
+
@io.pos.should == i
|
271
|
+
}
|
272
|
+
end
|
273
|
+
|
274
|
+
end
|
275
|
+
|
140
276
|
describe '#eof' do
|
141
277
|
|
142
278
|
it 'should return false if lineno is not the end of the file' do
|
@@ -150,6 +286,28 @@ describe Redisk::IO do
|
|
150
286
|
|
151
287
|
end
|
152
288
|
|
289
|
+
describe '#getc' do
|
290
|
+
|
291
|
+
it 'should get the next byte from the file as a fixnum' do
|
292
|
+
val = @io.getc
|
293
|
+
val.should be_kind_of(Fixnum)
|
294
|
+
val.should == @file_as_array[0].ord
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should increment the pos of the io' do
|
298
|
+
@io.getc
|
299
|
+
@io.pos.should == 1
|
300
|
+
@io.getc
|
301
|
+
@io.pos.should == 2
|
302
|
+
end
|
303
|
+
|
304
|
+
it 'should get the next line if necessary' do
|
305
|
+
@io.pos = @file_as_array[0].length + 1
|
306
|
+
@io.getc.should == @file_as_array[1][0].ord
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
153
311
|
describe '#gets' do
|
154
312
|
|
155
313
|
it 'should return the next line from the io' do
|
@@ -185,12 +343,35 @@ describe Redisk::IO do
|
|
185
343
|
@io.gets.should == @file_as_array[50]
|
186
344
|
end
|
187
345
|
end
|
346
|
+
|
347
|
+
describe '#pos' do
|
348
|
+
|
349
|
+
it 'should return the current pos' do
|
350
|
+
@io.pos.should == 0
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
|
355
|
+
describe '#pos=' do
|
356
|
+
|
357
|
+
it 'should set the pos' do
|
358
|
+
@io.pos = 5
|
359
|
+
@io.pos.should == 5
|
360
|
+
@io.getc.should == @file_as_array[0][5].ord
|
361
|
+
end
|
362
|
+
|
363
|
+
it 'should set the lineno based on the pos' do
|
364
|
+
@io.pos = @file_as_array[0].length + 2
|
365
|
+
@io.lineno.should == 2
|
366
|
+
end
|
367
|
+
|
368
|
+
end
|
188
369
|
|
189
370
|
describe '#print' do
|
190
371
|
|
191
372
|
it 'should append arguments into a string and write to io' do
|
192
373
|
@io.print('My ', 'name ', 'is ', 'redisk')
|
193
|
-
line = Redisk::IO.
|
374
|
+
line = Redisk::IO.read_lines(@io_name, 1, 100)
|
194
375
|
line.should == 'My name is redisk'
|
195
376
|
end
|
196
377
|
|
@@ -201,7 +382,7 @@ describe Redisk::IO do
|
|
201
382
|
it 'should write the contents of $_ if no arguments are provided' do
|
202
383
|
@io.gets
|
203
384
|
@io.print
|
204
|
-
line = Redisk::IO.
|
385
|
+
line = Redisk::IO.read_lines(@io_name, 1, 100)
|
205
386
|
line.should == @file_as_array[0]
|
206
387
|
end
|
207
388
|
end
|
@@ -210,7 +391,7 @@ describe Redisk::IO do
|
|
210
391
|
|
211
392
|
it 'should run the arguments through sprintf and print to the io' do
|
212
393
|
@io.printf('My name is %s', 'redisk')
|
213
|
-
line = Redisk::IO.
|
394
|
+
line = Redisk::IO.read_lines(@io_name, 1, 100)
|
214
395
|
line.should == 'My name is redisk'
|
215
396
|
end
|
216
397
|
|
@@ -221,19 +402,68 @@ describe Redisk::IO do
|
|
221
402
|
it 'should write each argument to the io' do
|
222
403
|
@io.puts('1', '2', '3')
|
223
404
|
@io.lineno = 100
|
224
|
-
@io.gets.should ==
|
225
|
-
@io.gets.should ==
|
226
|
-
@io.gets.should ==
|
405
|
+
@io.gets.should == "1\n"
|
406
|
+
@io.gets.should == "2\n"
|
407
|
+
@io.gets.should == "3\n"
|
227
408
|
end
|
228
409
|
|
229
410
|
it 'should write a blank string if no argument is passed' do
|
230
411
|
@io.puts
|
231
412
|
@io.lineno = 100
|
232
|
-
@io.gets.should ==
|
413
|
+
@io.gets.should == "\n"
|
233
414
|
end
|
234
415
|
|
235
416
|
end
|
236
417
|
|
418
|
+
describe '#read' do
|
419
|
+
|
420
|
+
it 'should read to the end of the file if [length] is ommited' do
|
421
|
+
@io.read.should == @file_as_array.join("")
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'should read into the [buffer] if a buffer is passed' do
|
425
|
+
string = "new string\n"
|
426
|
+
@io.read(nil, string)
|
427
|
+
string.should == "new string\n" + @file_as_array.join("")
|
428
|
+
end
|
429
|
+
|
430
|
+
it 'should read [length] bytes from the IO' do
|
431
|
+
val = @io.read(20)
|
432
|
+
val.length.should == 20
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'should return nil if [length] is passed at the eof' do
|
436
|
+
@io.pos = 1000000
|
437
|
+
@io.eof?.should == true
|
438
|
+
@io.read(5).should == nil
|
439
|
+
end
|
440
|
+
|
441
|
+
it 'should return "" if no [length] is passed at the eof' do
|
442
|
+
@io.pos = 1000000
|
443
|
+
@io.eof?.should == true
|
444
|
+
@io.read(nil).should == ""
|
445
|
+
end
|
446
|
+
|
447
|
+
end
|
448
|
+
|
449
|
+
describe '#readbytes' do
|
450
|
+
|
451
|
+
it 'should read [n] bytes from the io' do
|
452
|
+
val = @io.readbytes(10)
|
453
|
+
val.length.should == 10
|
454
|
+
val.should == @file_as_array.join("")[0...10]
|
455
|
+
end
|
456
|
+
|
457
|
+
it 'should raise EOFError if the data is nil' do
|
458
|
+
@io.each_byte {|b| b }
|
459
|
+
@io.eof?.should == true
|
460
|
+
lambda {
|
461
|
+
@io.readbytes(10)
|
462
|
+
}.should raise_error(EOFError)
|
463
|
+
end
|
464
|
+
|
465
|
+
end
|
466
|
+
|
237
467
|
describe '#readline' do
|
238
468
|
|
239
469
|
it 'should read the next line with gets' do
|
@@ -270,26 +500,26 @@ describe Redisk::IO do
|
|
270
500
|
|
271
501
|
describe '#seek' do
|
272
502
|
|
273
|
-
it 'should set the
|
503
|
+
it 'should set the pos to the absolute location' do
|
274
504
|
@io.seek(10)
|
275
|
-
@io.
|
505
|
+
@io.pos.should == 10
|
276
506
|
end
|
277
507
|
|
278
|
-
it 'should set the
|
508
|
+
it 'should set the pos to the absolute location with SEEK_SET' do
|
279
509
|
@io.seek(15, IO::SEEK_SET)
|
280
|
-
@io.
|
510
|
+
@io.pos.should == 15
|
281
511
|
end
|
282
512
|
|
283
|
-
it 'should set the
|
513
|
+
it 'should set the pos to the location relative to the end with SEEK_END' do
|
284
514
|
@io.seek(-5, IO::SEEK_END)
|
285
|
-
@io.
|
515
|
+
@io.pos.should == @file_as_array.join.length - 5
|
286
516
|
end
|
287
517
|
|
288
|
-
it 'should set the
|
289
|
-
@io.
|
290
|
-
@io.
|
518
|
+
it 'should set the pos to an offset position from the current line with SEEK_CUR' do
|
519
|
+
@io.pos = 5
|
520
|
+
@io.pos.should == 5
|
291
521
|
@io.seek(5, IO::SEEK_CUR)
|
292
|
-
@io.
|
522
|
+
@io.pos.should == 10
|
293
523
|
end
|
294
524
|
|
295
525
|
end
|
@@ -300,7 +530,7 @@ describe Redisk::IO do
|
|
300
530
|
@stat = @io.stat
|
301
531
|
@stat.should be_instance_of(Redisk::Stat)
|
302
532
|
@stat.atime.should be_instance_of(Time)
|
303
|
-
@stat.size.should
|
533
|
+
@stat.size.should be_instance_of(Fixnum)
|
304
534
|
end
|
305
535
|
|
306
536
|
end
|
@@ -329,6 +559,42 @@ describe Redisk::IO do
|
|
329
559
|
|
330
560
|
end
|
331
561
|
|
562
|
+
describe '#ungetc' do
|
563
|
+
|
564
|
+
it 'should put the string represented by a fixnum at the end of the io buffer' do
|
565
|
+
@io.ungetc 65
|
566
|
+
@io.flush
|
567
|
+
last_char = nil
|
568
|
+
@io.each_byte {|b| last_char = b }
|
569
|
+
last_char.should == 65
|
570
|
+
end
|
571
|
+
|
572
|
+
it 'should return nil' do
|
573
|
+
@io.ungetc(65).should == nil
|
574
|
+
end
|
575
|
+
|
576
|
+
end
|
577
|
+
|
578
|
+
describe '#unlink' do
|
579
|
+
before do
|
580
|
+
@io.unlink
|
581
|
+
end
|
582
|
+
|
583
|
+
it 'should delete all keys associated with the io' do
|
584
|
+
Redisk.redis.get(@key).should == nil
|
585
|
+
Redisk::Stat.new(@key).size.should == 0
|
586
|
+
end
|
587
|
+
|
588
|
+
it 'should close the stream' do
|
589
|
+
@io.closed?.should == true
|
590
|
+
end
|
591
|
+
|
592
|
+
it 'should remove the key from the list of ios' do
|
593
|
+
Redisk::IO.all.should_not include(@io_name)
|
594
|
+
end
|
595
|
+
|
596
|
+
end
|
597
|
+
|
332
598
|
end
|
333
599
|
|
334
600
|
describe 'As an interface for logger' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redisk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Quint
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-22 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -54,9 +54,12 @@ extra_rdoc_files:
|
|
54
54
|
files:
|
55
55
|
- .document
|
56
56
|
- .gitignore
|
57
|
+
- HISTORY
|
57
58
|
- LICENSE
|
58
59
|
- README.rdoc
|
59
60
|
- Rakefile
|
61
|
+
- examples/rails.rb
|
62
|
+
- examples/yajl.rb
|
60
63
|
- lib/redisk.rb
|
61
64
|
- lib/redisk/helper.rb
|
62
65
|
- lib/redisk/io.rb
|
@@ -103,3 +106,5 @@ test_files:
|
|
103
106
|
- spec/redisk_logger_spec.rb
|
104
107
|
- spec/redisk_stat_spec.rb
|
105
108
|
- spec/spec_helper.rb
|
109
|
+
- examples/rails.rb
|
110
|
+
- examples/yajl.rb
|