cassandra 0.7.4 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.7.5 Another packaging error.
2
+
1
3
  v0.7.4 Fix thrift_client dependency
2
4
 
3
5
  v0.7.3 New Cassandra::Mock - a pure ruby mock of cassanra; bugfixes.
data/Manifest CHANGED
@@ -14,10 +14,13 @@ lib/cassandra/columns.rb
14
14
  lib/cassandra/comparable.rb
15
15
  lib/cassandra/constants.rb
16
16
  lib/cassandra/debug.rb
17
+ lib/cassandra/helpers.rb
17
18
  lib/cassandra/long.rb
19
+ lib/cassandra/mock.rb
18
20
  lib/cassandra/ordered_hash.rb
19
21
  lib/cassandra/protocol.rb
20
22
  lib/cassandra/time.rb
23
+ test/cassandra_mock_test.rb
21
24
  test/cassandra_test.rb
22
25
  test/comparable_types_test.rb
23
26
  test/ordered_hash_test.rb
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{cassandra}
5
- s.version = "0.7.4"
5
+ s.version = "0.7.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0.8") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Evan Weaver, Ryan King"]
@@ -12,8 +12,8 @@ Gem::Specification.new do |s|
12
12
  s.description = %q{A Ruby client for the Cassandra distributed database.}
13
13
  s.email = %q{}
14
14
  s.executables = ["cassandra_helper"]
15
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb"]
16
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.rdoc", "Rakefile", "bin/cassandra_helper", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb", "vendor/gen-rb/cassandra.rb", "vendor/gen-rb/cassandra_constants.rb", "vendor/gen-rb/cassandra_types.rb", "cassandra.gemspec", "test/cassandra_mock_test.rb"]
15
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.rdoc", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb"]
16
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.rdoc", "Rakefile", "bin/cassandra_helper", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb", "vendor/gen-rb/cassandra.rb", "vendor/gen-rb/cassandra_constants.rb", "vendor/gen-rb/cassandra_types.rb", "cassandra.gemspec"]
17
17
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/cassandra/}
18
18
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cassandra", "--main", "README.rdoc"]
19
19
  s.require_paths = ["lib"]
@@ -2,6 +2,7 @@ require 'rubygems'
2
2
  require 'thrift_client'
3
3
  require 'json'
4
4
  require 'simple_uuid'
5
+ include SimpleUUID
5
6
  here = File.expand_path(File.dirname(__FILE__))
6
7
 
7
8
  $LOAD_PATH << "#{here}/../vendor/gen-rb"
