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,44 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # for production, you should probably set pattern to %c instead of %l.
18
+ # (%l is slower.)
19
+
20
+ # output messages into a rolling log file as well as stdout
21
+ log4j.rootLogger=INFO,stdout,R
22
+
23
+ # stdout
24
+ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
25
+ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
26
+ log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
27
+
28
+ # rolling log file
29
+ log4j.appender.R=org.apache.log4j.RollingFileAppender
30
+ log4j.appender.R.maxFileSize=20MB
31
+ log4j.appender.R.maxBackupIndex=50
32
+ log4j.appender.R.layout=org.apache.log4j.PatternLayout
33
+ log4j.appender.R.layout.ConversionPattern=%5p [%t] %d{ISO8601} %F (line %L) %m%n
34
+ # Edit the next line to point to your logs directory
35
+ log4j.appender.R.File=/var/log/cassandra/system.log
36
+
37
+ # Application logging options
38
+ #log4j.logger.org.apache.cassandra=DEBUG
39
+ #log4j.logger.org.apache.cassandra.db=DEBUG
40
+ #log4j.logger.org.apache.cassandra.service.StorageProxy=DEBUG
41
+
42
+ # Adding this to avoid thrift logging disconnect errors.
43
+ log4j.logger.org.apache.thrift.server.TNonblockingServer=ERROR
44
+
@@ -0,0 +1,72 @@
1
+ {"Twitter":{
2
+ "Users":{
3
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
4
+ "column_type":"Standard"},
5
+ "UserAudits":{
6
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
7
+ "column_type":"Standard"},
8
+ "UserCounters":{
9
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
10
+ "column_type":"Standard",
11
+ "default_validation_class":"CounterColumnType"},
12
+ "UserCounterAggregates":{
13
+ "subcomparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
14
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
15
+ "column_type":"Super",
16
+ "default_validation_class":"CounterColumnType"},
17
+ "UserRelationships":{
18
+ "subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
19
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
20
+ "column_type":"Super"},
21
+ "Usernames":{
22
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
23
+ "column_type":"Standard"},
24
+ "Statuses":{
25
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
26
+ "column_type":"Standard"},
27
+ "StatusAudits":{
28
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
29
+ "column_type":"Standard"},
30
+ "StatusRelationships":{
31
+ "subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
32
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
33
+ "column_type":"Super"},
34
+ "Indexes":{
35
+ "comparator_type":"org.apache.cassandra.db.marshal.UTF8Type",
36
+ "column_type":"Super"},
37
+ "TimelinishThings":{
38
+ "comparator_type":"org.apache.cassandra.db.marshal.BytesType",
39
+ "column_type":"Standard"}
40
+ },
41
+ "Multiblog":{
42
+ "Blogs":{
43
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
44
+ "column_type":"Standard"},
45
+ "Comments":{
46
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
47
+ "column_type":"Standard"}
48
+ },
49
+ "MultiblogLong":{
50
+ "Blogs":{
51
+ "comparator_type":"org.apache.cassandra.db.marshal.LongType",
52
+ "column_type":"Standard"},
53
+ "Comments":{
54
+ "comparator_type":"org.apache.cassandra.db.marshal.LongType",
55
+ "column_type":"Standard"}
56
+ },
57
+ "TypeConversions":{
58
+ "UUIDColumnConversion":{
59
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
60
+ "column_type":"Standard"},
61
+ "SuperUUID":{
62
+ "subcomparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
63
+ "comparator_type":"org.apache.cassandra.db.marshal.TimeUUIDType",
64
+ "column_type":"Super"},
65
+ "CompositeColumnConversion":{
66
+ "comparator_type":"org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.IntegerType,org.apache.cassandra.db.marshal.UTF8Type)",
67
+ "column_type":"Standard"},
68
+ "DynamicComposite":{
69
+ "comparator_type":"org.apache.cassandra.db.marshal.DynamicCompositeType(u=>org.apache.cassandra.db.marshal.UUIDType,t=>org.apache.cassandra.db.marshal.TimeUUIDType,s=>org.apache.cassandra.db.marshal.UTF8Type,b=>org.apache.cassandra.db.marshal.BytesType,a=>org.apache.cassandra.db.marshal.AsciiType,l=>org.apache.cassandra.db.marshal.LongType,x=>org.apache.cassandra.db.marshal.LexicalUUIDType,i=>org.apache.cassandra.db.marshal.IntegerType)",
70
+ "column_type":"Standard"}
71
+ }
72
+ }
@@ -0,0 +1,57 @@
1
+ create keyspace Twitter with
2
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
3
+ strategy_options = {replication_factor:1};
4
+ use Twitter;
5
+ create column family Users with comparator = 'UTF8Type';
6
+ create column family UserAudits with comparator = 'UTF8Type';
7
+ create column family UserCounters with comparator = 'UTF8Type' and
8
+ default_validation_class = CounterColumnType;
9
+ create column family UserCounterAggregates with column_type = 'Super'
10
+ and comparator = 'UTF8Type' and
11
+ subcomparator = 'UTF8Type' and
12
+ default_validation_class = CounterColumnType;
13
+ create column family UserRelationships with
14
+ comparator = 'UTF8Type' and
15
+ column_type = 'Super' and
16
+ subcomparator = 'TimeUUIDType';
17
+ create column family Usernames with comparator = 'UTF8Type';
18
+ create column family Statuses
19
+ with comparator = 'UTF8Type'
20
+ and column_metadata = [
21
+ {column_name: 'tags', validation_class: 'BytesType', index_type: 'KEYS'}
22
+ ];
23
+ create column family StatusAudits with comparator = 'UTF8Type';
24
+ create column family StatusRelationships with
25
+ comparator = 'UTF8Type' and
26
+ column_type = 'Super' and
27
+ subcomparator = 'TimeUUIDType';
28
+ create column family Indexes with
29
+ comparator = 'UTF8Type' and
30
+ column_type = 'Super';
31
+ create column family TimelinishThings with
32
+ comparator = 'BytesType';
33
+
34
+ create keyspace Multiblog with
35
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
36
+ strategy_options = {replication_factor:1};
37
+ use Multiblog;
38
+ create column family Blogs with comparator = 'TimeUUIDType';
39
+ create column family Comments with comparator = 'TimeUUIDType';
40
+
41
+
42
+ create keyspace MultiblogLong with
43
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
44
+ strategy_options = {replication_factor:1};
45
+ use MultiblogLong;
46
+ create column family Blogs with comparator = 'LongType';
47
+ create column family Comments with comparator = 'LongType';
48
+
49
+ create keyspace TypeConversions with
50
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
51
+ strategy_options = {replication_factor:1};
52
+ use TypeConversions;
53
+ create column family UUIDColumnConversion with comparator = TimeUUIDType;
54
+ create column family SuperUUID with comparator = TimeUUIDType and column_type = Super;
55
+ create column family CompositeColumnConversion with comparator = 'CompositeType(IntegerType, UTF8Type)';
56
+ create column family DynamicComposite with comparator ='DynamicCompositeType
57
+ (a=>AsciiType,b=>BytesType,i=>IntegerType,x=>LexicalUUIDType,l=>LongType,t=>TimeUUIDType,s=>UTF8Type,u=>UUIDType)';
@@ -0,0 +1,34 @@
1
+ #include <ruby.h>
2
+ #include <arpa/inet.h>
3
+
4
+ VALUE parts_ivar_id;
5
+
6
+ VALUE rb_cassandra_composite_fast_unpack(VALUE self, VALUE packed_string_value) {
7
+ int i = 0;
8
+ int index = 0;
9
+ int message_length = RSTRING_LEN(packed_string_value);
10
+ char *packed_string = (char *)RSTRING_PTR(packed_string_value);
11
+
12
+ VALUE parts = rb_ary_new();
13
+ while (index < message_length) {
14
+ uint16_t length = ntohs(((uint16_t *)(packed_string+index))[0]);
15
+ VALUE part = rb_str_new("", length);
16
+ for (i = 0; i < length; i++) {
17
+ ((char *)RSTRING_PTR(part))[i] = packed_string[index+2+i];
18
+ }
19
+ rb_ary_push(parts, part);
20
+ index += length + 3;
21
+ }
22
+
23
+ rb_ivar_set(self, parts_ivar_id, parts);
24
+
25
+ return Qnil;
26
+ }
27
+
28
+ void Init_cassandra_native(void) {
29
+ VALUE cassandra_module = rb_const_get(rb_cObject, rb_intern("Cassandra"));
30
+ VALUE cassandra_composite_class = rb_define_class_under(cassandra_module, "Composite", rb_cObject);
31
+ rb_define_method(cassandra_composite_class, "fast_unpack", rb_cassandra_composite_fast_unpack, 1);
32
+
33
+ parts_ivar_id = rb_intern("@parts");
34
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,9 @@
1
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/
2
+ File.open('Makefile', 'w'){|f| f.puts "all:\n\ninstall:\n" }
3
+ else
4
+ require 'mkmf'
5
+
6
+ $CFLAGS = "-g -O2 -Wall -Werror"
7
+
8
+ create_makefile 'cassandra_native'
9
+ end
@@ -0,0 +1,113 @@
1
+ class Cassandra
2
+ def self.DEFAULT_TRANSPORT_WRAPPER
3
+ Thrift::BufferedTransport
4
+ end
5
+
6
+ ##
7
+ # Issues a login attempt using the username and password specified.
8
+ #
9
+ # * username
10
+ # * password
11
+ #
12
+ def login!(username, password)
13
+ @auth_request = CassandraThrift::AuthenticationRequest.new
14
+ @auth_request.credentials = {'username' => username, 'password' => password}
15
+ client.login(@keyspace, @auth_request)
16
+ end
17
+
18
+ def inspect
19
+ "#<Cassandra:#{object_id}, @keyspace=#{keyspace.inspect}, @schema={#{
20
+ schema(false).map {|name, hash| ":#{name} => #{hash['type'].inspect}"}.join(', ')
21
+ }}, @servers=#{servers.inspect}>"
22
+ end
23
+
24
+ ##
25
+ # Returns an array of available keyspaces.
26
+ #
27
+ def keyspaces
28
+ @keyspaces ||= client.describe_keyspaces()
29
+ end
30
+
31
+ ##
32
+ # Remove all rows in the column family you request.
33
+ #
34
+ # * column_family
35
+ # * options
36
+ # * consitency
37
+ # * timestamp
38
+ #
39
+ def clear_column_family!(column_family, options = {})
40
+ each_key(column_family) do |key|
41
+ remove(column_family, key, options)
42
+ end
43
+ end
44
+ alias truncate! clear_column_family!
45
+
46
+ # Remove all rows in the keyspace. Supports options <tt>:consistency</tt> and
47
+ # <tt>:timestamp</tt>.
48
+ # FIXME May not currently delete all records without multiple calls. Waiting
49
+ # for ranged remove support in Cassandra.
50
+ def clear_keyspace!(options = {})
51
+ schema.keys.each { |column_family| clear_column_family!(column_family, options) }
52
+ end
53
+
54
+ # Open a batch operation and yield self. Inserts and deletes will be queued
55
+ # until the block closes, and then sent atomically to the server. Supports
56
+ # the <tt>:consistency</tt> option, which overrides the consistency set in
57
+ # the individual commands.
58
+ def batch(options = {})
59
+ _, _, _, options =
60
+ extract_and_validate_params(schema.keys.first, "", [options], WRITE_DEFAULTS)
61
+
62
+ @batch = []
63
+ yield(self)
64
+ compacted_map,seen_clevels = compact_mutations!
65
+ clevel = if options[:consistency] != nil # Override any clevel from individual mutations if
66
+ options[:consistency]
67
+ elsif seen_clevels.length > 1 # Cannot choose which CLevel to use if there are several ones
68
+ raise "Multiple consistency levels used in the batch, and no override...cannot pick one"
69
+ else # if no consistency override has been provided but all the clevels in the batch are the same: use that one
70
+ seen_clevels.first
71
+ end
72
+
73
+ _mutate(compacted_map,clevel)
74
+ ensure
75
+ @batch = nil
76
+ end
77
+
78
+ protected
79
+
80
+ def schema(load=true)
81
+ if !load && !@schema
82
+ []
83
+ else
84
+ @schema ||= client.describe_keyspace(@keyspace)
85
+ end
86
+ end
87
+
88
+ def client
89
+ reconnect! if @client.nil?
90
+ @client
91
+ end
92
+
93
+ def reconnect!
94
+ @servers = all_nodes
95
+ @client = new_client
96
+ end
97
+
98
+ def all_nodes
99
+ if @auto_discover_nodes
100
+ temp_client = new_client
101
+ begin
102
+ ips = ::JSON.parse(temp_client.get_string_property('token map')).values
103
+ port = @servers.first.split(':').last
104
+ ips.map{|ip| "#{ip}:#{port}" }
105
+ ensure
106
+ temp_client.disconnect!
107
+ end
108
+ else
109
+ @servers
110
+ end
111
+ end
112
+
113
+ end
@@ -0,0 +1,78 @@
1
+ class Cassandra
2
+ # A bunch of crap, mostly related to introspecting on column types
3
+ module Columns #:nodoc:
4
+ private
5
+
6
+ def is_super(column_family)
7
+ @is_super[column_family] ||= column_family_property(column_family, 'Type') == "Super"
8
+ end
9
+
10
+ def column_name_class(column_family)
11
+ @column_name_class[column_family] ||= column_name_class_for_key(column_family, "CompareWith")
12
+ end
13
+
14
+ def sub_column_name_class(column_family)
15
+ @sub_column_name_class[column_family] ||= column_name_class_for_key(column_family, "CompareSubcolumnsWith")
16
+ end
17
+
18
+ def column_family_property(column_family, key)
19
+ unless schema[column_family]
20
+ raise AccessError, "Invalid column family \"#{column_family}\""
21
+ end
22
+ schema[column_family][key]
23
+ end
24
+
25
+ def _standard_insert_mutation(column_family, column_name, value, timestamp, _=nil)
26
+ CassandraThrift::Mutation.new(
27
+ :column_or_supercolumn => CassandraThrift::ColumnOrSuperColumn.new(
28
+ :column => CassandraThrift::Column.new(
29
+ :name => column_name_class(column_family).new(column_name).to_s,
30
+ :value => value,
31
+ :timestamp => timestamp
32
+ )
33
+ )
34
+ )
35
+ end
36
+
37
+ def _super_insert_mutation(column_family, super_column_name, sub_columns, timestamp, _=nil)
38
+ CassandraThrift::Mutation.new(:column_or_supercolumn =>
39
+ CassandraThrift::ColumnOrSuperColumn.new(
40
+ :super_column => CassandraThrift::SuperColumn.new(
41
+ :name => column_name_class(column_family).new(super_column_name).to_s,
42
+ :columns => sub_columns.collect { |sub_column_name, sub_column_value|
43
+ CassandraThrift::Column.new(
44
+ :name => sub_column_name_class(column_family).new(sub_column_name).to_s,
45
+ :value => sub_column_value.to_s,
46
+ :timestamp => timestamp
47
+ )
48
+ }
49
+ )
50
+ )
51
+ )
52
+ end
53
+
54
+ # General info about a deletion object within a mutation
55
+ # timestamp - required. If this is the only param, it will cause deletion of the whole key at that TS
56
+ # supercolumn - opt. If passed, the deletes will only occur within that supercolumn (only subcolumns
57
+ # will be deleted). Otherwise the normal columns will be deleted.
58
+ # predicate - opt. Defines how to match the columns to delete. if supercolumn passed, the slice will
59
+ # be scoped to subcolumns of that supercolumn.
60
+
61
+ # Deletes a single column from the containing key/CF (and possibly supercolumn), at a given timestamp.
62
+ # Although mutations (as opposed to 'remove' calls) support deleting slices and lists of columns in one shot, this is not implemented here.
63
+ # 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
64
+ # methods to use delete mutation calls...although that might have performance implications. We'll leave that refactoring for later.
65
+ def _delete_mutation(cf, column, subcolumn, timestamp, options={})
66
+ deletion_hash = {:timestamp => timestamp}
67
+ if is_super(cf)
68
+ deletion_hash[:super_column] = column if column
69
+ deletion_hash[:predicate] = CassandraThrift::SlicePredicate.new(:column_names => [subcolumn]) if subcolumn
70
+ else
71
+ deletion_hash[:predicate] = CassandraThrift::SlicePredicate.new(:column_names => [column]) if column
72
+ end
73
+ CassandraThrift::Mutation.new(
74
+ :deletion => CassandraThrift::Deletion.new(deletion_hash)
75
+ )
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,91 @@
1
+
2
+ class Cassandra
3
+ # Inner methods for actually doing the Thrift calls
4
+ module Protocol #:nodoc:
5
+ private
6
+
7
+ def _mutate(mutation_map, consistency_level)
8
+ client.batch_mutate(@keyspace, mutation_map, consistency_level)
9
+ end
10
+
11
+ def _remove(key, column_path, timestamp, consistency_level)
12
+ client.remove(@keyspace, key, column_path, timestamp, consistency_level)
13
+ end
14
+
15
+ def _count_columns(column_family, key, super_column, start, stop, count, consistency)
16
+ client.get_count(@keyspace, key,
17
+ CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => super_column),
18
+ consistency
19
+ )
20
+ end
21
+
22
+ # FIXME: add support for start, stop, count functionality
23
+ def _get_columns(column_family, key, columns, sub_columns, consistency)
24
+ result = if is_super(column_family)
25
+ if sub_columns
26
+ columns_to_hash(column_family, client.get_slice(@keyspace, key,
27
+ CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => columns),
28
+ CassandraThrift::SlicePredicate.new(:column_names => sub_columns),
29
+ consistency))
30
+ else
31
+ columns_to_hash(column_family, client.get_slice(@keyspace, key,
32
+ CassandraThrift::ColumnParent.new(:column_family => column_family),
33
+ CassandraThrift::SlicePredicate.new(:column_names => columns),
34
+ consistency))
35
+ end
36
+ else
37
+ columns_to_hash(column_family, client.get_slice(@keyspace, key,
38
+ CassandraThrift::ColumnParent.new(:column_family => column_family),
39
+ CassandraThrift::SlicePredicate.new(:column_names => columns),
40
+ consistency))
41
+ end
42
+
43
+ klass = column_name_class(column_family)
44
+ (sub_columns || columns).map { |name| result[klass.new(name)] }
45
+ end
46
+
47
+ def _multiget(column_family, keys, column, sub_column, count, start, finish, reversed, consistency)
48
+ # Single values; count and range parameters have no effect
49
+ if is_super(column_family) and sub_column
50
+ column_path = CassandraThrift::ColumnPath.new(:column_family => column_family, :super_column => column, :column => sub_column)
51
+ multi_column_to_hash!(client.multiget(@keyspace, keys, column_path, consistency))
52
+ elsif !is_super(column_family) and column
53
+ column_path = CassandraThrift::ColumnPath.new(:column_family => column_family, :column => column)
54
+ multi_column_to_hash!(client.multiget(@keyspace, keys, column_path, consistency))
55
+
56
+ # Slices
57
+ else
58
+ predicate = CassandraThrift::SlicePredicate.new(:slice_range =>
59
+ CassandraThrift::SliceRange.new(
60
+ :reversed => reversed,
61
+ :count => count,
62
+ :start => start,
63
+ :finish => finish))
64
+
65
+ if is_super(column_family) and column
66
+ column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => column)
67
+ multi_sub_columns_to_hash!(column_family, client.multiget_slice(@keyspace, keys, column_parent, predicate, consistency))
68
+ else
69
+ column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family)
70
+ multi_columns_to_hash!(column_family, client.multiget_slice(@keyspace, keys, column_parent, predicate, consistency))
71
+ end
72
+ end
73
+ end
74
+
75
+ def _get_range(column_family, start_key, finish_key, key_count, columns, start, finish, count, consistency, reversed=false)
76
+ column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family)
77
+ predicate = if columns
78
+ CassandraThrift::SlicePredicate.new(:column_names => columns)
79
+ else
80
+ CassandraThrift::SlicePredicate.new(:slice_range =>
81
+ CassandraThrift::SliceRange.new(
82
+ :start => start,
83
+ :finish => finish,
84
+ :count => count,
85
+ :reversed => reversed))
86
+ end
87
+ range = CassandraThrift::KeyRange.new(:start_key => start_key, :end_key => finish_key, :count => key_count)
88
+ client.get_range_slices(@keyspace, column_parent, predicate, range, consistency)
89
+ end
90
+ end
91
+ end