cql-rb 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fddc76ac77bf418eab2dfd497c342b5104481a99
4
- data.tar.gz: f8b91abc145bf42ff716fb0af17b50d3a24b19cd
3
+ metadata.gz: e3f3bbe6a70ee126fc4ebcf7a33fcd19812bbc69
4
+ data.tar.gz: 28c7bf1d6d92bd3ac5fb8e38155a7ea6ee06eef5
5
5
  SHA512:
6
- metadata.gz: 8af6c7c7acc157843d1f0f0c101a2a42da30e8f0433f7d53f870a1ceadbf233416dfa2254af425a35ecc6a3c8aa2b6a54e4ad82c3cb0b342526d792e9b7ea06d
7
- data.tar.gz: 7f3472cda89cccb1674424a7bcef58bd52cdaacfa579eba56c83c6dbf2d826b4fe2ca0707c8b94eff2009e6b6377f514655ba49c8a80286adacb4b691c8c3185
6
+ metadata.gz: fd921b73960d9bd46289cfe98d3a18239b09df793b1eed9cf87f7d7e211e0d71716aed118ef1a536149722f0939d8466a24aed27b063e8819325e4286262b300
7
+ data.tar.gz: 95de3b5aaf74d6c7a072ebe054fd4cd73b92b16a6ecb1d02e629d73b675df04e00d8fec3cd8c646ab47c060a08bd4962c6f4df2c4edae0f5efc1909f07050148
data/README.md CHANGED
@@ -14,9 +14,7 @@ Cassandra 1.2 or later with the native transport protocol turned on and a modern
14
14
 
15
15
  gem install cql-rb
16
16
 
