sessionm-cassandra 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/CHANGELOG +135 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE +202 -0
  4. data/Manifest +94 -0
  5. data/README.md +373 -0
  6. data/Rakefile +195 -0
  7. data/bin/cassandra_helper +16 -0
  8. data/conf/0.6/cassandra.in.sh +47 -0
  9. data/conf/0.6/log4j.properties +38 -0
  10. data/conf/0.6/schema.json +57 -0
  11. data/conf/0.6/storage-conf.xml +352 -0
  12. data/conf/0.7/cassandra.in.sh +46 -0
  13. data/conf/0.7/cassandra.yaml +336 -0
  14. data/conf/0.7/log4j-server.properties +41 -0
  15. data/conf/0.7/schema.json +57 -0
  16. data/conf/0.7/schema.txt +45 -0
  17. data/conf/0.8/cassandra.in.sh +41 -0
  18. data/conf/0.8/cassandra.yaml +61 -0
  19. data/conf/0.8/log4j-server.properties +40 -0
  20. data/conf/0.8/schema.json +72 -0
  21. data/conf/0.8/schema.txt +57 -0
  22. data/conf/1.0/cassandra.in.sh +41 -0
  23. data/conf/1.0/cassandra.yaml +415 -0
  24. data/conf/1.0/log4j-server.properties +40 -0
  25. data/conf/1.0/schema.json +72 -0
  26. data/conf/1.0/schema.txt +57 -0
  27. data/conf/1.1/cassandra.in.sh +41 -0
  28. data/conf/1.1/cassandra.yaml +567 -0
  29. data/conf/1.1/log4j-server.properties +44 -0
  30. data/conf/1.1/schema.json +72 -0
  31. data/conf/1.1/schema.txt +57 -0
  32. data/ext/cassandra_native.c +34 -0
  33. data/ext/extconf.rb +9 -0
  34. data/lib/cassandra/0.6/cassandra.rb +113 -0
  35. data/lib/cassandra/0.6/columns.rb +78 -0
  36. data/lib/cassandra/0.6/protocol.rb +91 -0
  37. data/lib/cassandra/0.6.rb +7 -0
  38. data/lib/cassandra/0.7/cassandra.rb +2 -0
  39. data/lib/cassandra/0.7/columns.rb +4 -0
  40. data/lib/cassandra/0.7/protocol.rb +5 -0
  41. data/lib/cassandra/0.7.rb +7 -0
  42. data/lib/cassandra/0.8/cassandra.rb +51 -0
  43. data/lib/cassandra/0.8/columns.rb +28 -0
  44. data/lib/cassandra/0.8/protocol.rb +10 -0
  45. data/lib/cassandra/0.8.rb +7 -0
  46. data/lib/cassandra/1.0/cassandra.rb +1 -0
  47. data/lib/cassandra/1.0/columns.rb +1 -0
  48. data/lib/cassandra/1.0/protocol.rb +1 -0
  49. data/lib/cassandra/1.0.rb +7 -0
  50. data/lib/cassandra/1.1/cassandra.rb +1 -0
  51. data/lib/cassandra/1.1/columns.rb +1 -0
  52. data/lib/cassandra/1.1/protocol.rb +1 -0
  53. data/lib/cassandra/1.1.rb +7 -0
  54. data/lib/cassandra/array.rb +8 -0
  55. data/lib/cassandra/batch.rb +41 -0
  56. data/lib/cassandra/cassandra.rb +1088 -0
  57. data/lib/cassandra/column_family.rb +3 -0
  58. data/lib/cassandra/columns.rb +172 -0
  59. data/lib/cassandra/comparable.rb +28 -0
  60. data/lib/cassandra/composite.rb +140 -0
  61. data/lib/cassandra/constants.rb +11 -0
  62. data/lib/cassandra/debug.rb +9 -0
  63. data/lib/cassandra/dynamic_composite.rb +96 -0
  64. data/lib/cassandra/helpers.rb +41 -0
  65. data/lib/cassandra/keyspace.rb +3 -0
  66. data/lib/cassandra/long.rb +58 -0
  67. data/lib/cassandra/mock.rb +525 -0
  68. data/lib/cassandra/ordered_hash.rb +192 -0
  69. data/lib/cassandra/protocol.rb +137 -0
  70. data/lib/cassandra/time.rb +11 -0
  71. data/lib/cassandra.rb +41 -0
  72. data/sessionm-cassandra.gemspec +47 -0
  73. data/test/cassandra_client_test.rb +20 -0
  74. data/test/cassandra_mock_test.rb +128 -0
  75. data/test/cassandra_test.rb +1353 -0
  76. data/test/comparable_types_test.rb +45 -0
  77. data/test/composite_type_test.rb +64 -0
  78. data/test/eventmachine_test.rb +42 -0
  79. data/test/ordered_hash_test.rb +386 -0
  80. data/test/test_helper.rb +19 -0
  81. data/vendor/0.6/gen-rb/cassandra.rb +1481 -0
  82. data/vendor/0.6/gen-rb/cassandra_constants.rb +12 -0
  83. data/vendor/0.6/gen-rb/cassandra_types.rb +482 -0
  84. data/vendor/0.7/gen-rb/cassandra.rb +1936 -0
  85. data/vendor/0.7/gen-rb/cassandra_constants.rb +12 -0
  86. data/vendor/0.7/gen-rb/cassandra_types.rb +681 -0
  87. data/vendor/0.8/gen-rb/cassandra.rb +2215 -0
  88. data/vendor/0.8/gen-rb/cassandra_constants.rb +12 -0
  89. data/vendor/0.8/gen-rb/cassandra_types.rb +824 -0
  90. data/vendor/1.0/gen-rb/cassandra.rb +2215 -0
  91. data/vendor/1.0/gen-rb/cassandra_constants.rb +12 -0
  92. data/vendor/1.0/gen-rb/cassandra_types.rb +857 -0
  93. data/vendor/1.1/gen-rb/cassandra.rb +2571 -0
  94. data/vendor/1.1/gen-rb/cassandra_constants.rb +12 -0
  95. data/vendor/1.1/gen-rb/cassandra_types.rb +928 -0
  96. metadata +287 -0
