cassilds 0.9.2 → 0.12.1
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/CHANGELOG +51 -1
- data/LICENSE +0 -0
- data/Manifest +25 -7
- data/README.md +352 -0
- data/Rakefile +169 -1
- data/cassilds.gemspec +45 -0
- data/conf/{cassandra.in.sh → 0.6/cassandra.in.sh} +0 -0
- data/conf/{log4j.properties → 0.6/log4j.properties} +0 -0
- data/conf/0.6/schema.json +57 -0
- data/conf/{storage-conf.xml → 0.6/storage-conf.xml} +15 -5
- data/conf/0.7/cassandra.in.sh +46 -0
- data/conf/0.7/cassandra.yaml +336 -0
- data/conf/0.7/log4j-server.properties +41 -0
- data/conf/0.7/schema.json +57 -0
- data/conf/0.7/schema.txt +45 -0
- data/conf/0.8/cassandra.in.sh +41 -0
- data/conf/0.8/cassandra.yaml +61 -0
- data/conf/0.8/log4j-server.properties +40 -0
- data/conf/0.8/schema.json +66 -0
- data/conf/0.8/schema.txt +51 -0
- data/lib/cassandra/0.6/cassandra.rb +58 -13
- data/lib/cassandra/0.6/columns.rb +43 -0
- data/lib/cassandra/0.6/protocol.rb +16 -18
- data/lib/cassandra/0.6.rb +0 -0
- data/lib/cassandra/0.7/cassandra.rb +0 -270
- data/lib/cassandra/0.7/columns.rb +1 -64
- data/lib/cassandra/0.7/protocol.rb +0 -134
- data/lib/cassandra/0.7.rb +0 -0
- data/lib/cassandra/0.8/cassandra.rb +10 -0
- data/lib/cassandra/0.8/columns.rb +4 -0
- data/lib/cassandra/0.8/protocol.rb +23 -0
- data/lib/cassandra/0.8.rb +7 -0
- data/lib/cassandra/array.rb +0 -0
- data/lib/cassandra/cassandra.rb +877 -111
- data/lib/cassandra/{0.7/column_family.rb → column_family.rb} +0 -0
- data/lib/cassandra/columns.rb +72 -6
- data/lib/cassandra/comparable.rb +0 -0
- data/lib/cassandra/constants.rb +0 -0
- data/lib/cassandra/debug.rb +0 -0
- data/lib/cassandra/helpers.rb +1 -0
- data/lib/cassandra/{0.7/keyspace.rb → keyspace.rb} +0 -0
- data/lib/cassandra/long.rb +5 -0
- data/lib/cassandra/mock.rb +259 -85
- data/lib/cassandra/ordered_hash.rb +10 -18
- data/lib/cassandra/protocol.rb +120 -0
- data/lib/cassandra/time.rb +0 -0
- data/lib/cassandra.rb +6 -7
- data/test/cassandra_client_test.rb +0 -0
- data/test/cassandra_mock_test.rb +52 -28
- data/test/cassandra_test.rb +465 -44
- data/test/comparable_types_test.rb +0 -0
- data/test/eventmachine_test.rb +30 -30
- data/test/ordered_hash_test.rb +6 -0
- data/test/test_helper.rb +3 -2
- data/vendor/0.6/gen-rb/cassandra.rb +0 -0
- data/vendor/0.6/gen-rb/cassandra_constants.rb +0 -0
- data/vendor/0.6/gen-rb/cassandra_types.rb +0 -0
- data/vendor/0.7/gen-rb/cassandra.rb +0 -0
- data/vendor/0.7/gen-rb/cassandra_constants.rb +0 -0
- data/vendor/0.7/gen-rb/cassandra_types.rb +4 -2
- data/vendor/0.8/gen-rb/cassandra.rb +2215 -0
- data/vendor/0.8/gen-rb/cassandra_constants.rb +12 -0
- data/vendor/0.8/gen-rb/cassandra_types.rb +816 -0
- metadata +50 -27
- data/README.rdoc +0 -83
- data/cassandra.gemspec +0 -46
- data/conf/cassandra.yaml +0 -113
data/test/cassandra_test.rb
CHANGED
@@ -4,15 +4,21 @@ class CassandraTest < Test::Unit::TestCase
|
|
4
4
|
include Cassandra::Constants
|
5
5
|
|
6
6
|
def setup
|
7
|
-
@twitter = Cassandra.new('Twitter', "127.0.0.1:9160", :retries => 2, :exception_classes => [])
|
7
|
+
@twitter = Cassandra.new('Twitter', "127.0.0.1:9160", :retries => 2, :connect_timeout => 0.1, :exception_classes => [])
|
8
8
|
@twitter.clear_keyspace!
|
9
9
|
|
10
|
-
@blogs = Cassandra.new('Multiblog')
|
10
|
+
@blogs = Cassandra.new('Multiblog', "127.0.0.1:9160", :retries => 2, :connect_timeout => 0.1, :exception_classes => [])
|
11
11
|
@blogs.clear_keyspace!
|
12
12
|
|
13
|
-
@blogs_long = Cassandra.new('MultiblogLong')
|
13
|
+
@blogs_long = Cassandra.new('MultiblogLong', "127.0.0.1:9160", :retries => 2, :connect_timeout => 0.1, :exception_classes => [])
|
14
14
|
@blogs_long.clear_keyspace!
|
15
15
|
|
16
|
+
@type_conversions = Cassandra.new('TypeConversions', "127.0.0.1:9160", :retries => 2, :connect_timeout => 0.1, :exception_classes => [])
|
17
|
+
@type_conversions.clear_keyspace!
|
18
|
+
|
19
|
+
Cassandra::WRITE_DEFAULTS[:consistency] = Cassandra::Consistency::ONE
|
20
|
+
Cassandra::READ_DEFAULTS[:consistency] = Cassandra::Consistency::ONE
|
21
|
+
|
16
22
|
@uuids = (0..6).map {|i| SimpleUUID::UUID.new(Time.at(2**(24+i))) }
|
17
23
|
@longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
|
18
24
|
end
|
@@ -24,13 +30,37 @@ class CassandraTest < Test::Unit::TestCase
|
|
24
30
|
end
|
25
31
|
end
|
26
32
|
|
33
|
+
def test_setting_default_consistency
|
34
|
+
assert_nothing_raised do
|
35
|
+
@twitter.default_read_consistency = Cassandra::Consistency::ALL
|
36
|
+
end
|
37
|
+
assert_equal(Cassandra::READ_DEFAULTS[:consistency], Cassandra::Consistency::ALL)
|
38
|
+
|
39
|
+
assert_nothing_raised do
|
40
|
+
@twitter.default_write_consistency = Cassandra::Consistency::ALL
|
41
|
+
end
|
42
|
+
assert_equal(Cassandra::WRITE_DEFAULTS[:consistency], Cassandra::Consistency::ALL)
|
43
|
+
end
|
44
|
+
|
27
45
|
def test_get_key
|
46
|
+
|
28
47
|
@twitter.insert(:Users, key, {'body' => 'v', 'user' => 'v'})
|
29
48
|
assert_equal({'body' => 'v', 'user' => 'v'}, @twitter.get(:Users, key))
|
30
49
|
assert_equal(['body', 'user'].sort, @twitter.get(:Users, key).timestamps.keys.sort)
|
31
50
|
assert_equal({}, @twitter.get(:Users, 'bogus'))
|
32
51
|
end
|
33
52
|
|
53
|
+
def test_get_single_column_returns_single_value
|
54
|
+
@twitter.insert(:Users, key, {'body' => 'body_text', 'user' => 'user_name'})
|
55
|
+
assert_equal('body_text', @twitter.get(:Users, key, 'body'))
|
56
|
+
assert_equal('user_name', @twitter.get(:Users, key, 'user'))
|
57
|
+
|
58
|
+
@blogs.insert(:Blogs, key,
|
59
|
+
{@uuids[0] => 'I like this cat', @uuids[1] => 'Buttons is cuter', @uuids[2] => 'I disagree'})
|
60
|
+
|
61
|
+
assert_equal('I like this cat', @blogs.get(:Blogs, key, @uuids[0]))
|
62
|
+
end
|
63
|
+
|
34
64
|
def test_get_key_preserving_order
|
35
65
|
# In-order hash is preserved
|
36
66
|
hash = OrderedHash['a', '', 'b', '', 'c', '', 'd', '',]
|
@@ -43,7 +73,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
43
73
|
hash = OrderedHash['b', '', 'c', '', 'd', '', 'a', '']
|
44
74
|
@twitter.insert(:Users, key, hash)
|
45
75
|
assert_equal(hash.keys.sort, @twitter.get(:Users, key).keys)
|
46
|
-
assert_equal(hash.timestamps.keys.sort, @twitter.get(:Users, key).timestamps.keys
|
76
|
+
assert_equal(hash.timestamps.keys.sort, @twitter.get(:Users, key).timestamps.keys)
|
47
77
|
assert_not_equal(hash.keys, @twitter.get(:Users, key).keys)
|
48
78
|
end
|
49
79
|
|
@@ -102,9 +132,39 @@ class CassandraTest < Test::Unit::TestCase
|
|
102
132
|
assert !@twitter.exists?(:Statuses, 'bogus', 'body')
|
103
133
|
end
|
104
134
|
|
105
|
-
def
|
135
|
+
def test_get_value_with_range
|
136
|
+
k = key
|
137
|
+
|
138
|
+
10.times do |i|
|
139
|
+
@twitter.insert(:Statuses, k, {"body-#{i}" => 'v'})
|
140
|
+
end
|
141
|
+
|
142
|
+
assert_equal 5, @twitter.get(:Statuses, k, :count => 5).length
|
143
|
+
assert_equal 5, @twitter.get(:Statuses, k, :start => "body-5").length
|
144
|
+
assert_equal 5, @twitter.get(:Statuses, k, :finish => "body-4").length
|
145
|
+
assert_equal 5, @twitter.get(:Statuses, k, :start => "body-1", :count => 5).length
|
146
|
+
assert_equal 5, @twitter.get(:Statuses, k, :start => "body-0", :finish => "body-4", :count => 7).length
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_exists
|
106
150
|
@twitter.insert(:Statuses, key, {'body' => 'v'})
|
107
|
-
|
151
|
+
assert_equal true, @twitter.exists?(:Statuses, key)
|
152
|
+
assert_equal false, @twitter.exists?(:Statuses, 'bogus')
|
153
|
+
|
154
|
+
columns = {@uuids[1] => 'v1', @uuids[2] => 'v2'}
|
155
|
+
@twitter.insert(:StatusRelationships, key, {'user_timelines' => columns})
|
156
|
+
|
157
|
+
# verify return value when searching by key
|
158
|
+
assert_equal true, @twitter.exists?(:StatusRelationships, key)
|
159
|
+
assert_equal false, @twitter.exists?(:StatusRelationships, 'bogus')
|
160
|
+
|
161
|
+
# verify return value when searching by key and column
|
162
|
+
assert_equal true, @twitter.exists?(:StatusRelationships, key, 'user_timelines')
|
163
|
+
assert_equal false, @twitter.exists?(:StatusRelationships, key, 'bogus')
|
164
|
+
|
165
|
+
# verify return value when searching by key and column and subcolumn
|
166
|
+
assert_equal true, @twitter.exists?(:StatusRelationships, key, 'user_timelines', @uuids[1])
|
167
|
+
assert_equal false, @twitter.exists?(:StatusRelationships, key, 'user_timelines', @uuids[3])
|
108
168
|
end
|
109
169
|
|
110
170
|
def test_get_super_key
|
@@ -116,9 +176,11 @@ class CassandraTest < Test::Unit::TestCase
|
|
116
176
|
end
|
117
177
|
|
118
178
|
def test_get_several_super_keys
|
119
|
-
columns =
|
120
|
-
'
|
121
|
-
'
|
179
|
+
columns = OrderedHash[
|
180
|
+
'mentions_timelines', {@uuids[2] => 'v2'},
|
181
|
+
'user_timelines', {@uuids[1] => 'v1'}
|
182
|
+
]
|
183
|
+
|
122
184
|
@twitter.insert(:StatusRelationships, key, columns)
|
123
185
|
|
124
186
|
assert_equal(columns, @twitter.get(:StatusRelationships, key))
|
@@ -165,7 +227,7 @@ class CassandraTest < Test::Unit::TestCase
|
|
165
227
|
assert_equal(columns.keys.sort, @twitter.get(:StatusRelationships, key, 'user_timelines').timestamps.keys.sort)
|
166
228
|
assert_equal({}, @twitter.get(:StatusRelationships, 'bogus', 'user_timelines'))
|
167
229
|
# FIXME Not sure if this is valid
|
168
|
-
|
230
|
+
assert_equal false, @twitter.exists?(:StatusRelationships, 'bogus', 'user_timelines')
|
169
231
|
end
|
170
232
|
|
171
233
|
def test_get_super_value
|
@@ -175,24 +237,129 @@ class CassandraTest < Test::Unit::TestCase
|
|
175
237
|
assert_nil @twitter.get(:StatusRelationships, 'bogus', 'user_timelines', columns.keys.first)
|
176
238
|
end
|
177
239
|
|
240
|
+
# def test_get_range_with_key_range
|
241
|
+
# skip('This test requires the use of OrderPreservingPartitioner on the cluster to work properly.')
|
242
|
+
# k = key
|
243
|
+
# @twitter.insert(:Statuses, k + '2', {'body' => '1'})
|
244
|
+
# @twitter.insert(:Statuses, k + '3', {'body' => '1'})
|
245
|
+
# @twitter.insert(:Statuses, k + '4', {'body' => '1'})
|
246
|
+
# @twitter.insert(:Statuses, k + '5', {'body' => '1'})
|
247
|
+
# @twitter.insert(:Statuses, k + '6', {'body' => '1'})
|
248
|
+
# assert_equal([k + '3', k + '4', k + '5'], @twitter.get_range(:Statuses, :start_key => k + '3', :finish_key => k + '5').keys)
|
249
|
+
# end
|
250
|
+
|
251
|
+
def test_get_range
|
252
|
+
# make sure that deleted rows are not included in the iteration
|
253
|
+
10.times do |i|
|
254
|
+
@twitter.insert(:Statuses, i.to_s, {'body' => '1'})
|
255
|
+
@twitter.insert(:Statuses, i.to_s + '_delete_me', {'test' => 'value'})
|
256
|
+
@twitter.remove(:Statuses, i.to_s + '_delete_me')
|
257
|
+
end
|
178
258
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
259
|
+
assert_equal(4, @twitter.get_range_keys(:Statuses, :key_count => 4).size)
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_get_range_with_count
|
263
|
+
@twitter.insert(:Statuses, key + '1', {'test_column1' => '1', 'test_column2' => '2', 'test_column3' => '2', 'deleted_column' => '1'})
|
264
|
+
@twitter.insert(:Statuses, key + '2', {'test_column4' => '3', 'test_column5' => '4', 'test_column6' => '2', 'deleted_column' => '2'})
|
265
|
+
|
266
|
+
@twitter.get_range(:Statuses, :count => 3) do |key, columns|
|
267
|
+
assert_equal columns.count, 3
|
268
|
+
end
|
269
|
+
|
270
|
+
assert_equal 2, @twitter.get_range(:Statuses, :start_key => key + '1', :finish_key => key + '1', :count => 2)[key + '1'].count
|
271
|
+
|
272
|
+
@twitter.remove(:Statuses, key + '1', 'deleted_column')
|
273
|
+
@twitter.remove(:Statuses, key + '2', 'deleted_column')
|
274
|
+
|
275
|
+
@twitter.get_range(:Statuses, :count => 2) do |key, columns|
|
276
|
+
assert_equal columns.count, 2
|
277
|
+
end
|
188
278
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_get_range_block
|
282
|
+
k = key
|
283
|
+
5.times do |i|
|
284
|
+
@twitter.insert(:Statuses, k+i.to_s, {"body-#{i.to_s}" => 'v'})
|
285
|
+
end
|
286
|
+
|
287
|
+
values = (0..4).collect{|n| { :key => "test_get_range_block#{n}", :columns => { "body-#{n}" => "v" }} }.reverse
|
288
|
+
|
289
|
+
returned_value = @twitter.get_range(:Statuses, :start_key => k.to_s, :key_count => 5) do |key,columns|
|
290
|
+
expected = values.pop
|
291
|
+
assert_equal expected[:key], key
|
292
|
+
assert_equal expected[:columns], columns
|
293
|
+
end
|
294
|
+
|
295
|
+
assert_equal [], values
|
296
|
+
assert_nil returned_value
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_get_range_reversed
|
300
|
+
data = 3.times.map { |i| ["body-#{i.to_s}", "v"] }
|
301
|
+
hash = Cassandra::OrderedHash[data]
|
302
|
+
reversed_hash = Cassandra::OrderedHash[data.reverse]
|
303
|
+
|
304
|
+
@twitter.insert(:Statuses, "all-keys", hash)
|
305
|
+
|
306
|
+
columns = @twitter.get_range(:Statuses, :reversed => true)["all-keys"]
|
307
|
+
columns.each do |column|
|
308
|
+
assert_equal reversed_hash.shift, column
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_each_key
|
313
|
+
k = key
|
314
|
+
keys_yielded = []
|
315
|
+
|
316
|
+
10.times do |i|
|
317
|
+
@twitter.insert(:Statuses, k + i.to_s, {"body-#{i.to_s}" => 'v'})
|
318
|
+
end
|
319
|
+
|
320
|
+
# make sure that deleted rows are not included in the iteration
|
321
|
+
@twitter.insert(:Statuses, k + '_delete_me', {'test' => 'value'})
|
322
|
+
@twitter.remove(:Statuses, k + '_delete_me')
|
323
|
+
|
324
|
+
@twitter.each_key(:Statuses) do |key|
|
325
|
+
keys_yielded << key
|
326
|
+
end
|
327
|
+
|
328
|
+
assert_equal 10, keys_yielded.length
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_each
|
332
|
+
k = key
|
333
|
+
key_columns = {}
|
334
|
+
|
335
|
+
10.times do |i|
|
336
|
+
key_columns[k + i.to_s] = {"body-#{i.to_s}" => 'v', 'single_column_lookup' => "value = #{i.to_s}"}
|
337
|
+
@twitter.insert(:Statuses, k + i.to_s, key_columns[k + i.to_s])
|
338
|
+
end
|
339
|
+
|
340
|
+
keys_yielded = []
|
341
|
+
@twitter.each(:Statuses, :batch_size => 5) do |key, columns|
|
342
|
+
assert_equal key_columns[key], columns
|
343
|
+
keys_yielded << key
|
344
|
+
end
|
345
|
+
|
346
|
+
assert_equal 10, keys_yielded.length
|
347
|
+
|
348
|
+
keys_yielded = []
|
349
|
+
@twitter.each(:Statuses, :key_count => 7, :batch_size => 5) do |key, columns|
|
350
|
+
assert_equal key_columns[key], columns
|
351
|
+
keys_yielded << key
|
352
|
+
end
|
353
|
+
|
354
|
+
assert_equal 7, keys_yielded.length, 'each limits to specified count'
|
355
|
+
|
356
|
+
keys_yielded = []
|
357
|
+
@twitter.each(:Statuses, :columns => ['single_column_lookup'], :batch_size => 5) do |key, columns|
|
358
|
+
assert_equal key_columns[key].reject {|k2,v| k2 != 'single_column_lookup'}, columns
|
359
|
+
keys_yielded << key
|
360
|
+
end
|
361
|
+
|
362
|
+
assert_equal 10, keys_yielded.length
|
196
363
|
end
|
197
364
|
|
198
365
|
def test_multi_get
|
@@ -220,6 +387,13 @@ class CassandraTest < Test::Unit::TestCase
|
|
220
387
|
assert_equal({}, @twitter.get(:Statuses, key))
|
221
388
|
end
|
222
389
|
|
390
|
+
def test_remove_super_sub_key_errors_for_normal_column_family
|
391
|
+
@twitter.insert(:Statuses, key, {'body' => 'v'})
|
392
|
+
assert_equal({'body' => 'v'}, @twitter.get(:Statuses, key))
|
393
|
+
|
394
|
+
assert_raise( ArgumentError) { @twitter.remove(:Statuses, key, 'body' , 'subcolumn') }
|
395
|
+
end
|
396
|
+
|
223
397
|
def test_remove_value
|
224
398
|
@twitter.insert(:Statuses, key, {'body' => 'v'})
|
225
399
|
@twitter.remove(:Statuses, key, 'body')
|
@@ -240,11 +414,12 @@ class CassandraTest < Test::Unit::TestCase
|
|
240
414
|
end
|
241
415
|
|
242
416
|
def test_remove_super_value
|
243
|
-
columns = {@uuids[1] => 'v1'}
|
417
|
+
columns = {@uuids[1] => 'v1', @uuids[2] => 'v2'}
|
418
|
+
column_name_to_remove = @uuids[2]
|
244
419
|
@twitter.insert(:StatusRelationships, key, {'user_timelines' => columns})
|
245
|
-
@twitter.remove(:StatusRelationships, key, 'user_timelines',
|
246
|
-
|
247
|
-
assert_nil @twitter.get(:StatusRelationships, key, 'user_timelines').timestamps[
|
420
|
+
@twitter.remove(:StatusRelationships, key, 'user_timelines', column_name_to_remove)
|
421
|
+
assert_equal( columns.reject{|k,v| k == column_name_to_remove}, @twitter.get(:StatusRelationships, key, 'user_timelines') )
|
422
|
+
assert_nil @twitter.get(:StatusRelationships, key, 'user_timelines').timestamps[column_name_to_remove]
|
248
423
|
end
|
249
424
|
|
250
425
|
def test_clear_column_family
|
@@ -306,15 +481,21 @@ class CassandraTest < Test::Unit::TestCase
|
|
306
481
|
end
|
307
482
|
|
308
483
|
def test_count_keys
|
309
|
-
|
310
|
-
@twitter.insert(:Statuses,
|
311
|
-
@twitter.insert(:Statuses,
|
484
|
+
k = key
|
485
|
+
@twitter.insert(:Statuses, k + "1", {'body' => '1'})
|
486
|
+
@twitter.insert(:Statuses, k + "2", {'body' => '2'})
|
487
|
+
@twitter.insert(:Statuses, k + "3", {'body' => '3'})
|
312
488
|
assert_equal 3, @twitter.count_range(:Statuses)
|
313
489
|
end
|
314
490
|
|
315
491
|
def test_count_columns
|
316
|
-
|
317
|
-
|
492
|
+
columns = (1..200).inject(Hash.new){|h,v| h['column' + v.to_s] = v.to_s; h;}
|
493
|
+
|
494
|
+
@twitter.insert(:Statuses, key, columns)
|
495
|
+
assert_equal 200, @twitter.count_columns(:Statuses, key, :count => 200)
|
496
|
+
assert_equal 100, @twitter.count_columns(:Statuses, key)
|
497
|
+
assert_equal 55, @twitter.count_columns(:Statuses, key, :count => 55)
|
498
|
+
|
318
499
|
end
|
319
500
|
|
320
501
|
def test_count_super_columns
|
@@ -343,24 +524,45 @@ class CassandraTest < Test::Unit::TestCase
|
|
343
524
|
def test_batch_mutate
|
344
525
|
k = key
|
345
526
|
|
527
|
+
@twitter.insert(:Users, k + '0', {'delete_me' => 'v0', 'keep_me' => 'v0'})
|
346
528
|
@twitter.insert(:Users, k + '1', {'body' => 'v1', 'user' => 'v1'})
|
529
|
+
initial_subcolumns = {@uuids[1] => 'v1', @uuids[2] => 'v2'}
|
530
|
+
@twitter.insert(:StatusRelationships, k, {'user_timelines' => initial_subcolumns, 'dummy_supercolumn' => {@uuids[5] => 'value'}})
|
531
|
+
assert_equal(initial_subcolumns, @twitter.get(:StatusRelationships, k, 'user_timelines'))
|
532
|
+
assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn'))
|
533
|
+
new_subcolumns = {@uuids[3] => 'v3', @uuids[4] => 'v4'}
|
534
|
+
subcolumn_to_delete = initial_subcolumns.keys.first # the first column of the initial set
|
347
535
|
|
348
536
|
@twitter.batch do
|
537
|
+
# Normal Columns
|
349
538
|
@twitter.insert(:Users, k + '2', {'body' => 'v2', 'user' => 'v2'})
|
350
539
|
@twitter.insert(:Users, k + '3', {'body' => 'bogus', 'user' => 'v3'})
|
351
540
|
@twitter.insert(:Users, k + '3', {'body' => 'v3', 'location' => 'v3'})
|
352
541
|
@twitter.insert(:Statuses, k + '3', {'body' => 'v'})
|
353
542
|
|
543
|
+
assert_equal({'delete_me' => 'v0', 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # Written
|
354
544
|
assert_equal({'body' => 'v1', 'user' => 'v1'}, @twitter.get(:Users, k + '1')) # Written
|
355
545
|
assert_equal({}, @twitter.get(:Users, k + '2')) # Not yet written
|
356
546
|
assert_equal({}, @twitter.get(:Statuses, k + '3')) # Not yet written
|
357
547
|
|
358
|
-
@twitter.remove(:Users, k + '1')
|
548
|
+
@twitter.remove(:Users, k + '1') # Full row
|
359
549
|
assert_equal({'body' => 'v1', 'user' => 'v1'}, @twitter.get(:Users, k + '1')) # Not yet removed
|
360
550
|
|
551
|
+
@twitter.remove(:Users, k + '0', 'delete_me') # A single column of the row
|
552
|
+
assert_equal({'delete_me' => 'v0', 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # Not yet removed
|
553
|
+
|
361
554
|
@twitter.remove(:Users, k + '4')
|
362
555
|
@twitter.insert(:Users, k + '4', {'body' => 'v4', 'user' => 'v4'})
|
363
556
|
assert_equal({}, @twitter.get(:Users, k + '4')) # Not yet written
|
557
|
+
|
558
|
+
# SuperColumns
|
559
|
+
# Add and delete new sub columns to the user timeline supercolumn
|
560
|
+
@twitter.insert(:StatusRelationships, k, {'user_timelines' => new_subcolumns })
|
561
|
+
@twitter.remove(:StatusRelationships, k, 'user_timelines' , subcolumn_to_delete ) # Delete the first of the initial_subcolumns from the user_timeline supercolumn
|
562
|
+
assert_equal(initial_subcolumns, @twitter.get(:StatusRelationships, k, 'user_timelines')) # No additions or deletes reflected yet
|
563
|
+
# Delete a complete supercolumn
|
564
|
+
@twitter.remove(:StatusRelationships, k, 'dummy_supercolumn' ) # Delete the full dummy supercolumn
|
565
|
+
assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn')) # dummy supercolumn not yet deleted
|
364
566
|
end
|
365
567
|
|
366
568
|
assert_equal({'body' => 'v2', 'user' => 'v2'}, @twitter.get(:Users, k + '2')) # Written
|
@@ -368,11 +570,20 @@ class CassandraTest < Test::Unit::TestCase
|
|
368
570
|
assert_equal({'body' => 'v4', 'user' => 'v4'}, @twitter.get(:Users, k + '4')) # Written
|
369
571
|
assert_equal({'body' => 'v'}, @twitter.get(:Statuses, k + '3')) # Written
|
370
572
|
assert_equal({}, @twitter.get(:Users, k + '1')) # Removed
|
573
|
+
|
574
|
+
assert_equal({ 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # 'delete_me' column removed
|
575
|
+
|
371
576
|
|
372
577
|
assert_equal({'body' => 'v2', 'user' => 'v2'}.keys.sort, @twitter.get(:Users, k + '2').timestamps.keys.sort) # Written
|
373
578
|
assert_equal({'body' => 'v3', 'user' => 'v3', 'location' => 'v3'}.keys.sort, @twitter.get(:Users, k + '3').timestamps.keys.sort) # Written and compacted
|
374
579
|
assert_equal({'body' => 'v4', 'user' => 'v4'}.keys.sort, @twitter.get(:Users, k + '4').timestamps.keys.sort) # Written
|
375
580
|
assert_equal({'body' => 'v'}.keys.sort, @twitter.get(:Statuses, k + '3').timestamps.keys.sort) # Written
|
581
|
+
|
582
|
+
# Final result: initial_subcolumns - initial_subcolumns.first + new_subcolumns
|
583
|
+
resulting_subcolumns = initial_subcolumns.merge(new_subcolumns).reject{|k2,v| k2 == subcolumn_to_delete }
|
584
|
+
assert_equal(resulting_subcolumns, @twitter.get(:StatusRelationships, key, 'user_timelines'))
|
585
|
+
assert_equal({}, @twitter.get(:StatusRelationships, key, 'dummy_supercolumn')) # dummy supercolumn deleted
|
586
|
+
|
376
587
|
end
|
377
588
|
|
378
589
|
def test_complain_about_nil_key
|
@@ -381,15 +592,8 @@ class CassandraTest < Test::Unit::TestCase
|
|
381
592
|
end
|
382
593
|
end
|
383
594
|
|
384
|
-
def test_raise_access_error_on_nonexistent_keyspace
|
385
|
-
nonexistent = Cassandra.new('Nonexistent')
|
386
|
-
assert_raises(Cassandra::AccessError) do
|
387
|
-
nonexistent.get "foo", "bar"
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
595
|
def test_nil_sub_column_value
|
392
|
-
@twitter.insert(:
|
596
|
+
@twitter.insert(:Indexes, 'asdf', {"thing" => {'jkl' => ''} })
|
393
597
|
end
|
394
598
|
|
395
599
|
def test_disconnect!
|
@@ -397,6 +601,13 @@ class CassandraTest < Test::Unit::TestCase
|
|
397
601
|
assert_nil @twitter.instance_variable_get(:@client)
|
398
602
|
end
|
399
603
|
|
604
|
+
def test_disconnect_when_not_connected!
|
605
|
+
assert_nothing_raised do
|
606
|
+
@twitter = Cassandra.new('Twitter', "127.0.0.1:9160", :retries => 2, :exception_classes => [])
|
607
|
+
@twitter.disconnect!
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
400
611
|
def test_super_allows_for_non_string_values_while_normal_does_not
|
401
612
|
columns = {'user_timelines' => {@uuids[4] => '4', @uuids[5] => '5'}}
|
402
613
|
|
@@ -404,6 +615,216 @@ class CassandraTest < Test::Unit::TestCase
|
|
404
615
|
@twitter.insert(:Statuses, key, { 'body' => '1' })
|
405
616
|
end
|
406
617
|
|
618
|
+
def test_batch_over_deletes
|
619
|
+
k = key
|
620
|
+
|
621
|
+
@twitter.batch do
|
622
|
+
@twitter.insert(:Users, k, {'body' => 'body', 'user' => 'user'})
|
623
|
+
@twitter.remove(:Users, k, 'body')
|
624
|
+
end
|
625
|
+
|
626
|
+
assert_equal({'user' => 'user'}, @twitter.get(:Users, k))
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_each_key
|
630
|
+
num_users = rand(60)
|
631
|
+
num_users.times do |twit_counter|
|
632
|
+
@twitter.insert(:Users, "Twitter : #{twit_counter}", {'body' => 'v1', 'user' => 'v1'})
|
633
|
+
end
|
634
|
+
counter = 0
|
635
|
+
@twitter.each_key(:Users) do |_, _|
|
636
|
+
counter += 1
|
637
|
+
end
|
638
|
+
assert_equal num_users, counter
|
639
|
+
end
|
640
|
+
|
641
|
+
def test_each_with_column_predicate
|
642
|
+
num_users = rand(60)
|
643
|
+
num_users.times do |twit_counter|
|
644
|
+
@twitter.insert(:Users, "Twitter : #{twit_counter}", {'body' => 'v1', 'user' => 'v1'})
|
645
|
+
end
|
646
|
+
counter = 0
|
647
|
+
@twitter.each(:Users, :batch_size => 10, :start => 'body', :finish => 'body') do |key, columns|
|
648
|
+
assert_equal 1, columns.length
|
649
|
+
counter += 1
|
650
|
+
end
|
651
|
+
assert_equal num_users, counter
|
652
|
+
end
|
653
|
+
|
654
|
+
def test_each_with_super_column
|
655
|
+
num_users = rand(50)
|
656
|
+
block_name = key
|
657
|
+
num_users.times do |twit_counter|
|
658
|
+
@twitter.insert(:StatusRelationships, block_name + twit_counter.to_s, {
|
659
|
+
'user_timelines' => {@uuids[1] => 'v1', @uuids[2] => 'v2'},
|
660
|
+
'mentions_timelines' => {@uuids[3] => 'v3'}})
|
661
|
+
end
|
662
|
+
|
663
|
+
counter = 0
|
664
|
+
# Restrict to one super column ::
|
665
|
+
@twitter.each(:StatusRelationships, :batch_size => 10, :start => 'user_timelines', :finish => 'user_timelines') do |key, columns|
|
666
|
+
columns.each do |_, column_value|
|
667
|
+
assert_equal 2, column_value.length
|
668
|
+
end
|
669
|
+
counter += 1
|
670
|
+
end
|
671
|
+
|
672
|
+
#Both super columns
|
673
|
+
@twitter.each(:StatusRelationships, :batch_size => 10, :start => 'mentions_timelines', :finish => 'user_timelines') do |key,columns|
|
674
|
+
assert_equal 2, columns.length
|
675
|
+
counter += 1
|
676
|
+
end
|
677
|
+
|
678
|
+
assert_equal num_users*2, counter
|
679
|
+
|
680
|
+
end
|
681
|
+
|
682
|
+
def test_each_column_types
|
683
|
+
num_users = rand(60)
|
684
|
+
num_users.times do |twit_counter|
|
685
|
+
@type_conversions.insert(:UUIDColumnConversion, twit_counter.to_s, {@uuids[1] => 'v1'})
|
686
|
+
end
|
687
|
+
counter = 0
|
688
|
+
@type_conversions.each(:UUIDColumnConversion) do |_, columns|
|
689
|
+
counter += 1
|
690
|
+
columns.keys.each {|column_name| assert_equal SimpleUUID::UUID, column_name.class}
|
691
|
+
end
|
692
|
+
assert_equal num_users, counter
|
693
|
+
end
|
694
|
+
|
695
|
+
|
696
|
+
if CASSANDRA_VERSION.to_f >= 0.7
|
697
|
+
def test_creating_and_dropping_new_index
|
698
|
+
@twitter.create_index('Twitter', 'Statuses', 'column_name', 'LongType')
|
699
|
+
assert_nil @twitter.create_index('Twitter', 'Statuses', 'column_name', 'LongType')
|
700
|
+
|
701
|
+
@twitter.drop_index('Twitter', 'Statuses', 'column_name')
|
702
|
+
assert_nil @twitter.drop_index('Twitter', 'Statuses', 'column_name')
|
703
|
+
|
704
|
+
# Recreating and redropping the same index should not error either.
|
705
|
+
@twitter.create_index('Twitter', 'Statuses', 'column_name', 'LongType')
|
706
|
+
@twitter.drop_index('Twitter', 'Statuses', 'column_name')
|
707
|
+
end
|
708
|
+
|
709
|
+
def test_get_indexed_slices
|
710
|
+
@twitter.create_index('Twitter', 'Statuses', 'x', 'LongType')
|
711
|
+
|
712
|
+
@twitter.insert(:Statuses, 'row1', { 'x' => [0,10].pack("NN") })
|
713
|
+
|
714
|
+
(2..10).to_a.each do |i|
|
715
|
+
@twitter.insert(:Statuses, 'row' + i.to_s, { 'x' => [0,20].pack("NN"), 'non_indexed' => [i].pack('N*') })
|
716
|
+
end
|
717
|
+
|
718
|
+
@twitter.insert(:Statuses, 'row11', { 'x' => [0,30].pack("NN") })
|
719
|
+
|
720
|
+
expressions = [{:column_name => 'x', :value => [0,20].pack("NN"), :comparison => "=="}]
|
721
|
+
|
722
|
+
# verify multiples will be returned
|
723
|
+
assert_equal 9, @twitter.get_indexed_slices(:Statuses, expressions).length
|
724
|
+
|
725
|
+
# verify that GT and LT queries perform properly
|
726
|
+
expressions = [
|
727
|
+
{:column_name => 'x', :value => [0,20].pack("NN"), :comparison => "=="},
|
728
|
+
{:column_name => 'non_indexed', :value => [5].pack("N*"), :comparison => ">"}
|
729
|
+
]
|
730
|
+
assert_equal(5, @twitter.get_indexed_slices(:Statuses, expressions).length)
|
731
|
+
end
|
732
|
+
|
733
|
+
def test_old_get_indexed_slices
|
734
|
+
@twitter.create_index('Twitter', 'Statuses', 'x', 'LongType')
|
735
|
+
|
736
|
+
@twitter.insert(:Statuses, 'row1', { 'x' => [0,10].pack("NN") })
|
737
|
+
|
738
|
+
(2..10).to_a.each do |i|
|
739
|
+
@twitter.insert(:Statuses, 'row' + i.to_s, { 'x' => [0,20].pack("NN"), 'non_indexed' => [i].pack('N*') })
|
740
|
+
end
|
741
|
+
|
742
|
+
@twitter.insert(:Statuses, 'row11', { 'x' => [0,30].pack("NN") })
|
743
|
+
|
744
|
+
idx_expr = @twitter.create_idx_expr('x', [0,20].pack("NN"), "==")
|
745
|
+
|
746
|
+
# verify count is observed
|
747
|
+
idx_clause = @twitter.create_idx_clause([idx_expr], "", 1)
|
748
|
+
assert_equal 1, @twitter.get_indexed_slices(:Statuses, idx_clause).length
|
749
|
+
|
750
|
+
# verify multiples will be returned
|
751
|
+
idx_clause = @twitter.create_idx_clause([idx_expr])
|
752
|
+
assert_equal 9, @twitter.get_indexed_slices(:Statuses, idx_clause).length
|
753
|
+
|
754
|
+
# verify that GT and LT queries perform properly
|
755
|
+
idx_expr = [
|
756
|
+
@twitter.create_idx_expr('x', [0,20].pack("NN"), "=="),
|
757
|
+
@twitter.create_idx_expr('non_indexed', [5].pack("N*"), ">")
|
758
|
+
]
|
759
|
+
idx_clause = @twitter.create_idx_clause(idx_expr)
|
760
|
+
assert_equal(5, @twitter.get_indexed_slices(:Statuses, idx_clause).length)
|
761
|
+
end
|
762
|
+
|
763
|
+
def test_column_family_mutation
|
764
|
+
k = key
|
765
|
+
|
766
|
+
if @twitter.column_families.include?(k)
|
767
|
+
@twitter.drop_column_family(k)
|
768
|
+
end
|
769
|
+
|
770
|
+
# Verify add_column_family works as desired.
|
771
|
+
@twitter.add_column_family(
|
772
|
+
Cassandra::ColumnFamily.new(
|
773
|
+
:keyspace => 'Twitter',
|
774
|
+
:name => k
|
775
|
+
)
|
776
|
+
)
|
777
|
+
assert @twitter.column_families.include?(k)
|
778
|
+
|
779
|
+
if CASSANDRA_VERSION.to_f == 0.7
|
780
|
+
# Verify rename_column_family works properly
|
781
|
+
@twitter.rename_column_family(k, k + '_renamed')
|
782
|
+
assert @twitter.column_families.include?(k + '_renamed')
|
783
|
+
|
784
|
+
# Change it back and validate
|
785
|
+
@twitter.rename_column_family(k + '_renamed', k)
|
786
|
+
assert @twitter.column_families.include?(k)
|
787
|
+
end
|
788
|
+
|
789
|
+
temp_cf_def = @twitter.column_families[k]
|
790
|
+
temp_cf_def.comment = k
|
791
|
+
@twitter.update_column_family(temp_cf_def)
|
792
|
+
assert @twitter.column_families.include?(k)
|
793
|
+
|
794
|
+
@twitter.drop_column_family(k)
|
795
|
+
assert !@twitter.column_families.include?(k)
|
796
|
+
end
|
797
|
+
end
|
798
|
+
|
799
|
+
if CASSANDRA_VERSION.to_f >= 0.8
|
800
|
+
def test_adding_getting_value_in_counter
|
801
|
+
assert_nil @twitter.add(:UserCounters, 'bob', 5, 'tweet_count')
|
802
|
+
assert_equal(5, @twitter.get(:UserCounters, 'bob', 'tweet_count'))
|
803
|
+
assert_nil @twitter.get(:UserCounters, 'bogus', 'tweet_count')
|
804
|
+
end
|
805
|
+
|
806
|
+
def test_get_counter_slice
|
807
|
+
assert_nil @twitter.add(:UserCounters, 'bob', 5, 'tweet_count')
|
808
|
+
assert_equal({'tweet_count' => 5}, @twitter.get(:UserCounters, 'bob', :start => "tweet_count", :finish => "tweet_count"))
|
809
|
+
end
|
810
|
+
|
811
|
+
def test_adding_getting_value_in_multiple_counters
|
812
|
+
assert_nil @twitter.add(:UserCounters, 'bob', 5, 'tweet_count')
|
813
|
+
assert_nil @twitter.add(:UserCounters, 'bob', 7, 'follower_count')
|
814
|
+
assert_equal(5, @twitter.get(:UserCounters, 'bob', 'tweet_count'))
|
815
|
+
assert_nil @twitter.get(:UserCounters, 'bogus', 'tweet_count')
|
816
|
+
assert_equal([5, 7], @twitter.get_columns(:UserCounters, 'bob', ['tweet_count', 'follower_count']))
|
817
|
+
assert_equal([5, 7, nil], @twitter.get_columns(:UserCounters, 'bob', ['tweet_count', 'follower_count', 'bogus']))
|
818
|
+
end
|
819
|
+
|
820
|
+
def test_adding_getting_value_in_multiple_counters_with_super_columns
|
821
|
+
assert_nil @twitter.add(:UserCounterAggregates, 'bob', 1, 'DAU', 'today')
|
822
|
+
assert_nil @twitter.add(:UserCounterAggregates, 'bob', 2, 'DAU', 'tomorrow')
|
823
|
+
assert_equal(1, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'today'))
|
824
|
+
assert_equal(2, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'tomorrow'))
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
407
828
|
private
|
408
829
|
|
409
830
|
def key
|
File without changes
|