cassilds 0.9.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 +53 -0
- data/LICENSE +202 -0
- data/Manifest +45 -0
- data/README.rdoc +83 -0
- data/Rakefile +9 -0
- data/bin/cassandra_helper +16 -0
- data/cassandra.gemspec +46 -0
- data/conf/cassandra.in.sh +47 -0
- data/conf/cassandra.yaml +113 -0
- data/conf/log4j.properties +38 -0
- data/conf/storage-conf.xml +342 -0
- data/lib/cassandra/0.6/cassandra.rb +68 -0
- data/lib/cassandra/0.6/columns.rb +35 -0
- data/lib/cassandra/0.6/protocol.rb +92 -0
- data/lib/cassandra/0.6.rb +7 -0
- data/lib/cassandra/0.7/cassandra.rb +272 -0
- data/lib/cassandra/0.7/column_family.rb +3 -0
- data/lib/cassandra/0.7/columns.rb +67 -0
- data/lib/cassandra/0.7/keyspace.rb +3 -0
- data/lib/cassandra/0.7/protocol.rb +139 -0
- data/lib/cassandra/0.7.rb +7 -0
- data/lib/cassandra/array.rb +8 -0
- data/lib/cassandra/cassandra.rb +302 -0
- data/lib/cassandra/columns.rb +79 -0
- data/lib/cassandra/comparable.rb +28 -0
- data/lib/cassandra/constants.rb +11 -0
- data/lib/cassandra/debug.rb +9 -0
- data/lib/cassandra/helpers.rb +40 -0
- data/lib/cassandra/long.rb +58 -0
- data/lib/cassandra/mock.rb +326 -0
- data/lib/cassandra/ordered_hash.rb +200 -0
- data/lib/cassandra/time.rb +11 -0
- data/lib/cassandra.rb +39 -0
- data/test/cassandra_client_test.rb +20 -0
- data/test/cassandra_mock_test.rb +73 -0
- data/test/cassandra_test.rb +412 -0
- data/test/comparable_types_test.rb +45 -0
- data/test/eventmachine_test.rb +42 -0
- data/test/ordered_hash_test.rb +380 -0
- data/test/test_helper.rb +14 -0
- data/vendor/0.6/gen-rb/cassandra.rb +1481 -0
- data/vendor/0.6/gen-rb/cassandra_constants.rb +12 -0
- data/vendor/0.6/gen-rb/cassandra_types.rb +482 -0
- data/vendor/0.7/gen-rb/cassandra.rb +1937 -0
- data/vendor/0.7/gen-rb/cassandra_constants.rb +12 -0
- data/vendor/0.7/gen-rb/cassandra_types.rb +679 -0
- metadata +176 -0
@@ -0,0 +1,326 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
class SimpleUUID::UUID
|
4
|
+
def >=(other)
|
5
|
+
(self <=> other) >= 0
|
6
|
+
end
|
7
|
+
|
8
|
+
def <=(other)
|
9
|
+
(self <=> other) <= 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Cassandra
|
14
|
+
class Mock
|
15
|
+
include ::Cassandra::Helpers
|
16
|
+
include ::Cassandra::Columns
|
17
|
+
|
18
|
+
def initialize(keyspace, storage_xml)
|
19
|
+
@keyspace = keyspace
|
20
|
+
@column_name_class = {}
|
21
|
+
@sub_column_name_class = {}
|
22
|
+
@storage_xml = storage_xml
|
23
|
+
clear_keyspace!
|
24
|
+
end
|
25
|
+
|
26
|
+
def disconnect!
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear_keyspace!
|
30
|
+
@data = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def clear_column_family!(column_family)
|
34
|
+
@data[column_family.to_sym] = OrderedHash.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def insert(column_family, key, hash_or_array, options = {})
|
38
|
+
if @batch
|
39
|
+
@batch << [:insert, column_family, key, hash_or_array, options]
|
40
|
+
else
|
41
|
+
raise ArgumentError if key.nil?
|
42
|
+
if column_family_type(column_family) == 'Standard'
|
43
|
+
insert_standard(column_family, key, hash_or_array)
|
44
|
+
else
|
45
|
+
insert_super(column_family, key, hash_or_array)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def insert_standard(column_family, key, hash_or_array)
|
51
|
+
old = cf(column_family)[key] || OrderedHash.new
|
52
|
+
cf(column_family)[key] = merge_and_sort(old, hash_or_array)
|
53
|
+
end
|
54
|
+
|
55
|
+
def insert_super(column_family, key, hash)
|
56
|
+
raise ArgumentError unless hash.is_a?(Hash)
|
57
|
+
cf(column_family)[key] ||= OrderedHash.new
|
58
|
+
|
59
|
+
hash.keys.each do |sub_key|
|
60
|
+
old = cf(column_family)[key][sub_key] || OrderedHash.new
|
61
|
+
cf(column_family)[key][sub_key] = merge_and_sort(old, hash[sub_key])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def batch
|
66
|
+
@batch = []
|
67
|
+
yield
|
68
|
+
b = @batch
|
69
|
+
@batch = nil
|
70
|
+
b.each do |mutation|
|
71
|
+
send(*mutation)
|
72
|
+
end
|
73
|
+
ensure
|
74
|
+
@batch = nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def get(column_family, key, *columns_and_options)
|
78
|
+
column_family, column, sub_column, options =
|
79
|
+
extract_and_validate_params_for_real(column_family, [key], columns_and_options, READ_DEFAULTS)
|
80
|
+
if column_family_type(column_family) == 'Standard'
|
81
|
+
get_standard(column_family, key, column, options)
|
82
|
+
else
|
83
|
+
get_super(column_family, key, column, sub_column, options)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_standard(column_family, key, column, options)
|
88
|
+
row = cf(column_family)[key] || OrderedHash.new
|
89
|
+
if column
|
90
|
+
row[column]
|
91
|
+
else
|
92
|
+
row = apply_range(row, column_family, options[:start], options[:finish])
|
93
|
+
apply_count(row, options[:count], options[:reversed])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_super(column_family, key, column, sub_column, options)
|
98
|
+
if column
|
99
|
+
if sub_column
|
100
|
+
if cf(column_family)[key] &&
|
101
|
+
cf(column_family)[key][column] &&
|
102
|
+
cf(column_family)[key][column][sub_column]
|
103
|
+
cf(column_family)[key][column][sub_column]
|
104
|
+
else
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
else
|
108
|
+
row = cf(column_family)[key] && cf(column_family)[key][column] ?
|
109
|
+
cf(column_family)[key][column] :
|
110
|
+
OrderedHash.new
|
111
|
+
row = apply_range(row, column_family, options[:start], options[:finish], false)
|
112
|
+
apply_count(row, options[:count], options[:reversed])
|
113
|
+
end
|
114
|
+
elsif cf(column_family)[key]
|
115
|
+
cf(column_family)[key]
|
116
|
+
else
|
117
|
+
OrderedHash.new
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def exists?(column_family, key, column=nil)
|
122
|
+
!!get(column_family, key, column)
|
123
|
+
end
|
124
|
+
|
125
|
+
def multi_get(column_family, keys, *columns_and_options)
|
126
|
+
column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, keys, columns_and_options, READ_DEFAULTS)
|
127
|
+
keys.inject(OrderedHash.new) do |hash, key|
|
128
|
+
hash[key] = get(column_family, key)
|
129
|
+
hash
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def remove(column_family, key, *columns_and_options)
|
134
|
+
column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, WRITE_DEFAULTS)
|
135
|
+
if @batch
|
136
|
+
@batch << [:remove, column_family, key, column]
|
137
|
+
else
|
138
|
+
if column
|
139
|
+
if sub_column
|
140
|
+
cf(column_family)[key][column].delete(sub_column)
|
141
|
+
else
|
142
|
+
cf(column_family)[key].delete(column)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
cf(column_family).delete(key)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_columns(column_family, key, *columns_and_options)
|
151
|
+
column_family, columns, sub_columns, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, READ_DEFAULTS)
|
152
|
+
d = get(column_family, key)
|
153
|
+
|
154
|
+
|
155
|
+
if sub_columns
|
156
|
+
sub_columns.collect do |sub_column|
|
157
|
+
d[columns][sub_column]
|
158
|
+
end
|
159
|
+
else
|
160
|
+
columns.collect do |column|
|
161
|
+
d[column]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def count_columns(column_family, key, column=nil)
|
167
|
+
get(column_family, key, column).keys.length
|
168
|
+
end
|
169
|
+
|
170
|
+
def multi_get_columns(column_family, keys, columns)
|
171
|
+
keys.inject(OrderedHash.new) do |hash, key|
|
172
|
+
hash[key] = get_columns(column_family, key, columns)
|
173
|
+
hash
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def multi_count_columns(column_family, keys)
|
178
|
+
keys.inject(OrderedHash.new) do |hash, key|
|
179
|
+
hash[key] = count_columns(column_family, key)
|
180
|
+
hash
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def get_range(column_family, options = {})
|
185
|
+
column_family, _, _, options = extract_and_validate_params_for_real(column_family, "", [options], READ_DEFAULTS)
|
186
|
+
_get_range(column_family, options[:start], options[:finish], options[:count]).keys
|
187
|
+
end
|
188
|
+
|
189
|
+
def count_range(column_family, options={})
|
190
|
+
count = 0
|
191
|
+
l = []
|
192
|
+
start_key = ''
|
193
|
+
while (l = get_range(column_family, options.merge(:count => 1000, :start => start_key))).size > 0
|
194
|
+
count += l.size
|
195
|
+
start_key = l.last.succ
|
196
|
+
end
|
197
|
+
count
|
198
|
+
end
|
199
|
+
|
200
|
+
def schema(load=true)
|
201
|
+
if !load && !@schema
|
202
|
+
[]
|
203
|
+
else
|
204
|
+
@schema ||= schema_for_keyspace(@keyspace)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def _get_range(column_family, start, finish, count)
|
211
|
+
ret = OrderedHash.new
|
212
|
+
start = to_compare_with_type(start, column_family)
|
213
|
+
finish = to_compare_with_type(finish, column_family)
|
214
|
+
cf(column_family).keys.sort.each do |key|
|
215
|
+
break if ret.keys.size >= count
|
216
|
+
if (start.nil? || key >= start) && (finish.nil? || key <= finish)
|
217
|
+
ret[key] = cf(column_family)[key]
|
218
|
+
end
|
219
|
+
end
|
220
|
+
ret
|
221
|
+
end
|
222
|
+
|
223
|
+
def schema_for_keyspace(keyspace)
|
224
|
+
doc = read_storage_xml
|
225
|
+
ret = {}
|
226
|
+
doc.css("Keyspaces Keyspace[@Name='#{keyspace}']").css('ColumnFamily').each do |cf|
|
227
|
+
ret[cf['Name']] = {}
|
228
|
+
if cf['CompareSubcolumnsWith']
|
229
|
+
ret[cf['Name']]['CompareSubcolumnsWith'] = 'org.apache.cassandra.db.marshal.' + cf['CompareSubcolumnsWith']
|
230
|
+
end
|
231
|
+
if cf['CompareWith']
|
232
|
+
ret[cf['Name']]['CompareWith'] = 'org.apache.cassandra.db.marshal.' + cf['CompareWith']
|
233
|
+
end
|
234
|
+
if cf['ColumnType'] == 'Super'
|
235
|
+
ret[cf['Name']]['Type'] = 'Super'
|
236
|
+
else
|
237
|
+
ret[cf['Name']]['Type'] = 'Standard'
|
238
|
+
end
|
239
|
+
end
|
240
|
+
ret
|
241
|
+
end
|
242
|
+
|
243
|
+
def read_storage_xml
|
244
|
+
@doc ||= Nokogiri::XML(open(@storage_xml))
|
245
|
+
end
|
246
|
+
|
247
|
+
def extract_and_validate_params_for_real(column_family, keys, args, options)
|
248
|
+
column_family, columns, sub_column, options = extract_and_validate_params(column_family, keys, args, options)
|
249
|
+
options[:start] = nil if options[:start] == ''
|
250
|
+
options[:finish] = nil if options[:finish] == ''
|
251
|
+
[column_family, to_compare_with_types(columns, column_family), to_compare_with_types(sub_column, column_family, false), options]
|
252
|
+
end
|
253
|
+
|
254
|
+
def to_compare_with_types(column_names, column_family, standard=true)
|
255
|
+
if column_names.is_a?(Array)
|
256
|
+
column_names.collect do |name|
|
257
|
+
to_compare_with_type(name, column_family, standard)
|
258
|
+
end
|
259
|
+
else
|
260
|
+
to_compare_with_type(column_names, column_family, standard)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def to_compare_with_type(column_name, column_family, standard=true)
|
265
|
+
return column_name if column_name.nil?
|
266
|
+
klass = if standard
|
267
|
+
schema[column_family.to_s]["CompareWith"]
|
268
|
+
else
|
269
|
+
schema[column_family.to_s]["CompareSubcolumnsWith"]
|
270
|
+
end
|
271
|
+
|
272
|
+
case klass
|
273
|
+
when "org.apache.cassandra.db.marshal.UTF8Type", "org.apache.cassandra.db.marshal.BytesType"
|
274
|
+
column_name
|
275
|
+
when "org.apache.cassandra.db.marshal.TimeUUIDType"
|
276
|
+
SimpleUUID::UUID.new(column_name)
|
277
|
+
when "org.apache.cassandra.db.marshal.LongType"
|
278
|
+
Long.new(column_name)
|
279
|
+
else
|
280
|
+
raise "Unknown column family type: #{klass.inspect}"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def column_family_type(column_family)
|
285
|
+
schema[column_family.to_s]['Type']
|
286
|
+
end
|
287
|
+
|
288
|
+
def cf(column_family)
|
289
|
+
@data[column_family.to_sym] ||= OrderedHash.new
|
290
|
+
end
|
291
|
+
|
292
|
+
def merge_and_sort(old_stuff, new_stuff)
|
293
|
+
if new_stuff.is_a?(Array)
|
294
|
+
new_stuff = new_stuff.inject({}){|h,k| h[k] = nil; h }
|
295
|
+
end
|
296
|
+
OrderedHash[old_stuff.merge(new_stuff).sort{|a,b| a[0] <=> b[0]}]
|
297
|
+
end
|
298
|
+
|
299
|
+
def apply_count(row, count, reversed=false)
|
300
|
+
if count
|
301
|
+
keys = row.keys.sort
|
302
|
+
keys = keys.reverse if reversed
|
303
|
+
keys = keys[0...count]
|
304
|
+
keys.inject(OrderedHash.new) do |memo, key|
|
305
|
+
memo[key] = row[key]
|
306
|
+
memo
|
307
|
+
end
|
308
|
+
else
|
309
|
+
row
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def apply_range(row, column_family, strt, fin, standard=true)
|
314
|
+
start = to_compare_with_type(strt, column_family, standard)
|
315
|
+
finish = to_compare_with_type(fin, column_family, standard)
|
316
|
+
ret = OrderedHash.new
|
317
|
+
row.keys.each do |key|
|
318
|
+
if (start.nil? || key >= start) && (finish.nil? || key <= finish)
|
319
|
+
ret[key] = row[key]
|
320
|
+
end
|
321
|
+
end
|
322
|
+
ret
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# OrderedHash is namespaced to prevent conflicts with other implementations
|
2
|
+
class Cassandra
|
3
|
+
# Hash is ordered in Ruby 1.9!
|
4
|
+
if RUBY_VERSION >= '1.9'
|
5
|
+
OrderedHashInt = ::Hash
|
6
|
+
else
|
7
|
+
class OrderedHashInt < Hash #:nodoc:
|
8
|
+
def initialize(*args, &block)
|
9
|
+
super
|
10
|
+
@keys = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.[](*args)
|
14
|
+
ordered_hash = new
|
15
|
+
|
16
|
+
if (args.length == 1 && args.first.is_a?(Array))
|
17
|
+
args.first.each do |key_value_pair|
|
18
|
+
next unless (key_value_pair.is_a?(Array))
|
19
|
+
ordered_hash[key_value_pair[0]] = key_value_pair[1]
|
20
|
+
end
|
21
|
+
|
22
|
+
return ordered_hash
|
23
|
+
end
|
24
|
+
|
25
|
+
unless (args.size % 2 == 0)
|
26
|
+
raise ArgumentError.new("odd number of arguments for Hash")
|
27
|
+
end
|
28
|
+
|
29
|
+
args.each_with_index do |val, ind|
|
30
|
+
next if (ind % 2 != 0)
|
31
|
+
ordered_hash[val] = args[ind + 1]
|
32
|
+
end
|
33
|
+
|
34
|
+
ordered_hash
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize_copy(other)
|
38
|
+
super
|
39
|
+
# make a deep copy of keys
|
40
|
+
@keys = other.keys
|
41
|
+
end
|
42
|
+
|
43
|
+
def []=(key, value)
|
44
|
+
@keys << key if !has_key?(key)
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(key)
|
49
|
+
if has_key? key
|
50
|
+
index = @keys.index(key)
|
51
|
+
@keys.delete_at index
|
52
|
+
end
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_if
|
57
|
+
super
|
58
|
+
sync_keys!
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
def reject!
|
63
|
+
super
|
64
|
+
sync_keys!
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def reject(&block)
|
69
|
+
dup.reject!(&block)
|
70
|
+
end
|
71
|
+
|
72
|
+
def keys
|
73
|
+
@keys.dup
|
74
|
+
end
|
75
|
+
|
76
|
+
def values
|
77
|
+
@keys.collect { |key| self[key] }
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_hash
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_a
|
85
|
+
@keys.map { |key| [ key, self[key] ] }
|
86
|
+
end
|
87
|
+
|
88
|
+
def each_key
|
89
|
+
@keys.each { |key| yield key }
|
90
|
+
end
|
91
|
+
|
92
|
+
def each_value
|
93
|
+
@keys.each { |key| yield self[key]}
|
94
|
+
end
|
95
|
+
|
96
|
+
def each
|
97
|
+
@keys.each {|key| yield [key, self[key]]}
|
98
|
+
end
|
99
|
+
|
100
|
+
alias_method :each_pair, :each
|
101
|
+
|
102
|
+
def clear
|
103
|
+
super
|
104
|
+
@keys.clear
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def shift
|
109
|
+
k = @keys.first
|
110
|
+
v = delete(k)
|
111
|
+
[k, v]
|
112
|
+
end
|
113
|
+
|
114
|
+
def merge!(other_hash)
|
115
|
+
other_hash.each {|k,v| self[k] = v }
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
def merge(other_hash)
|
120
|
+
dup.merge!(other_hash)
|
121
|
+
end
|
122
|
+
|
123
|
+
# When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
|
124
|
+
def replace(other)
|
125
|
+
super
|
126
|
+
@keys = other.keys
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def sync_keys!
|
133
|
+
@keys.delete_if {|k| !has_key?(k)}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class OrderedHash < OrderedHashInt #:nodoc:
|
139
|
+
def initialize(*args, &block)
|
140
|
+
@timestamps = Hash.new
|
141
|
+
super
|
142
|
+
end
|
143
|
+
|
144
|
+
def initialize_copy(other)
|
145
|
+
@timestamps = other.timestamps
|
146
|
+
super
|
147
|
+
end
|
148
|
+
|
149
|
+
def []=(key, value, timestamp = nil)
|
150
|
+
@timestamps[key] = timestamp
|
151
|
+
super(key, value)
|
152
|
+
end
|
153
|
+
|
154
|
+
def delete(key)
|
155
|
+
@timestamps.delete(key)
|
156
|
+
super
|
157
|
+
end
|
158
|
+
|
159
|
+
def delete_if
|
160
|
+
@timestamps.delete_if
|
161
|
+
super
|
162
|
+
end
|
163
|
+
|
164
|
+
def reject!
|
165
|
+
@timestamps.reject!
|
166
|
+
super
|
167
|
+
end
|
168
|
+
|
169
|
+
def timestamps
|
170
|
+
@timestamps.dup
|
171
|
+
end
|
172
|
+
|
173
|
+
def clear
|
174
|
+
@timestamps.clear
|
175
|
+
super
|
176
|
+
end
|
177
|
+
|
178
|
+
def shift
|
179
|
+
k, v = super
|
180
|
+
@timestamps.delete(k)
|
181
|
+
[k, v]
|
182
|
+
end
|
183
|
+
|
184
|
+
def replace(other)
|
185
|
+
@timestamps = other.timestamps
|
186
|
+
super
|
187
|
+
end
|
188
|
+
|
189
|
+
def inspect
|
190
|
+
"#<OrderedHash #{super}--TimeStamps: #{@timestamps.inspect}>"
|
191
|
+
end
|
192
|
+
|
193
|
+
private
|
194
|
+
|
195
|
+
def sync_keys!
|
196
|
+
@timestamps.delete_if {|k,v| !has_key?(k)}
|
197
|
+
super
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
data/lib/cassandra.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'thrift', '~> 0.5.0'
|
3
|
+
require 'thrift'
|
4
|
+
gem 'thrift_client', '~> 0.6.0'
|
5
|
+
require 'thrift_client'
|
6
|
+
gem 'simple_uuid' , '~> 0.1.0'
|
7
|
+
require 'simple_uuid'
|
8
|
+
|
9
|
+
require 'json' unless defined?(JSON)
|
10
|
+
|
11
|
+
here = File.expand_path(File.dirname(__FILE__))
|
12
|
+
|
13
|
+
class Cassandra ; end
|
14
|
+
unless Cassandra.respond_to?(:VERSION)
|
15
|
+
require "#{here}/cassandra/0.7"
|
16
|
+
end
|
17
|
+
|
18
|
+
$LOAD_PATH << "#{here}/../vendor/#{Cassandra.VERSION}/gen-rb"
|
19
|
+
require "#{here}/../vendor/#{Cassandra.VERSION}/gen-rb/cassandra"
|
20
|
+
|
21
|
+
$LOAD_PATH << "#{here}"
|
22
|
+
|
23
|
+
require 'cassandra/helpers'
|
24
|
+
require 'cassandra/array'
|
25
|
+
require 'cassandra/time'
|
26
|
+
require 'cassandra/comparable'
|
27
|
+
require 'cassandra/long'
|
28
|
+
require 'cassandra/ordered_hash'
|
29
|
+
require 'cassandra/columns'
|
30
|
+
require "cassandra/#{Cassandra.VERSION}/columns"
|
31
|
+
require "cassandra/#{Cassandra.VERSION}/protocol"
|
32
|
+
require "cassandra/cassandra"
|
33
|
+
require "cassandra/#{Cassandra.VERSION}/cassandra"
|
34
|
+
unless Cassandra.VERSION.eql?("0.6")
|
35
|
+
require "cassandra/#{Cassandra.VERSION}/column_family"
|
36
|
+
require "cassandra/#{Cassandra.VERSION}/keyspace"
|
37
|
+
end
|
38
|
+
require 'cassandra/constants'
|
39
|
+
require 'cassandra/debug' if ENV['DEBUG']
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
|
+
|
3
|
+
class CassandraClientTest < Test::Unit::TestCase
|
4
|
+
include Cassandra::Constants
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@twitter = Cassandra.new('Twitter', "127.0.0.1:9160", :retries => 2, :exception_classes => [])
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_client_method_is_called
|
11
|
+
assert_nil @twitter.instance_variable_get(:@client)
|
12
|
+
@twitter.insert(:Statuses, key, {'1' => 'v', '2' => 'v', '3' => 'v'})
|
13
|
+
assert_not_nil @twitter.instance_variable_get(:@client)
|
14
|
+
end
|
15
|
+
|
16
|
+
def key
|
17
|
+
caller.first[/`(.*?)'/, 1]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
|
+
require 'cassandra_test'
|
3
|
+
require 'cassandra/mock'
|
4
|
+
|
5
|
+
class CassandraMockTest < CassandraTest
|
6
|
+
include Cassandra::Constants
|
7
|
+
|
8
|
+
def setup
|
9
|
+
storage_xml_path = File.expand_path(File.join(File.dirname(File.dirname(__FILE__)), 'conf', 'storage-conf.xml'))
|
10
|
+
@twitter = Cassandra::Mock.new('Twitter', storage_xml_path)
|
11
|
+
@twitter.clear_keyspace!
|
12
|
+
|
13
|
+
@blogs = Cassandra::Mock.new('Multiblog', storage_xml_path)
|
14
|
+
@blogs.clear_keyspace!
|
15
|
+
|
16
|
+
@blogs_long = Cassandra::Mock.new('MultiblogLong', storage_xml_path)
|
17
|
+
@blogs_long.clear_keyspace!
|
18
|
+
|
19
|
+
@uuids = (0..6).map {|i| SimpleUUID::UUID.new(Time.at(2**(24+i))) }
|
20
|
+
@longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_setup
|
24
|
+
assert @twitter
|
25
|
+
assert @blogs
|
26
|
+
assert @blogs_long
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_schema_for_keyspace
|
30
|
+
data = {
|
31
|
+
"StatusRelationships"=>{
|
32
|
+
"CompareSubcolumnsWith"=>"org.apache.cassandra.db.marshal.TimeUUIDType",
|
33
|
+
"CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
|
34
|
+
"Type"=>"Super"},
|
35
|
+
"StatusAudits"=>{
|
36
|
+
"CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
|
37
|
+
"Type"=>"Standard"},
|
38
|
+
"Statuses"=>{
|
39
|
+
"CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
|
40
|
+
"Type"=>"Standard"},
|
41
|
+
"UserRelationships"=>{
|
42
|
+
"CompareSubcolumnsWith"=>"org.apache.cassandra.db.marshal.TimeUUIDType",
|
43
|
+
"CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
|
44
|
+
"Type"=>"Super"},
|
45
|
+
"UserAudits"=>{
|
46
|
+
"CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
|
47
|
+
"Type"=>"Standard"},
|
48
|
+
"Users"=>{"CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type", "Type"=>"Standard"},
|
49
|
+
"TimelinishThings"=>
|
50
|
+
{"CompareWith"=>"org.apache.cassandra.db.marshal.BytesType", "Type"=>"Standard"}
|
51
|
+
}
|
52
|
+
stuff = @twitter.send(:schema_for_keyspace, 'Twitter')
|
53
|
+
data.keys.each do |k|
|
54
|
+
assert_equal data[k], stuff[k], k
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_sorting_row_keys
|
59
|
+
@twitter.insert(:Statuses, 'b', {:text => 'foo'})
|
60
|
+
@twitter.insert(:Statuses, 'a', {:text => 'foo'})
|
61
|
+
assert_equal ['a'], @twitter.get_range(:Statuses, :count => 1)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_inserting_array_for_indices
|
65
|
+
@twitter.insert(:TimelinishThings, 'a', ['1','2'])
|
66
|
+
row = @twitter.get(:TimelinishThings, 'a')
|
67
|
+
assert_equal({'1' => nil, '2' => nil}, row)
|
68
|
+
|
69
|
+
assert_raises(ArgumentError) {
|
70
|
+
@twitter.insert(:UserRelationships, 'a', ['u1','u2'])
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|