cassandra 0.7.4 → 0.7.5

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.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