@@ -0,0 +1,38 @@
1
+ class Cassandra
2
+ module Helpers
3
+ def extract_and_validate_params(column_family, keys, args, options)
4
+ options = options.dup
5
+ column_family = column_family.to_s
6
+ # Keys
7
+ [keys].flatten.each do |key|
8
+ raise ArgumentError, "Key #{key.inspect} must be a String for #{calling_method}" unless key.is_a?(String)
9
+ end
10
+
11
+ # Options
12
+ if args.last.is_a?(Hash)
13
+ extras = args.last.keys - options.keys
14
+ raise ArgumentError, "Invalid options #{extras.inspect[1..-2]} for #{calling_method}" if extras.any?
15
+ options.merge!(args.pop)
16
+ end
17
+
18
+ # Ranges
19
+ column, sub_column = args[0], args[1]
20
+ klass, sub_klass = column_name_class(column_family), sub_column_name_class(column_family)
21
+ range_class = column ? sub_klass : klass
22
+ options[:start] = options[:start] ? range_class.new(options[:start]).to_s : ""
23
+ options[:finish] = options[:finish] ? range_class.new(options[:finish]).to_s : ""
24
+
25
+ [column_family, s_map(column, klass), s_map(sub_column, sub_klass), options]
26
+ end
27
+
28
+ # Convert stuff to strings.
29
+ def s_map(el, klass)
30
+ case el
31
+ when Array then el.map { |i| s_map(i, klass) }
32
+ when NilClass then nil
33
+ else
34
+ klass.new(el).to_s
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,300 @@
1
+ require 'nokogiri'
2
+
3
+ class 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, servers=nil, options={})
19
+ @keyspace = keyspace
20
+ @column_name_class = {}
21
+ @sub_column_name_class = {}
22
+ @storage_xml = options[:storage_xml]
23
+ end
24
+
25
+ def clear_keyspace!
26
+ @data = {}
27
+ end
28
+
29
+ def clear_column_family!(column_family)
30
+ @data[column_family.to_sym] = OrderedHash.new
31
+ end
32
+
33
+ def insert(column_family, key, hash, options = {})
34
+ if @batch
35
+ @batch << [:insert, column_family, key, hash, options]
36
+ else
37
+ raise ArgumentError if key.nil?
38
+ if column_family_type(column_family) == 'Standard'
39
+ insert_standard(column_family, key, hash)
40
+ else
41
+ insert_super(column_family, key, hash)
42
+ end
43
+ end
44
+ end
45
+
46
+ def insert_standard(column_family, key, hash)
47
+ if cf(column_family)[key]
48
+ cf(column_family)[key] = merge_and_sort(cf(column_family)[key], hash)
49
+ else
50
+ cf(column_family)[key] = OrderedHash[hash.sort{|a,b| a[0] <=> b[0]}]
51
+ end
52
+ end
53
+
54
+ def insert_super(column_family, key, hash)
55
+ cf(column_family)[key] ||= OrderedHash.new
56
+ hash.keys.each do |sub_key|
57
+ if cf(column_family)[key][sub_key]
58
+ cf(column_family)[key][sub_key] = merge_and_sort(cf(column_family)[key][sub_key], hash[sub_key])
59
+ else
60
+ cf(column_family)[key][sub_key] = OrderedHash[hash[sub_key].sort{|a,b| a[0] <=> b[0]}]
61
+ end
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
+ apply_count(row, options[:count], options[:reversed])
93
+ end
94
+ end
95
+
96
+ def get_super(column_family, key, column, sub_column, options)
97
+ if column
98
+ if sub_column
99
+ if cf(column_family)[key] &&
100
+ cf(column_family)[key][column] &&
101
+ cf(column_family)[key][column][sub_column]
102
+ cf(column_family)[key][column][sub_column]
103
+ else
104
+ nil
105
+ end
106
+ else
107
+ row = cf(column_family)[key] && cf(column_family)[key][column] ?
108
+ cf(column_family)[key][column] :
109
+ OrderedHash.new
110
+ if options[:start] || options[:finish]
111
+ start = to_compare_with_type(options[:start], column_family, false)
112
+ finish = to_compare_with_type(options[:finish], column_family, false)
113
+ ret = OrderedHash.new
114
+ row.keys.each do |key|
115
+ if (start.nil? || key >= start) && (finish.nil? || key <= finish)
116
+ ret[key] = row[key]
117
+ end
118
+ end
119
+ row = ret
120
+ end
121
+ apply_count(row, options[:count], options[:reversed])
122
+ end
123
+ elsif cf(column_family)[key]
124
+ cf(column_family)[key]
125
+ else
126
+ OrderedHash.new
127
+ end
128
+ end
129
+
130
+ def exists?(column_family, key, column=nil)
131
+ !!get(column_family, key, column)
132
+ end
133
+
134
+ def multi_get(column_family, keys)
135
+ keys.inject(OrderedHash.new) do |hash, key|
136
+ hash[key] = get(column_family, key)
137
+ hash
138
+ end
139
+ end
140
+
141
+ def remove(column_family, key, column=nil, sub_column=nil)
142
+ if @batch
143
+ @batch << [:remove, column_family, key, column]
144
+ else
145
+ if column
146
+ if sub_column
147
+ cf(column_family)[key][column].delete(sub_column)
148
+ else
149
+ cf(column_family)[key].delete(column)
150
+ end
151
+ else
152
+ cf(column_family).delete(key)
153
+ end
154
+ end
155
+ end
156
+
157
+ def get_columns(column_family, key, columns)
158
+ d = get(column_family, key)
159
+ columns.collect do |column|
160
+ d[column]
161
+ end
162
+ end
163
+
164
+ def count_columns(column_family, key, column=nil)
165
+ get(column_family, key, column).keys.length
166
+ end
167
+
168
+ def multi_get_columns(column_family, keys, columns)
169
+ keys.inject(OrderedHash.new) do |hash, key|
170
+ hash[key] = get_columns(column_family, key, columns)
171
+ hash
172
+ end
173
+ end
174
+
175
+ def multi_count_columns(column_family, keys)
176
+ keys.inject(OrderedHash.new) do |hash, key|
177
+ hash[key] = count_columns(column_family, key)
178
+ hash
179
+ end
180
+ end
181
+
182
+ def get_range(column_family, options = {})
183
+ column_family, _, _, options =
184
+ extract_and_validate_params_for_real(column_family, "", [options], READ_DEFAULTS)
185
+ _get_range(column_family, options[:start], options[:finish], options[:count]).keys
186
+ end
187
+
188
+ def count_range(column_family, options={})
189
+ count = 0
190
+ l = []
191
+ start_key = ''
192
+ while (l = get_range(column_family, options.merge(:count => 1000, :start => start_key))).size > 0
193
+ count += l.size
194
+ start_key = l.last.succ
195
+ end
196
+ count
197
+ end
198
+
199
+ def schema(load=true)
200
+ if !load && !@schema
201
+ []
202
+ else
203
+ @schema ||= schema_for_keyspace(@keyspace)
204
+ end
205
+ end
206
+
207
+ private
208
+
209
+ def _get_range(column_family, start, finish, count)
210
+ ret = OrderedHash.new
211
+ start = to_compare_with_type(start, column_family)
212
+ finish = to_compare_with_type(finish, column_family)
213
+ cf(column_family).keys.sort.each do |key|
214
+ break if ret.keys.size >= count
215
+ if (start.nil? || key >= start) && (finish.nil? || key <= finish)
216
+ ret[key] = cf(column_family)[key]
217
+ end
218
+ end
219
+ ret
220
+ end
221
+
222
+ def schema_for_keyspace(keyspace)
223
+ doc = read_storage_xml
224
+ ret = {}
225
+ doc.css("Keyspaces Keyspace[@Name='#{keyspace}']").css('ColumnFamily').each do |cf|
226
+ ret[cf['Name']] = {}
227
+ if cf['CompareSubcolumnsWith']
228
+ ret[cf['Name']]['CompareSubcolumnsWith'] = 'org.apache.cassandra.db.marshal.' + cf['CompareSubcolumnsWith']
229
+ end
230
+ if cf['CompareWith']
231
+ ret[cf['Name']]['CompareWith'] = 'org.apache.cassandra.db.marshal.' + cf['CompareWith']
232
+ end
233
+ if cf['ColumnType']
234
+ ret[cf['Name']]['Type'] = 'Super'
235
+ else
236
+ ret[cf['Name']]['Type'] = 'Standard'
237
+ end
238
+ end
239
+ ret
240
+ end
241
+
242
+ def read_storage_xml
243
+ @doc ||= Nokogiri::XML(open(@storage_xml))
244
+ end
245
+
246
+ def extract_and_validate_params_for_real(column_family, keys, args, options)
247
+ column_family, column, sub_column, options = extract_and_validate_params(column_family, keys, args, options)
248
+ options[:start] = nil if options[:start] == ''
249
+ options[:finish] = nil if options[:finish] == ''
250
+ [column_family, to_compare_with_type(column, column_family), to_compare_with_type(sub_column, column_family, false), options]
251
+ end
252
+
253
+ def to_compare_with_type(column_name, column_family, standard=true)
254
+ return column_name if column_name.nil?
255
+ klass = if standard
256
+ schema[column_family.to_s]["CompareWith"]
257
+ else
258
+ schema[column_family.to_s]["CompareSubcolumnsWith"]
259
+ end
260
+
261
+ case klass
262
+ when "org.apache.cassandra.db.marshal.UTF8Type"
263
+ column_name
264
+ when "org.apache.cassandra.db.marshal.TimeUUIDType"
265
+ UUID.new(column_name)
266
+ when "org.apache.cassandra.db.marshal.LongType"
267
+ Long.new(column_name)
268
+ else
269
+ p klass
270
+ raise
271
+ end
272
+ end
273
+
274
+ def column_family_type(column_family)
275
+ schema[column_family.to_s]['Type']
276
+ end
277
+
278
+ def cf(column_family)
279
+ @data[column_family.to_sym] ||= OrderedHash.new
280
+ end
281
+
282
+ def merge_and_sort(old_stuff, new_stuff)
283
+ OrderedHash[old_stuff.merge(new_stuff).sort{|a,b| a[0] <=> b[0]}]
284
+ end
285
+
286
+ def apply_count(row, count, reversed=false)
287
+ if count
288
+ keys = row.keys.sort
289
+ keys = keys.reverse if reversed
290
+ keys = keys[0...count]
291
+ keys.inject(OrderedHash.new) do |memo, key|
292
+ memo[key] = row[key]
293
+ memo
294
+ end
295
+ else
296
+ row
297
+ end
298
+ end
299
+ end
300
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.7.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Weaver, Ryan King
@@ -97,7 +97,9 @@ extra_rdoc_files:
97
97
  - lib/cassandra/comparable.rb
98
98
  - lib/cassandra/constants.rb
99
99
  - lib/cassandra/debug.rb
100
+ - lib/cassandra/helpers.rb
100
101
  - lib/cassandra/long.rb
102
+ - lib/cassandra/mock.rb
101
103
  - lib/cassandra/ordered_hash.rb
102
104
  - lib/cassandra/protocol.rb
103
105
  - lib/cassandra/time.rb
@@ -118,10 +120,13 @@ files:
118
120
  - lib/cassandra/comparable.rb
119
121
  - lib/cassandra/constants.rb
120
122
  - lib/cassandra/debug.rb
123
+ - lib/cassandra/helpers.rb
121
124
  - lib/cassandra/long.rb
125
+ - lib/cassandra/mock.rb
122
126
  - lib/cassandra/ordered_hash.rb
123
127
  - lib/cassandra/protocol.rb
124
128
  - lib/cassandra/time.rb
129
+ - test/cassandra_mock_test.rb
125
130
  - test/cassandra_test.rb
126
131
  - test/comparable_types_test.rb
127
132
  - test/ordered_hash_test.rb
metadata.gz.sig CHANGED
Binary file