@@ -0,0 +1,41 @@
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 #{caller[2].inspect}." 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 #{caller[1]}" if extras.any?
15
+ options.merge!(args.pop)
16
+ end
17
+
18
+ # Ranges
19
+ column, sub_column = args[0], args[1]
20
+ raise ArgumentError, "Invalid arguments: subcolumns specified for a non-supercolumn family" if sub_column && !is_super(column_family)
21
+ klass, sub_klass = column_name_class(column_family), sub_column_name_class(column_family)
22
+ range_class = column ? sub_klass : klass
23
+
24
+ [:start, :finish].each do |opt|
25
+ options[opt] = options[opt] ? range_class.new(options[opt]).to_s : ''
26
+ end
27
+
28
+ [column_family, s_map(column, klass), s_map(sub_column, sub_klass), options]
29
+ end
30
+
31
+ # Convert stuff to strings.
32
+ def s_map(el, klass)
33
+ case el
34
+ when Array then el.map { |i| s_map(i, klass) }
35
+ when NilClass then nil
36
+ else
37
+ klass.new(el).to_s
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ class Cassandra
2
+ class Keyspace < CassandraThrift::KsDef ; end
3
+ end
@@ -0,0 +1,58 @@
1
+
2
+ class Cassandra
3
+ # A temporally-ordered Long class for use in Cassandra column names
4
+ class Long < Comparable
5
+
6
+ # FIXME Should unify with or subclass Cassandra::UUID
7
+ def initialize(bytes = nil)
8
+ case bytes
9
+ when self.class # Long
10
+ @bytes = bytes.to_s
11
+ when String
12
+ case bytes.size
13
+ when 8 # Raw byte array
14
+ @bytes = bytes
15
+ when 18 # Human-readable UUID-like representation; inverse of #to_guid
16
+ elements = bytes.split("-")
17
+ raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (malformed UUID-like representation)" if elements.size != 3
18
+ @bytes = [elements.join].pack('H32')
19
+ else
20
+ raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (invalid bytecount)"
21
+ end
22
+ when Integer
23
+ raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (integer out of range)" if bytes < 0 or bytes > 2**64
24
+ @bytes = [bytes >> 32, bytes % 2**32].pack("NN")
25
+ when NilClass, Time
26
+ # Time.stamp is 52 bytes, so we have 12 bytes of entropy left over
27
+ int = ((bytes || Time).stamp << 12) + rand(2**12)
28
+ @bytes = [int >> 32, int % 2**32].pack("NN")
29
+ else
30
+ raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (unknown source class)"
31
+ end
32
+ end
33
+
34
+ def to_i
35
+ @to_i ||= begin
36
+ ints = @bytes.unpack("NN")
37
+ (ints[0] << 32) +
38
+ ints[1]
39
+ end
40
+ end
41
+
42
+ def to_guid
43
+ "%08x-%04x-%04x" % @bytes.unpack("Nnn")
44
+ end
45
+
46
+ def inspect
47
+ "<Cassandra::Long##{object_id} time: #{
48
+ Time.at((to_i >> 12) / 1_000_000).utc.inspect
49
+ }, usecs: #{
50
+ (to_i >> 12) % 1_000_000
51
+ }, jitter: #{
52
+ to_i % 2**12
53
+ }, guid: #{
54
+ to_guid
55
+ }>"
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,525 @@
1
+ class SimpleUUID::UUID
2
+ def >=(other)
3
+ (self <=> other) >= 0
4
+ end
5
+
6
+ def <=(other)
7
+ (self <=> other) <= 0
8
+ end
9
+ end
10
+
11
+ class Cassandra
12
+ class Mock
13
+ include ::Cassandra::Helpers
14
+ include ::Cassandra::Columns
15
+
16
+ attr_reader :keyspace
17
+
18
+ def initialize(keyspace, schema)
19
+ @is_super = {}
20
+ @keyspace = keyspace
21
+ @column_name_class = {}
22
+ @sub_column_name_class = {}
23
+ @column_name_maker = {}
24
+ @sub_column_name_maker = {}
25
+ @indexes = {}
26
+ @schema = schema[keyspace]
27
+ clear_keyspace!
28
+ end
29
+
30
+ def disconnect!
31
+ end
32
+
33
+ def clear_keyspace!
34
+ @data = {}
35
+ end
36
+
37
+ def clear_column_family!(column_family)
38
+ @data[column_family.to_sym] = OrderedHash.new
39
+ end
40
+
41
+ def default_write_consistency=(value)
42
+ WRITE_DEFAULTS[:consistency] = value
43
+ end
44
+
45
+ def default_read_consistency=(value)
46
+ READ_DEFAULTS[:consistency] = value
47
+ end
48
+
49
+ def insert(column_family, key, hash_or_array, options = {})
50
+ if @batch
51
+ @batch << [:insert, column_family, key, hash_or_array, options]
52
+ else
53
+ raise ArgumentError if key.nil?
54
+ if !is_super(column_family)
55
+ insert_standard(column_family, key, hash_or_array)
56
+ else
57
+ insert_super(column_family, key, hash_or_array)
58
+ end
59
+ end
60
+ end
61
+
62
+ def insert_standard(column_family, key, hash_or_array)
63
+ old = cf(column_family)[key] || OrderedHash.new
64
+ cf(column_family)[key] = merge_and_sort(old, hash_or_array)
65
+ end
66
+
67
+ def insert_super(column_family, key, hash)
68
+ raise ArgumentError unless hash.is_a?(Hash)
69
+ cf(column_family)[key] ||= OrderedHash.new
70
+
71
+ hash.keys.each do |sub_key|
72
+ old = cf(column_family)[key][sub_key] || OrderedHash.new
73
+ cf(column_family)[key][sub_key] = merge_and_sort(old, hash[sub_key])
74
+ end
75
+ end
76
+
77
+ def batch(options={})
78
+ @batch = Cassandra::Batch.new(self, options)
79
+ yield
80
+ flush_batch(options)
81
+ ensure
82
+ @batch = nil
83
+ end
84
+
85
+ def flush_batch(options)
86
+ b = @batch
87
+ @batch = nil
88
+ b.each do |mutation|
89
+ send(*mutation)
90
+ end
91
+ @batch = b
92
+ end
93
+
94
+ def get(column_family, key, *columns_and_options)
95
+ column_family, column, sub_column, options =
96
+ extract_and_validate_params_for_real(column_family, [key], columns_and_options, READ_DEFAULTS)
97
+ if !is_super(column_family)
98
+ get_standard(column_family, key, column, options)
99
+ else
100
+ get_super(column_family, key, column, sub_column, options)
101
+ end
102
+ end
103
+
104
+ def get_standard(column_family, key, column, options)
105
+ columns = cf(column_family)[key] || OrderedHash.new
106
+ row = columns_to_hash(column_family, columns)
107
+
108
+ if column
109
+ row[column]
110
+ else
111
+ row = apply_range(row, column_family, options[:start], options[:finish])
112
+ row = apply_count(row, options[:count], options[:reversed])
113
+ end
114
+ end
115
+
116
+ def get_super(column_family, key, column, sub_column, options)
117
+ columns = cf(column_family)[key] || OrderedHash.new
118
+ row = columns_to_hash(column_family, columns)
119
+
120
+ if column
121
+ if sub_column
122
+ if row[column] &&
123
+ row[column][sub_column]
124
+ row[column][sub_column]
125
+ else
126
+ nil
127
+ end
128
+ else
129
+ row = row[column] || OrderedHash.new
130
+ row = apply_range(row, column_family, options[:start], options[:finish], false)
131
+ row = apply_count(row, options[:count], options[:reversed])
132
+ end
133
+ else
134
+ row
135
+ end
136
+ end
137
+
138
+ def exists?(column_family, key, *columns_and_options)
139
+ column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, [key], columns_and_options, READ_DEFAULTS)
140
+ results = get(column_family, key, column, sub_column)
141
+
142
+ ![{}, nil].include?(results)
143
+ end
144
+
145
+ def multi_get(column_family, keys, *columns_and_options)
146
+ column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, keys, columns_and_options, READ_DEFAULTS)
147
+ keys.inject(OrderedHash.new) do |hash, key|
148
+ hash[key] = get(column_family, key)
149
+ hash
150
+ end
151
+ end
152
+
153
+ def remove(column_family, key, *columns_and_options)
154
+ column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, WRITE_DEFAULTS)
155
+ if @batch
156
+ @batch << [:remove, column_family, key, column, sub_column]
157
+ else
158
+ if column
159
+ if sub_column
160
+ cf(column_family)[key][column].delete(sub_column.to_s) if cf(column_family)[key][column]
161
+ else
162
+ cf(column_family)[key].delete(column.to_s) if cf(column_family)[key]
163
+ end
164
+ else
165
+ cf(column_family).delete(key)
166
+ end
167
+ end
168
+ end
169
+
170
+ def get_columns(column_family, key, *columns_and_options)
171
+ column_family, columns, sub_columns, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, READ_DEFAULTS)
172
+ d = get(column_family, key)
173
+
174
+ if sub_columns
175
+ sub_columns.collect do |sub_column|
176
+ d[columns][sub_column]
177
+ end
178
+ else
179
+ columns.collect do |column|
180
+ d[column]
181
+ end
182
+ end
183
+ end
184
+
185
+ def count_columns(column_family, key, *columns_and_options)
186
+ column_family, columns, sub_columns, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, READ_DEFAULTS)
187
+
188
+ get(column_family, key, columns, options).keys.length
189
+ end
190
+
191
+ def multi_get_columns(column_family, keys, columns)
192
+ keys.inject(OrderedHash.new) do |hash, key|
193
+ hash[key] = get_columns(column_family, key, columns)
194
+ hash
195
+ end
196
+ end
197
+
198
+ def multi_count_columns(column_family, keys)
199
+ keys.inject(OrderedHash.new) do |hash, key|
200
+ hash[key] = count_columns(column_family, key)
201
+ hash
202
+ end
203
+ end
204
+
205
+ def get_range(column_family, options = {}, &blk)
206
+ column_family, _, _, options = extract_and_validate_params_for_real(column_family, "", [options],
207
+ READ_DEFAULTS.merge(:start_key => nil,
208
+ :finish_key => nil,
209
+ :key_count => 100,
210
+ :columns => nil,
211
+ :reversed => false
212
+ )
213
+ )
214
+ res = _get_range(column_family,
215
+ options[:start_key],
216
+ options[:finish_key],
217
+ options[:key_count],
218
+ options[:columns],
219
+ options[:start],
220
+ options[:finish],
221
+ options[:count],
222
+ options[:consistency],
223
+ options[:reversed], &blk)
224
+
225
+ if blk.nil?
226
+ res
227
+ else
228
+ nil
229
+ end
230
+ end
231
+
232
+ def get_range_keys(column_family, options = {})
233
+ get_range(column_family,options.merge!(:columns => [])).keys
234
+ end
235
+
236
+ def count_range(column_family, options = {})
237
+ Hash[get_range(column_family, options).select{|k,v| v.length > 0}].keys.compact.length
238
+ end
239
+
240
+ def each_key(column_family, options = {})
241
+ each(column_family, options.merge!(:columns => [])) do |key, value|
242
+ yield key
243
+ end
244
+ end
245
+
246
+ def each(column_family, options = {})
247
+ batch_size = options.delete(:batch_size) || 100
248
+ count = options.delete(:key_count)
249
+ yielded_count = 0
250
+
251
+ options[:start_key] ||= ''
252
+ last_key = nil
253
+
254
+ while options[:start_key] != last_key && (count.nil? || count > yielded_count)
255
+ options[:start_key] = last_key
256
+ res = get_range(column_family, options.merge!(:start_key => last_key, :key_count => batch_size))
257
+ res.each do |key, columns|
258
+ next if options[:start_key] == key
259
+ next if yielded_count == count
260
+ yield key, columns
261
+ yielded_count += 1
262
+ last_key = key
263
+ end
264
+ end
265
+ end
266
+
267
+ def create_index(ks_name, cf_name, c_name, v_class)
268
+ if @indexes[ks_name] &&
269
+ @indexes[ks_name][cf_name] &&
270
+ @indexes[ks_name][cf_name][c_name]
271
+ nil
272
+
273
+ else
274
+ @indexes[ks_name] ||= {}
275
+ @indexes[ks_name][cf_name] ||= {}
276
+ @indexes[ks_name][cf_name][c_name] = true
277
+ end
278
+ end
279
+
280
+ def drop_index(ks_name, cf_name, c_name)
281
+ if @indexes[ks_name] &&
282
+ @indexes[ks_name][cf_name] &&
283
+ @indexes[ks_name][cf_name][c_name]
284
+
285
+ @indexes[ks_name][cf_name].delete(c_name)
286
+ else
287
+ nil
288
+ end
289
+ end
290
+
291
+ def create_index_expression(c_name, value, op)
292
+ {:column_name => c_name, :value => value, :comparison => op}
293
+ end
294
+ alias :create_idx_expr :create_index_expression
295
+
296
+ def create_index_clause(idx_expressions, start = "", count = 100)
297
+ {:start => start, :index_expressions => idx_expressions, :count => count, :type => :index_clause}
298
+ end
299
+ alias :create_idx_clause :create_index_clause
300
+
301
+ def get_indexed_slices(column_family, idx_clause, *columns_and_options)
302
+ column_family, columns, _, options =
303
+ extract_and_validate_params_for_real(column_family, [], columns_and_options,
304
+ READ_DEFAULTS.merge(:key_count => 100, :start_key => nil, :key_start => nil))
305
+
306
+ start_key = options[:start_key] || options[:key_start] || ""
307
+
308
+ unless [Hash, OrderedHash].include?(idx_clause.class) && idx_clause[:type] == :index_clause
309
+ idx_clause = create_index_clause(idx_clause, start_key, options[:key_count])
310
+ end
311
+
312
+ ret = OrderedHash.new
313
+ cf(column_family).each do |key, row|
314
+ next if idx_clause[:start] != '' && key < idx_clause[:start]
315
+ next if ret.length == idx_clause[:count]
316
+
317
+ matches = []
318
+ idx_clause[:index_expressions].each do |expr|
319
+ next if row[expr[:column_name]].nil?
320
+ next unless row[expr[:column_name]].send(expr[:comparison].to_sym, expr[:value])
321
+
322
+ matches << expr
323
+ end
324
+
325
+ ret[key] = row if matches.length == idx_clause[:index_expressions].length
326
+ end
327
+
328
+ ret
329
+ end
330
+
331
+ def add(column_family, key, value, *columns_and_options)
332
+ if @batch
333
+ @batch << [:add, column_family, key, value, *columns_and_options]
334
+ else
335
+ column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, WRITE_DEFAULTS)
336
+
337
+ if is_super(column_family)
338
+ cf(column_family)[key] ||= OrderedHash.new
339
+ cf(column_family)[key][column] ||= OrderedHash.new
340
+ cf(column_family)[key][column][sub_column] ||= 0
341
+ cf(column_family)[key][column][sub_column] += value
342
+ else
343
+ cf(column_family)[key] ||= OrderedHash.new
344
+ cf(column_family)[key][column] ||= 0
345
+ cf(column_family)[key][column] += value
346
+ end
347
+
348
+ nil
349
+ end
350
+ end
351
+
352
+ def column_families
353
+ cf_defs = {}
354
+ schema.each do |key, value|
355
+ cf_def = Cassandra::ColumnFamily.new
356
+
357
+ value.each do |property, property_value|
358
+ cf_def.send(:"#{property}=", property_value)
359
+ end
360
+
361
+ cf_defs[key] = cf_def
362
+ end
363
+
364
+ cf_defs
365
+ end
366
+
367
+ def schema(load=true)
368
+ @schema
369
+ end
370
+
371
+ def column_family_property(column_family, key)
372
+ schema[column_family.to_s][key]
373
+ end
374
+
375
+ def add_column_family(cf)
376
+ @schema[cf.name.to_s] ||= OrderedHash.new
377
+
378
+ cf.instance_variables.each do |var|
379
+ @schema[cf.name.to_s][var.slice(1..-1)] = cf.instance_variable_get(var)
380
+ end
381
+ end
382
+
383
+ def update_column_family(cf)
384
+ return false unless @schema.include?(cf.name.to_s)
385
+
386
+ cf.instance_variables.each do |var|
387
+ @schema[cf.name.to_s][var.slice(1..-1)] = cf.instance_variable_get(var)
388
+ end
389
+ end
390
+
391
+ def drop_column_family(column_family_name)
392
+ @schema.delete(column_family_name)
393
+ end
394
+
395
+ private
396
+
397
+ def schema_for_keyspace(keyspace)
398
+ @schema
399
+ end
400
+
401
+ def _get_range(column_family, start_key, finish_key, key_count, columns, start, finish, count, consistency, reversed, &blk)
402
+ ret = OrderedHash.new
403
+ start = to_compare_with_type(start, column_family)
404
+ finish = to_compare_with_type(finish, column_family)
405
+ cf(column_family).keys.sort.each do |key|
406
+ break if ret.keys.size >= key_count
407
+ if (start_key.nil? || key >= start_key) && (finish_key.nil? || key <= finish_key)
408
+ if columns
409
+ #ret[key] = columns.inject(OrderedHash.new){|hash, column_name| hash[column_name] = cf(column_family)[key][column_name]; hash;}
410
+ selected_hash = OrderedHash.new
411
+ cf(column_family)[key].each do |k, v|
412
+ selected_hash.[]=(k, v, cf(column_family)[key].timestamps[k]) if columns.include?(k)
413
+ end
414
+ ret[key] = columns_to_hash(column_family, selected_hash)
415
+ ret[key] = apply_count(ret[key], count, reversed)
416
+ blk.call(key,ret[key]) unless blk.nil?
417
+ else
418
+ #ret[key] = apply_range(cf(column_family)[key], column_family, start, finish, !is_super(column_family))
419
+ start, finish = finish, start if reversed
420
+ ret[key] = apply_range(columns_to_hash(column_family, cf(column_family)[key]), column_family, start, finish)
421
+ ret[key] = apply_count(ret[key], count, reversed)
422
+ blk.call(key,ret[key]) unless blk.nil?
423
+ end
424
+ end
425
+ end
426
+ ret
427
+ end
428
+
429
+ def extract_and_validate_params_for_real(column_family, keys, args, options)
430
+ column_family, columns, sub_column, options = extract_and_validate_params(column_family, keys, args, options)
431
+ options[:start] = nil if options[:start] == ''
432
+ options[:finish] = nil if options[:finish] == ''
433
+ [column_family, to_compare_with_types(columns, column_family), to_compare_with_types(sub_column, column_family, false), options]
434
+ end
435
+
436
+ def to_compare_with_types(column_names, column_family, standard=true)
437
+ if column_names.is_a?(Array)
438
+ column_names.collect do |name|
439
+ to_compare_with_type(name, column_family, standard)
440
+ end
441
+ else
442
+ to_compare_with_type(column_names, column_family, standard)
443
+ end
444
+ end
445
+
446
+ def to_compare_with_type(column_name, column_family, standard=true)
447
+ return column_name if column_name.nil?
448
+ klass = if standard
449
+ column_name_class(column_family)
450
+ else
451
+ sub_column_name_class(column_family)
452
+ end
453
+
454
+ klass.new(column_name)
455
+ end
456
+
457
+ def cf(column_family)
458
+ @data[column_family.to_sym] ||= OrderedHash.new
459
+ end
460
+
461
+ def merge_and_sort(old_stuff, new_stuff)
462
+ if new_stuff.is_a?(Array)
463
+ new_stuff = new_stuff.inject({}){|h,k| h[k] = nil; h }
464
+ end
465
+
466
+ new_stuff = new_stuff.to_a.inject({}){|h,k| h[k[0].to_s] = k[1]; h }
467
+
468
+ new_stuff.each { |k,v| old_stuff.[]=(k, v, (Time.now.to_f * 1000000).to_i) }
469
+ hash = OrderedHash.new
470
+ old_stuff.sort{ |a,b| a[0] <=> b[0] }.each do |k, v|
471
+ hash.[]=(k, v, old_stuff.timestamps[k])
472
+ end
473
+ hash
474
+ end
475
+
476
+ def columns_to_hash(column_family, columns)
477
+ column_class, sub_column_class = column_name_class(column_family), sub_column_name_class(column_family)
478
+ output = OrderedHash.new
479
+
480
+ columns.each do |column_name, value|
481
+ timestamp = columns.timestamps[column_name]
482
+ column = column_class.new(column_name)
483
+
484
+ if [Hash, OrderedHash].include?(value.class)
485
+ output[column] ||= OrderedHash.new
486
+ value.each do |sub_column, sub_column_value|
487
+ timestamp = value.timestamps[sub_column]
488
+ output[column].[]=(sub_column_class.new(sub_column), sub_column_value, timestamp)
489
+ end
490
+ else
491
+ output.[]=(column_class.new(column_name), value, timestamp)
492
+ end
493
+ end
494
+
495
+ output
496
+ end
497
+
498
+ def apply_count(row, count, reversed=false)
499
+ if count
500
+ keys = row.keys.sort
501
+ keys = keys.reverse if reversed
502
+ keys = keys[0...count]
503
+ keys.inject(OrderedHash.new) do |memo, key|
504
+ memo.[]=(key, row[key], row.timestamps[key])
505
+ memo
506
+ end
507
+ else
508
+ row
509
+ end
510
+ end
511
+
512
+ def apply_range(row, column_family, strt, fin, standard=true)
513
+ start = to_compare_with_type(strt, column_family, standard)
514
+ finish = to_compare_with_type(fin, column_family, standard)
515
+ ret = OrderedHash.new
516
+ row.keys.each do |key|
517
+ if (start.nil? || key >= start) && (finish.nil? || key <= finish)
518
+ ret.[]=(key, row[key], row.timestamps[key])
519
+ end
520
+ end
521
+ ret
522
+ end
523
+
524
+ end
525
+ end