17
- if you want to use compression you should also install the [snappy gem](http://rubygems.org/gems/snappy):
18
-
19
- gem install snappy
17
+ if you want to use compression you should also install [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby). See below for more information about compression.
20
18
 
21
19
  # Quick start
22
20
 
@@ -270,7 +268,7 @@ Consistency is ignored for `USE`, `TRUNCATE`, `CREATE` and `ALTER` statements, a
270
268
 
271
269
  The CQL protocol supports frame compression, which can give you a performance boost if your requests or responses are big. To enable it you can pass a compressor object when you connect.
272
270
 
273
- Cassandra currently supports two compression algorithms: Snappy and LZ4. Support for Snappy compression ships with cql-rb, but in order to use it you will have to install the [snappy](http://rubygems.org/gems/snappy) gem separately. Once it's installed you can enable compression like this:
271
+ Cassandra currently supports two compression algorithms: Snappy and LZ4. cql-rb supports both, but in order to use them you will have to install the [snappy](http://rubygems.org/gems/snappy) or [lz4-ruby](http://rubygems.org/gems/lz4-ruby) gems separately. Once it's installed you can enable compression like this:
274
272
 
275
273
  ```ruby
276
274
  require 'cql/compression/snappy_compressor'
@@ -279,6 +277,17 @@ compressor = Cql::Compression::SnappyCompressor.new
279
277
  client = Cql::Client.connect(hosts: %w[localhost], compressor: compressor)
280
278
  ```
281
279
 
280
+ or
281
+
282
+ ```ruby
283
+ require 'cql/compression/lz4_compressor'
284
+
285
+ compressor = Cql::Compression::Lz4Compressor.new
286
+ client = Cql::Client.connect(hosts: %w[localhost], compressor: compressor)
287
+ ```
288
+
289
+ Which one should you choose? On paper the LZ4 algorithm is more efficient and the one Cassandra defaults to for SSTable compression. They both achieve roughly the same compression ratio, but LZ4 does it quicker.
290
+
282
291
  ## Logging
283
292
 
284
293
  You can pass a standard Ruby logger to the client to get some more information about what is going on:
@@ -187,10 +187,13 @@ module Cql
187
187
 
188
188
  def ensure_materialized
189
189
  unless @rows
190
- @lock.synchronize do
190
+ @lock.lock
191
+ begin
191
192
  unless @rows
192
193
  @rows = @lazy_rows.materialize(@raw_metadata)
193
194
  end
195
+ ensure
196
+ @lock.unlock
194
197
  end
195
198
  end
196
199
  end
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'lz4-ruby'
5
+ rescue LoadError => e
6
+ raise LoadError, %[LZ4 support requires the "lz4-ruby" gem: #{e.message}], e.backtrace
7
+ end
8
+
9
+ module Cql
10
+ module Compression
11
+ # A compressor that uses the LZ4 compression library.
12
+ #
13
+ # @note This compressor requires the [lz4-ruby](http://rubygems.org/gems/lz4-ruby)
14
+ # gem (v0.3.2 or later required).
15
+ class Lz4Compressor
16
+ # @return [String]
17
+ attr_reader :algorithm
18
+
19
+ # @param [Integer] min_size (64) Don't compress frames smaller than
20
+ # this size (see {#compress?}).
21
+ def initialize(min_size=64)
22
+ @algorithm = 'lz4'.freeze
23
+ @min_size = min_size
24
+ end
25
+
26
+ # @return [true, false] will return false for frames smaller than the
27
+ # `min_size` given to the constructor.
28
+ def compress?(str)
29
+ str.bytesize > @min_size
30
+ end
31
+
32
+ def compress(str)
33
+ [str.bytesize, LZ4::Raw.compress(str.to_s).first].pack(BUFFER_FORMAT)
34
+ end
35
+
36
+ def decompress(str)
37
+ decompressed_size, compressed_data = str.to_s.unpack(BUFFER_FORMAT)
38
+ LZ4::Raw.decompress(compressed_data, decompressed_size).first
39
+ end
40
+
41
+ private
42
+
43
+ BUFFER_FORMAT = 'Na*'.freeze
44
+ end
45
+ end
46
+ end
@@ -251,10 +251,14 @@ module Cql
251
251
  def append_varint(n)
252
252
  num = n
253
253
  bytes = []
254
- until num == 0
255
- bytes << (num & 0xff)
256
- num = num >> 8
257
- break if num == -1
254
+ if num == 0
255
+ bytes << 0
256
+ else
257
+ until num == 0
258
+ bytes << (num & 0xff)
259
+ num = num >> 8
260
+ break if num == -1
261
+ end
258
262
  end
259
263
  append(bytes.reverse.pack(Formats::BYTES_FORMAT))
260
264
  end
@@ -58,13 +58,19 @@ module Cql
58
58
  # connection has been set up, or to keep statistics specific to the
59
59
  # connection this protocol handler wraps.
60
60
  def []=(key, value)
61
- @lock.synchronize { @data[key] = value }
61
+ @lock.lock
62
+ @data[key] = value
63
+ ensure
64
+ @lock.unlock
62
65
  end
63
66
 
64
67
  # @see {#[]=}
65
68
  # @return the value associated with the key
66
69
  def [](key)
67
- @lock.synchronize { @data[key] }
70
+ @lock.lock
71
+ @data[key]
72
+ ensure
73
+ @lock.unlock
68
74
  end
69
75
 
70
76
  # @return [true, false] true if the underlying connection is connected
@@ -94,9 +100,10 @@ module Cql
94
100
  #
95
101
  # @yieldparam event [Cql::Protocol::EventResponse] an event sent by the server
96
102
  def on_event(&listener)
97
- @lock.synchronize do
98
- @event_listeners += [listener]
99
- end
103
+ @lock.lock
104
+ @event_listeners += [listener]
105
+ ensure
106
+ @lock.unlock
100
107
  end
101
108
 
102
109
  # Serializes and send a request over the underlying connection.
@@ -119,19 +126,25 @@ module Cql
119
126
  return Future.failed(NotConnectedError.new) if closed?
120
127
  promise = RequestPromise.new(request, @frame_encoder)
121
128
  id = nil
122
- @lock.synchronize do
129
+ @lock.lock
130
+ begin
123
131
  if (id = next_stream_id)
124
132
  @promises[id] = promise
125
133
  end
134
+ ensure
135
+ @lock.unlock
126
136
  end
127
137
  if id
128
138
  @connection.write do |buffer|
129
139
  @frame_encoder.encode_frame(request, id, buffer)
130
140
  end
131
141
  else
132
- @lock.synchronize do
142
+ @lock.lock
143
+ begin
133
144
  promise.encode_frame
134
145
  @request_queue_in << promise
146
+ ensure
147
+ @lock.unlock
135
148
  end
136
149
  end
137
150
  if timeout
@@ -196,9 +209,12 @@ module Cql
196
209
 
197
210
  def notify_event_listeners(event_response)
198
211
  event_listeners = nil
199
- @lock.synchronize do
212
+ @lock.lock
213
+ begin
200
214
  event_listeners = @event_listeners
201
215
  return if event_listeners.empty?
216
+ ensure
217
+ @lock.unlock
202
218
  end
203
219
  event_listeners.each do |listener|
204
220
  listener.call(@current_frame.body) rescue nil
@@ -206,10 +222,13 @@ module Cql
206
222
  end
207
223
 
208
224
  def complete_request(id, response)
209
- promise = @lock.synchronize do
225
+ promise = nil
226
+ @lock.lock
227
+ begin
210
228
  promise = @promises[id]
211
229
  @promises[id] = nil
212
- promise
230
+ ensure
231
+ @lock.unlock
213
232
  end
214
233
  if response.is_a?(Protocol::SetKeyspaceResultResponse)
215
234
  @keyspace = response.keyspace
@@ -220,16 +239,20 @@ module Cql
220
239
  end
221
240
 
222
241
  def flush_request_queue
223
- @lock.synchronize do
242
+ @lock.lock
243
+ begin
224
244
  if @request_queue_out.empty? && !@request_queue_in.empty?
225
245
  @request_queue_out = @request_queue_in
226
246
  @request_queue_in = []
227
247
  end
248
+ ensure
249
+ @lock.unlock
228
250
  end
229
251
  while true
230
252
  id = nil
231
253
  frame = nil
232
- @lock.synchronize do
254
+ @lock.lock
255
+ begin
233
256
  if @request_queue_out.any? && (id = next_stream_id)
234
257
  promise = @request_queue_out.shift
235
258
  if promise.timed_out?
@@ -239,6 +262,8 @@ module Cql
239
262
  @promises[id] = promise
240
263
  end
241
264
  end
265
+ ensure
266
+ @lock.unlock
242
267
  end
243
268
  if id
244
269
  @frame_encoder.change_stream_id(id, frame)
@@ -271,10 +296,11 @@ module Cql
271
296
  end
272
297
 
273
298
  def next_stream_id
274
- @promises.each_with_index do |task, index|
275
- return index if task.nil?
299
+ if (stream_id = @promises.index(nil))
300
+ stream_id
301
+ else
302
+ nil
276
303
  end
277
- nil
278
304
  end
279
305
  end
280
306
  end
@@ -18,9 +18,9 @@ module Cql
18
18
  end
19
19
 
20
20
  def <=>(other)
21
- c = self.time_bits <=> other.time_bits
22
- return c unless c == 0
23
- (self.value & LOWER_HALF_MASK) <=> (other.value & LOWER_HALF_MASK)
21
+ c = self.value <=> other.value
22
+ return c if c == 0
23
+ self.time_bits <=> other.time_bits
24
24
  end
25
25
 
26
26
  protected
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cql
4
- VERSION = '2.0.0'.freeze
4
+ VERSION = '2.0.1'.freeze
5
5
  end
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
 
6
- shared_examples 'compressor' do |algorithm|
6
+ shared_examples 'compressor' do |algorithm, compressed_string|
7
7
  describe '#algorithm' do
8
8
  it %(returns "#{algorithm}") do
9
9
  described_class.new.algorithm.should == algorithm
@@ -36,8 +36,20 @@ shared_examples 'compressor' do |algorithm|
36
36
  compressed.bytesize.should be < input.bytesize
37
37
  end
38
38
 
39
+ it 'compresses byte buffers' do
40
+ input = Cql::Protocol::CqlByteBuffer.new('hello' * 100)
41
+ compressed = compressor.compress(input)
42
+ compressed.should == compressor.compress(input.to_s)
43
+ end
44
+
39
45
  it 'decompresses compressed strings' do
40
- input = "\x19\x10helloN\x05\x00"
46
+ input = compressed_string
47
+ decompressed = compressor.decompress(input)
48
+ decompressed.should == 'hellohellohellohellohello'
49
+ end
50
+
51
+ it 'decompresses byte buffers' do
52
+ input = Cql::Protocol::CqlByteBuffer.new(compressed_string)
41
53
  decompressed = compressor.decompress(input)
42
54
  decompressed.should == 'hellohellohellohellohello'
43
55
  end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'cql/compression/compression_common'
5
+
6
+
7
+ module Cql
8
+ module Compression
9
+ begin
10
+ require 'cql/compression/lz4_compressor'
11
+
12
+ describe Lz4Compressor do
13
+ include_examples 'compressor', 'lz4', "\x00\x00\x01\xF4[hello\x05\x00Phello"
14
+ end
15
+ rescue LoadError => e
16
+ describe 'Lz4Compressor' do
17
+ it 'supports LZ4' do
18
+ pending e.message
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -10,7 +10,7 @@ module Cql
10
10
  require 'cql/compression/snappy_compressor'
11
11
 
12
12
  describe SnappyCompressor do
13
- include_examples 'compressor', 'snappy'
13
+ include_examples 'compressor', 'snappy', "\x19\x10helloN\x05\x00"
14
14
  end
15
15
  rescue LoadError => e
16
16
  describe 'SnappyCompressor' do
@@ -810,6 +810,11 @@ module Cql
810
810
  end
811
811
 
812
812
  describe '#append_varint' do
813
+ it 'encodes zero' do
814
+ buffer.append_varint(0)
815
+ buffer.should eql_bytes("\x00")
816
+ end
817
+
813
818
  it 'encodes a variable length integer' do
814
819
  buffer.append_varint(1231312312331283012830129382342342412123)
815
820
  buffer.should eql_bytes("\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a[")
@@ -843,6 +848,11 @@ module Cql
843
848
  buffer.should eql_bytes("\x00\x00\x00\x12\r'\xFDI\xAD\x80f\x11g\xDCfV\xAA")
844
849
  end
845
850
 
851
+ it 'encodes a 0.0 BigDecimal' do
852
+ buffer.append_decimal(BigDecimal.new('0.0'))
853
+ buffer.should eql_bytes("\x00\x00\x00\x01\x00")
854
+ end
855
+
846
856
  it 'appends to the buffer' do
847
857
  buffer << "\x99"
848
858
  buffer.append_decimal(BigDecimal.new('1042342234234.123423435647768234'))
@@ -32,6 +32,12 @@ module Cql
32
32
  it 'sorts by the time component' do
33
33
  uuids.shuffle.sort.should == uuids
34
34
  end
35
+
36
+ it 'allows comparison of UUID and TimeUUID' do
37
+ x = generator.next
38
+ y = Uuid.new(x.value)
39
+ x.should == y
40
+ end
35
41
  end
36
42
  end
37
43
 
@@ -252,29 +252,45 @@ describe 'A CQL client' do
252
252
  end
253
253
  end
254
254
 
255
- context 'with compression' do
256
- begin
257
- require 'cql/compression/snappy_compressor'
255
+ shared_examples 'with_compressor' do |compressor_impl|
256
+ let :client do
257
+ Cql::Client.connect(connection_options.merge(compressor: compressor))
258
+ end
258
259
 
259
- let :client do
260
- Cql::Client.connect(connection_options.merge(compressor: compressor))
261
- end
260
+ let :compressor do
261
+ compressor_impl.new(0)
262
+ end
262
263
 
263
- let :compressor do
264
- Cql::Compression::SnappyCompressor.new(0)
265
- end
264
+ it 'compresses requests and decompresses responses' do
265
+ compressor.stub(:compress).and_call_original
266
+ compressor.stub(:decompress).and_call_original
267
+ client.execute('SELECT * FROM system.schema_keyspaces')
268
+ compressor.should have_received(:compress).at_least(1).times
269
+ compressor.should have_received(:decompress).at_least(1).times
270
+ end
271
+ end
266
272
 
267
- it 'compresses requests and decompresses responses' do
268
- compressor.stub(:compress).and_call_original
269
- compressor.stub(:decompress).and_call_original
270
- client.execute('SELECT * FROM system.schema_keyspaces')
271
- compressor.should have_received(:compress).at_least(1).times
272
- compressor.should have_received(:decompress).at_least(1).times
273
- end
273
+ shared_examples 'no_compressor' do
274
+ it 'compresses requests and decompresses responses' do
275
+ pending 'No compressor available for the current platform'
276
+ end
277
+ end
278
+
279
+ context 'with Snappy compression' do
280
+ begin
281
+ require 'cql/compression/snappy_compressor'
282
+ include_examples 'with_compressor', Cql::Compression::SnappyCompressor
274
283
  rescue LoadError
275
- it 'compresses requests and decompresses responses' do
276
- pending 'No compressor available for the current platform'
277
- end
284
+ include_examples 'no_compressor'
285
+ end
286
+ end
287
+
288
+ context 'with LZ4 compression' do
289
+ begin
290
+ require 'cql/compression/lz4_compressor'
291
+ include_examples 'with_compressor', Cql::Compression::Lz4Compressor
292
+ rescue LoadError
293
+ include_examples 'no_compressor'
278
294
  end
279
295
  end
280
296
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cql-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Theo Hultberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-23 00:00:00.000000000 Z
11
+ date: 2014-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ione
@@ -52,6 +52,7 @@ files:
52
52
  - lib/cql/client/result_metadata.rb
53
53
  - lib/cql/client/void_result.rb
54
54
  - lib/cql/compression.rb
55
+ - lib/cql/compression/lz4_compressor.rb
55
56
  - lib/cql/compression/snappy_compressor.rb
56
57
  - lib/cql/protocol.rb
57
58
  - lib/cql/protocol/cql_byte_buffer.rb
@@ -105,6 +106,7 @@ files:
105
106
  - spec/cql/client/request_runner_spec.rb
106
107
  - spec/cql/client/void_result_spec.rb
107
108
  - spec/cql/compression/compression_common.rb
109
+ - spec/cql/compression/lz4_compressor_spec.rb
108
110
  - spec/cql/compression/snappy_compressor_spec.rb
109
111
  - spec/cql/protocol/cql_byte_buffer_spec.rb
110
112
  - spec/cql/protocol/cql_protocol_handler_spec.rb
@@ -187,6 +189,7 @@ test_files:
187
189
  - spec/cql/client/request_runner_spec.rb
188
190
  - spec/cql/client/void_result_spec.rb
189
191
  - spec/cql/compression/compression_common.rb
192
+ - spec/cql/compression/lz4_compressor_spec.rb
190
193
  - spec/cql/compression/snappy_compressor_spec.rb
191
194
  - spec/cql/protocol/cql_byte_buffer_spec.rb
192
195
  - spec/cql/protocol/cql_protocol_handler_spec.rb