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,3 @@
1
+ class Cassandra
2
+ class ColumnFamily < CassandraThrift::CfDef ; end
3
+ end
@@ -0,0 +1,172 @@
1
+
2
+ class Cassandra
3
+ # A bunch of crap, mostly related to introspecting on column types
4
+ module Columns #:nodoc:
5
+ private
6
+
7
+ def is_super(column_family)
8
+ @is_super[column_family] ||= column_family_property(column_family, 'column_type') == "Super"
9
+ end
10
+
11
+ def column_name_class(column_family)
12
+ @column_name_class[column_family] ||= column_name_class_for_key(column_family, "comparator_type")
13
+ end
14
+
15
+ def sub_column_name_class(column_family)
16
+ @sub_column_name_class[column_family] ||= column_name_class_for_key(column_family, "subcomparator_type")
17
+ end
18
+
19
+ def column_name_maker(column_family)
20
+ @column_name_maker[column_family] ||=
21
+ begin
22
+ klass = column_name_class(column_family)
23
+ if klass == Composite
24
+ lambda {|name| klass.new_from_packed(name) }
25
+ else
26
+ lambda {|name| klass.new(name) }
27
+ end
28
+ end
29
+ end
30
+
31
+ def sub_column_name_maker(column_family)
32
+ @sub_column_name_maker[column_family] ||=
33
+ begin
34
+ klass = sub_column_name_class(column_family)
35
+ if klass == Composite
36
+ lambda {|name| klass.new_from_packed(name) }
37
+ else
38
+ lambda {|name| klass.new(name) }
39
+ end
40
+ end
41
+ end
42
+
43
+ def column_name_class_for_key(column_family, comparator_key)
44
+ property = column_family_property(column_family, comparator_key)
45
+ property =~ /[^(]*\.(.*?)$/
46
+ case $1
47
+ when "LongType" then Long
48
+ when "LexicalUUIDType", "TimeUUIDType" then SimpleUUID::UUID
49
+ when /^DynamicCompositeType\(/ then DynamicComposite
50
+ when /^CompositeType\(/ then Composite
51
+ else
52
+ String # UTF8, Ascii, Bytes, anything else
53
+ end
54
+ end
55
+
56
+ def column_family_property(column_family, key)
57
+ cfdef = schema.cf_defs.find {|cfdef| cfdef.name == column_family }
58
+ unless cfdef
59
+ raise AccessError, "Invalid column family \"#{column_family}\""
60
+ end
61
+ cfdef.send(key)
62
+ end
63
+
64
+ def multi_key_slices_to_hash(column_family, array, return_empty_rows = false)
65
+ ret = OrderedHash.new
66
+ array.each do |value|
67
+ next if return_empty_rows == false && value.columns.length == 0
68
+ ret[value.key] = columns_to_hash(column_family, value.columns)
69
+ end
70
+ ret
71
+ end
72
+
73
+ def multi_column_to_hash!(hash)
74
+ hash.each do |key, column_or_supercolumn|
75
+ hash[key] = (column_or_supercolumn.column.value if column_or_supercolumn.column)
76
+ end
77
+ end
78
+
79
+ def multi_columns_to_hash!(column_family, hash)
80
+ hash.each do |key, columns|
81
+ hash[key] = columns_to_hash(column_family, columns)
82
+ end
83
+ end
84
+
85
+ def multi_sub_columns_to_hash!(column_family, hash)
86
+ hash.each do |key, sub_columns|
87
+ hash[key] = sub_columns_to_hash(column_family, sub_columns)
88
+ end
89
+ end
90
+
91
+ def columns_to_hash(column_family, columns)
92
+ columns_to_hash_for_classes(columns, column_name_maker(column_family), sub_column_name_maker(column_family))
93
+ end
94
+
95
+ def sub_columns_to_hash(column_family, columns)
96
+ columns_to_hash_for_classes(columns, sub_column_name_maker(column_family))
97
+ end
98
+
99
+ def columns_to_hash_for_classes(columns, column_name_maker, sub_column_name_maker = nil)
100
+ hash = OrderedHash.new
101
+ Array(columns).each do |c|
102
+ c = c.super_column || c.column || c.counter_column || c.counter_super_column if c.is_a?(CassandraThrift::ColumnOrSuperColumn)
103
+ case c
104
+ when CassandraThrift::SuperColumn
105
+ hash.[]=(column_name_maker.call(c.name), columns_to_hash_for_classes(c.columns, sub_column_name_maker)) # Pop the class stack, and recurse
106
+ when CassandraThrift::Column
107
+ hash.[]=(column_name_maker.call(c.name), c.value, c.timestamp)
108
+ when CassandraThrift::CounterColumn
109
+ hash.[]=(column_name_maker.call(c.name), c.value, 0)
110
+ when CassandraThrift::CounterSuperColumn
111
+ hash.[]=(column_name_maker.call(c.name), columns_to_hash_for_classes(c.columns, sub_column_name_maker)) # Pop the class stack, and recurse
112
+ end
113
+ end
114
+ hash
115
+ end
116
+
117
+ def _standard_insert_mutation(column_family, column_name, value, timestamp, ttl = nil)
118
+ CassandraThrift::Mutation.new(
119
+ :column_or_supercolumn => CassandraThrift::ColumnOrSuperColumn.new(
120
+ :column => CassandraThrift::Column.new(
121
+ :name => column_name_class(column_family).new(column_name).to_s,
122
+ :value => value,
123
+ :timestamp => timestamp,
124
+ :ttl => ttl
125
+ )
126
+ )
127
+ )
128
+ end
129
+
130
+ def _super_insert_mutation(column_family, super_column_name, sub_columns, timestamp, ttl = nil)
131
+ CassandraThrift::Mutation.new(:column_or_supercolumn =>
132
+ CassandraThrift::ColumnOrSuperColumn.new(
133
+ :super_column => CassandraThrift::SuperColumn.new(
134
+ :name => column_name_class(column_family).new(super_column_name).to_s,
135
+ :columns => sub_columns.collect { |sub_column_name, sub_column_value|
136
+ CassandraThrift::Column.new(
137
+ :name => sub_column_name_class(column_family).new(sub_column_name).to_s,
138
+ :value => sub_column_value.to_s,
139
+ :timestamp => timestamp,
140
+ :ttl => ttl
141
+ )
142
+ }
143
+ )
144
+ )
145
+ )
146
+ end
147
+
148
+ # General info about a deletion object within a mutation
149
+ # timestamp - required. If this is the only param, it will cause deletion of the whole key at that TS
150
+ # supercolumn - opt. If passed, the deletes will only occur within that supercolumn (only subcolumns
151
+ # will be deleted). Otherwise the normal columns will be deleted.
152
+ # predicate - opt. Defines how to match the columns to delete. if supercolumn passed, the slice will
153
+ # be scoped to subcolumns of that supercolumn.
154
+
155
+ # Deletes a single column from the containing key/CF (and possibly supercolumn), at a given timestamp.
156
+ # Although mutations (as opposed to 'remove' calls) support deleting slices and lists of columns in one shot, this is not implemented here.
157
+ # The main reason being that the batch function takes removes, but removes don't have that capability...so we'd need to change the remove
158
+ # methods to use delete mutation calls...although that might have performance implications. We'll leave that refactoring for later.
159
+ def _delete_mutation(cf, column, subcolumn, timestamp, options={})
160
+ deletion_hash = {:timestamp => timestamp}
161
+ if is_super(cf)
162
+ deletion_hash[:super_column] = column if column
163
+ deletion_hash[:predicate] = CassandraThrift::SlicePredicate.new(:column_names => [subcolumn]) if subcolumn
164
+ else
165
+ deletion_hash[:predicate] = CassandraThrift::SlicePredicate.new(:column_names => [column]) if column
166
+ end
167
+ CassandraThrift::Mutation.new(
168
+ :deletion => CassandraThrift::Deletion.new(deletion_hash)
169
+ )
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,28 @@
1
+
2
+ class Cassandra
3
+ # Abstract base class for comparable numeric column name types
4
+ class Comparable
5
+ class TypeError < ::TypeError #:nodoc:
6
+ end
7
+
8
+ def <=>(other)
9
+ self.to_i <=> other.to_i
10
+ end
11
+
12
+ def hash
13
+ @bytes.hash
14
+ end
15
+
16
+ def eql?(other)
17
+ other.is_a?(Comparable) and @bytes == other.to_s
18
+ end
19
+
20
+ def ==(other)
21
+ other.respond_to?(:to_i) && self.to_i == other.to_i
22
+ end
23
+
24
+ def to_s
25
+ @bytes
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,140 @@
1
+ class Cassandra
2
+ class Composite
3
+ include ::Comparable
4
+ attr_reader :parts
5
+ attr_reader :column_slice
6
+
7
+ def initialize(*parts)
8
+ return if parts.empty?
9
+
10
+ options = {}
11
+ if parts.last.is_a?(Hash)
12
+ options = parts.pop
13
+ end
14
+ @column_slice = options[:slice]
15
+ raise ArgumentError if @column_slice != nil && ![:before, :after].include?(@column_slice)
16
+
17
+ if parts.length == 1 && parts[0].instance_of?(self.class)
18
+ @column_slice = parts[0].column_slice
19
+ @parts = parts[0].parts
20
+ elsif parts.length == 1 && parts[0].instance_of?(String) && @column_slice.nil? && try_packed_composite(parts[0])
21
+ @hash = parts[0].hash
22
+ else
23
+ @parts = parts
24
+ end
25
+ end
26
+
27
+ def self.new_from_packed(packed)
28
+ obj = new
29
+ obj.fast_unpack(packed)
30
+ return obj
31
+ end
32
+
33
+ def [](*args)
34
+ return @parts[*args]
35
+ end
36
+
37
+ def pack
38
+ packed = @parts.map do |part|
39
+ [part.length].pack('n') + part + "\x00"
40
+ end
41
+ if @column_slice
42
+ part = @parts[-1]
43
+ packed[-1] = [part.length].pack('n') + part + slice_end_of_component
44
+ end
45
+ return packed.join('')
46
+ end
47
+
48
+ def to_s
49
+ return pack
50
+ end
51
+
52
+ def <=>(other)
53
+ if !other.instance_of?(self.class)
54
+ return @parts.first <=> other
55
+ end
56
+ eoc = slice_end_of_component.unpack('c')[0]
57
+ other_eoc = other.slice_end_of_component.unpack('c')[0]
58
+ @parts.zip(other.parts).each do |a, b|
59
+ next if a == b
60
+ if a.nil? && b.nil?
61
+ return eoc <=> other_eoc
62
+ end
63
+
64
+ if a.nil?
65
+ return @column_slice == :after ? 1 : -1
66
+ end
67
+ if b.nil?
68
+ return other.column_slice == :after ? -1 : 1
69
+ end
70
+ return -1 if a < b
71
+ return 1 if a > b
72
+ end
73
+ return 0
74
+ end
75
+
76
+ def inspect
77
+ return "#<#{self.class}:#{@column_slice} #{@parts.inspect}>"
78
+ end
79
+
80
+ def slice_end_of_component
81
+ return "\x01" if @column_slice == :after
82
+ return "\xFF" if @column_slice == :before
83
+ return "\x00"
84
+ end
85
+
86
+ def fast_unpack(packed_string)
87
+ @hash = packed_string.hash
88
+
89
+ @parts = []
90
+ end_of_component = packed_string.slice(packed_string.length-1, 1)
91
+ while packed_string.length > 0
92
+ length = packed_string.unpack('n')[0]
93
+ @parts << packed_string.slice(2, length)
94
+
95
+ packed_string.slice!(0, length+3)
96
+ end
97
+
98
+ @column_slice = :after if end_of_component == "\x01"
99
+ @column_slice = :before if end_of_component == "\xFF"
100
+ end
101
+
102
+ private
103
+ def try_packed_composite(packed_string)
104
+ parts = []
105
+ end_of_component = nil
106
+ while packed_string.length > 0
107
+ length = packed_string.slice(0, 2).unpack('n')[0]
108
+ return false if length.nil? || length + 3 > packed_string.length
109
+
110
+ parts << packed_string.slice(2, length)
111
+ end_of_component = packed_string.slice(2 + length, 1)
112
+ if length + 3 != packed_string.length
113
+ return false if end_of_component != "\x00"
114
+ end
115
+
116
+ packed_string = packed_string.slice(3 + length, packed_string.length)
117
+ end
118
+
119
+ @column_slice = :after if end_of_component == "\x01"
120
+ @column_slice = :before if end_of_component == "\xFF"
121
+ @parts = parts
122
+
123
+ return true
124
+ end
125
+
126
+ def hash
127
+ return @hash ||= pack.hash
128
+ end
129
+
130
+ def eql?(other)
131
+ return to_s == other.to_s
132
+ end
133
+ end
134
+ end
135
+
136
+ begin
137
+ require "cassandra_native"
138
+ rescue LoadError
139
+ puts "Unable to load cassandra_native extension. Defaulting to pure Ruby libraries."
140
+ end
@@ -0,0 +1,11 @@
1
+
2
+ class Cassandra
3
+ # A helper module you can include in your own class. Makes it easier
4
+ # to work with Cassandra subclasses.
5
+ module Constants
6
+ include Cassandra::Consistency
7
+
8
+ Long = Cassandra::Long
9
+ OrderedHash = Cassandra::OrderedHash
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+
2
+ require 'pp'
3
+
4
+ class CassandraThrift::Cassandra::Client
5
+ def send_message(*args)
6
+ pp args
7
+ super
8
+ end
9
+ end
@@ -0,0 +1,96 @@
1
+ class Cassandra
2
+ class DynamicComposite < Composite
3
+ attr_accessor :types
4
+
5
+ def initialize(*parts)
6
+ return if parts.empty?
7
+
8
+ options = {}
9
+ if parts.last.is_a?(Hash)
10
+ options = parts.pop
11
+ end
12
+ @column_slice = options[:slice]
13
+ raise ArgumentError if @column_slice != nil && ![:before, :after].include?(@column_slice)
14
+
15
+ if parts.length == 1 && parts[0].instance_of?(self.class)
16
+ @column_slice = parts[0].column_slice
17
+ @parts = parts[0].parts
18
+ @types = parts[0].types
19
+ elsif parts.length == 1 && parts[0].instance_of?(String) && @column_slice.nil? && try_packed_composite(parts[0])
20
+ @hash = parts[0].hash
21
+ else
22
+ @types, @parts = parts.transpose
23
+ end
24
+ end
25
+
26
+ def pack
27
+ packed_parts = @parts.map do |part|
28
+ [part.length].pack('n') + part + "\x00"
29
+ end
30
+
31
+ if @column_slice
32
+ part = @parts[-1]
33
+ packed_parts[-1] = [part.length].pack('n') + part + slice_end_of_component
34
+ end
35
+
36
+ packed_types = @types.map do |type|
37
+ if type.length == 1
38
+ [0x8000 | type[0].ord].pack('n')
39
+ else
40
+ [type.length].pack('n') + type
41
+ end
42
+ end
43
+
44
+ return packed_types.zip(packed_parts).flatten.join('')
45
+ end
46
+
47
+ def fast_unpack(packed_string)
48
+ result = try_packed_composite(packed_string)
49
+ raise ArgumentError.new("Invalid DynamicComposite column") if !result
50
+ @hash = packed_string.hash
51
+ end
52
+
53
+ private
54
+ def try_packed_composite(packed_string)
55
+ types = []
56
+ parts = []
57
+ end_of_component = nil
58
+ offset = 0
59
+
60
+ read_bytes = proc do |length|
61
+ return false if offset + length > packed_string.length
62
+ out = packed_string.slice(offset, length)
63
+ offset += length
64
+ out
65
+ end
66
+
67
+ while offset < packed_string.length
68
+ header = read_bytes.call(2).unpack('n')[0]
69
+ is_alias = header & 0x8000 != 0
70
+ if is_alias
71
+ alias_char = (header & 0xFF).chr
72
+ types << alias_char
73
+ else
74
+ length = header
75
+ return false if length.nil? || length + offset > packed_string.length
76
+ type = read_bytes.call(length)
77
+ types << type
78
+ end
79
+ length = read_bytes.call(2).unpack('n')[0]
80
+ return false if length.nil? || length + offset > packed_string.length
81
+ parts << read_bytes.call(length)
82
+ end_of_component = read_bytes.call(1)
83
+ if offset < packed_string.length
84
+ return false if end_of_component != "\x00"
85
+ end
86
+ end
87
+ @column_slice = :after if end_of_component == "\x01"
88
+ @column_slice = :before if end_of_component == "\xFF"
89
+ @types = types
90
+ @parts = parts
91
+ @hash = packed_string.hash
92
+
93
+ return true
94
+ end
95
+ end
96
+ end