mcmire-cassandra 0.12.2 → 0.12.3

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.
@@ -0,0 +1,40 @@
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=data/logs/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
@@ -0,0 +1,69 @@
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
+ }
69
+ }
@@ -0,0 +1,51 @@
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 with comparator = 'UTF8Type';
19
+ create column family StatusAudits with comparator = 'UTF8Type';
20
+ create column family StatusRelationships with
21
+ comparator = 'UTF8Type' and
22
+ column_type = 'Super' and
23
+ subcomparator = 'TimeUUIDType';
24
+ create column family Indexes with
25
+ comparator = 'UTF8Type' and
26
+ column_type = 'Super';
27
+ create column family TimelinishThings with
28
+ comparator = 'BytesType';
29
+
30
+ create keyspace Multiblog with
31
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
32
+ strategy_options = {replication_factor:1};
33
+ use Multiblog;
34
+ create column family Blogs with comparator = 'TimeUUIDType';
35
+ create column family Comments with comparator = 'TimeUUIDType';
36
+
37
+
38
+ create keyspace MultiblogLong with
39
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
40
+ strategy_options = {replication_factor:1};
41
+ use MultiblogLong;
42
+ create column family Blogs with comparator = 'LongType';
43
+ create column family Comments with comparator = 'LongType';
44
+
45
+ create keyspace TypeConversions with
46
+ placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' AND
47
+ strategy_options = {replication_factor:1};
48
+ use TypeConversions;
49
+ create column family UUIDColumnConversion with comparator = TimeUUIDType;
50
+ create column family SuperUUID with comparator = TimeUUIDType and column_type = Super;
51
+ create column family CompositeColumnConversion with comparator = 'CompositeType(IntegerType, UTF8Type)';
@@ -23,6 +23,7 @@ require 'cassandra/array'
23
23
  require 'cassandra/time'
24
24
  require 'cassandra/comparable'
25
25
  require 'cassandra/long'
26
+ require 'cassandra/composite'
26
27
  require 'cassandra/ordered_hash'
27
28
  require 'cassandra/columns'
28
29
  require 'cassandra/protocol'
@@ -0,0 +1,7 @@
1
+ class Cassandra
2
+ def self.VERSION
3
+ "1.0"
4
+ end
5
+ end
6
+
7
+ require "#{File.expand_path(File.dirname(__FILE__))}/../cassandra"
@@ -0,0 +1,10 @@
1
+ class Cassandra
2
+
3
+ ## Counters
4
+
5
+ # Add a value to the counter in cf:key:super column:column
6
+ def add(column_family, key, value, *columns_and_options)
7
+ column_family, column, sub_column, options = extract_and_validate_params(column_family, key, columns_and_options, WRITE_DEFAULTS)
8
+ _add(column_family, key, column, sub_column, value, options[:consistency])
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ class Cassandra
2
+ module Columns #:nodoc:
3
+ end
4
+ end
@@ -0,0 +1,23 @@
1
+ require "#{File.expand_path(File.dirname(__FILE__))}/../0.7/protocol"
2
+
3
+ class Cassandra
4
+ # Inner methods for actually doing the Thrift calls
5
+ module Protocol #:nodoc:
6
+ private
7
+
8
+ def _remove_counter(key, column_path, consistency_level)
9
+ client.remove_counter(key, column_path, consistency_level)
10
+ end
11
+
12
+ def _add(column_family, key, column, sub_column, value, consistency)
13
+ if is_super(column_family)
14
+ column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family, :super_column => column)
15
+ counter_column = CassandraThrift::CounterColumn.new(:name => sub_column, :value => value)
16
+ else
17
+ column_parent = CassandraThrift::ColumnParent.new(:column_family => column_family)
18
+ counter_column = CassandraThrift::CounterColumn.new(:name => column, :value => value)
19
+ end
20
+ client.add(key, column_parent, counter_column, consistency)
21
+ end
22
+ end
23
+ end
@@ -18,10 +18,11 @@ class Cassandra
18
18
 
19
19
  def column_name_class_for_key(column_family, comparator_key)
20
20
  property = column_family_property(column_family, comparator_key)
21
- property =~ /.*\.(.*?)$/
21
+ property =~ /[^(]*\.(.*?)$/
22
22
  case $1
23
23
  when "LongType" then Long
24
24
  when "LexicalUUIDType", "TimeUUIDType" then SimpleUUID::UUID
25
+ when /^CompositeType\(/ then Composite
25
26
  else
26
27
  String # UTF8, Ascii, Bytes, anything else
27
28
  end
@@ -0,0 +1,118 @@
1
+
2
+ class Cassandra
3
+ class Composite
4
+ include ::Comparable
5
+ attr_reader :parts
6
+ attr_reader :column_slice
7
+
8
+ def initialize(*parts)
9
+ options = {}
10
+ if parts.last.is_a?(Hash)
11
+ options = parts.pop
12
+ end
13
+ @column_slice = options[:slice]
14
+ raise ArgumentError if @column_slice != nil && ![:before, :after].include?(@column_slice)
15
+
16
+ if parts.length == 1 && parts[0].instance_of?(self.class)
17
+ @column_slice = parts[0].column_slice
18
+ @parts = parts[0].parts
19
+ elsif parts.length == 1 && parts[0].instance_of?(String) && @column_slice.nil? && valid_packed_composite?(parts[0])
20
+ unpack(parts[0])
21
+ else
22
+ @parts = parts
23
+ end
24
+ end
25
+
26
+ def [](*args)
27
+ return @parts[*args]
28
+ end
29
+
30
+ def pack
31
+ packed = @parts.map do |part|
32
+ [part.length].pack('n') + part + "\x00"
33
+ end
34
+ if @column_slice
35
+ part = @parts[-1]
36
+ packed[-1] = [part.length].pack('n') + part + slice_end_of_component
37
+ end
38
+ return packed.join('')
39
+ end
40
+
41
+ def to_s
42
+ return pack
43
+ end
44
+
45
+ def <=>(other)
46
+ if !other.instance_of?(self.class)
47
+ return @parts.first <=> other
48
+ end
49
+ eoc = slice_end_of_component.unpack('c')[0]
50
+ other_eoc = other.slice_end_of_component.unpack('c')[0]
51
+ @parts.zip(other.parts).each do |a, b|
52
+ next if a == b
53
+ if a.nil? && b.nil?
54
+ return eoc <=> other_eoc
55
+ end
56
+
57
+ if a.nil?
58
+ return @column_slice == :after ? 1 : -1
59
+ end
60
+ if b.nil?
61
+ return other.column_slice == :after ? -1 : 1
62
+ end
63
+ return -1 if a < b
64
+ return 1 if a > b
65
+ end
66
+ return 0
67
+ end
68
+
69
+ def inspect
70
+ return "#<Composite:#{@column_slice} #{@parts.inspect}>"
71
+ end
72
+
73
+ def slice_end_of_component
74
+ return "\x01" if @column_slice == :after
75
+ return "\xFF" if @column_slice == :before
76
+ return "\x00"
77
+ end
78
+
79
+ private
80
+ def unpack(packed_string)
81
+ parts = []
82
+ end_of_component = nil
83
+ while packed_string.length > 0
84
+ length = packed_string.slice(0, 2).unpack('n')[0]
85
+ parts << packed_string.slice(2, length)
86
+ end_of_component = packed_string.slice(2 + length, 1)
87
+
88
+ packed_string = packed_string.slice(3 + length, packed_string.length)
89
+ end
90
+ @column_slice = :after if end_of_component == "\x01"
91
+ @column_slice = :before if end_of_component == "\xFF"
92
+ @parts = parts
93
+ end
94
+
95
+ def valid_packed_composite?(packed_string)
96
+ while packed_string.length > 0
97
+ length = packed_string.slice(0, 2).unpack('n')[0]
98
+ return false if length.nil? || length + 3 > packed_string.length
99
+
100
+ end_of_component = packed_string.slice(2 + length, 1)
101
+ if length + 3 != packed_string.length
102
+ return false if end_of_component != "\x00"
103
+ end
104
+
105
+ packed_string = packed_string.slice(3 + length, packed_string.length)
106
+ end
107
+ return true
108
+ end
109
+
110
+ def hash
111
+ return to_s.hash
112
+ end
113
+
114
+ def eql?(other)
115
+ return to_s == other.to_s
116
+ end
117
+ end
118
+ end
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "mcmire-cassandra"
5
- s.version = "0.12.2"
5
+ s.version = "0.12.3"
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"]
9
- s.date = "2012-03-29"
9
+ s.date = "2012-05-08"
10
10
  s.description = "A Ruby client for the Cassandra distributed database."
11
11
  s.email = ""
12
12
  s.executables = ["cassandra_helper"]
13
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb"]
14
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.md", "Rakefile", "bin/cassandra_helper", "conf/0.6/cassandra.in.sh", "conf/0.6/log4j.properties", "conf/0.6/schema.json", "conf/0.6/storage-conf.xml", "conf/0.7/cassandra.in.sh", "conf/0.7/cassandra.yaml", "conf/0.7/log4j-server.properties", "conf/0.7/schema.json", "conf/0.7/schema.txt", "conf/0.8/cassandra.in.sh", "conf/0.8/cassandra.yaml", "conf/0.8/log4j-server.properties", "conf/0.8/schema.json", "conf/0.8/schema.txt", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb", "vendor/0.6/gen-rb/cassandra.rb", "vendor/0.6/gen-rb/cassandra_constants.rb", "vendor/0.6/gen-rb/cassandra_types.rb", "vendor/0.7/gen-rb/cassandra.rb", "vendor/0.7/gen-rb/cassandra_constants.rb", "vendor/0.7/gen-rb/cassandra_types.rb", "vendor/0.8/gen-rb/cassandra.rb", "vendor/0.8/gen-rb/cassandra_constants.rb", "vendor/0.8/gen-rb/cassandra_types.rb", "mcmire-cassandra.gemspec"]
13
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.md", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/1.0.rb", "lib/cassandra/1.0/cassandra.rb", "lib/cassandra/1.0/columns.rb", "lib/cassandra/1.0/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/composite.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb"]
14
+ s.files = ["CHANGELOG", "Gemfile", "LICENSE", "Manifest", "README.md", "Rakefile", "bin/cassandra_helper", "conf/0.6/cassandra.in.sh", "conf/0.6/log4j.properties", "conf/0.6/schema.json", "conf/0.6/storage-conf.xml", "conf/0.7/cassandra.in.sh", "conf/0.7/cassandra.yaml", "conf/0.7/log4j-server.properties", "conf/0.7/schema.json", "conf/0.7/schema.txt", "conf/0.8/cassandra.in.sh", "conf/0.8/cassandra.yaml", "conf/0.8/log4j-server.properties", "conf/0.8/schema.json", "conf/0.8/schema.txt", "conf/1.0/cassandra.in.sh", "conf/1.0/cassandra.yaml", "conf/1.0/log4j-server.properties", "conf/1.0/schema.json", "conf/1.0/schema.txt", "lib/cassandra.rb", "lib/cassandra/0.6.rb", "lib/cassandra/0.6/cassandra.rb", "lib/cassandra/0.6/columns.rb", "lib/cassandra/0.6/protocol.rb", "lib/cassandra/0.7.rb", "lib/cassandra/0.7/cassandra.rb", "lib/cassandra/0.7/columns.rb", "lib/cassandra/0.7/protocol.rb", "lib/cassandra/0.8.rb", "lib/cassandra/0.8/cassandra.rb", "lib/cassandra/0.8/columns.rb", "lib/cassandra/0.8/protocol.rb", "lib/cassandra/1.0.rb", "lib/cassandra/1.0/cassandra.rb", "lib/cassandra/1.0/columns.rb", "lib/cassandra/1.0/protocol.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/column_family.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/composite.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/helpers.rb", "lib/cassandra/keyspace.rb", "lib/cassandra/long.rb", "lib/cassandra/mock.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "mcmire-cassandra.gemspec", "test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/composite_type_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb", "vendor/0.6/gen-rb/cassandra.rb", "vendor/0.6/gen-rb/cassandra_constants.rb", "vendor/0.6/gen-rb/cassandra_types.rb", "vendor/0.7/gen-rb/cassandra.rb", "vendor/0.7/gen-rb/cassandra_constants.rb", "vendor/0.7/gen-rb/cassandra_types.rb", "vendor/0.8/gen-rb/cassandra.rb", "vendor/0.8/gen-rb/cassandra_constants.rb", "vendor/0.8/gen-rb/cassandra_types.rb", "vendor/1.0/gen-rb/cassandra.rb", "vendor/1.0/gen-rb/cassandra_constants.rb", "vendor/1.0/gen-rb/cassandra_types.rb"]
15
15
  s.homepage = "http://fauna.github.com/fauna/mcmire-cassandra/"
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Mcmire-cassandra", "--main", "README.md"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubyforge_project = "fauna"
19
19
  s.rubygems_version = "1.8.11"
20
20
  s.summary = "A Ruby client for the Cassandra distributed database."
21
- s.test_files = ["test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb"]
21
+ s.test_files = ["test/cassandra_client_test.rb", "test/cassandra_mock_test.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/composite_type_test.rb", "test/eventmachine_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb"]
22
22
 
23
23
  if s.respond_to? :specification_version then
24
24
  s.specification_version = 3
@@ -22,6 +22,12 @@ class CassandraMockTest < CassandraTest
22
22
 
23
23
  @uuids = (0..6).map {|i| SimpleUUID::UUID.new(Time.at(2**(24+i))) }
24
24
  @longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
25
+ @composites = [
26
+ Cassandra::Composite.new([5].pack('N'), "zebra"),
27
+ Cassandra::Composite.new([5].pack('N'), "aardvark"),
28
+ Cassandra::Composite.new([1].pack('N'), "elephant"),
29
+ Cassandra::Composite.new([10].pack('N'), "kangaroo"),
30
+ ]
25
31
  end
26
32
 
27
33
  def test_setup
@@ -21,6 +21,12 @@ class CassandraTest < Test::Unit::TestCase
21
21
 
22
22
  @uuids = (0..6).map {|i| SimpleUUID::UUID.new(Time.at(2**(24+i))) }
23
23
  @longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
24
+ @composites = [
25
+ Cassandra::Composite.new([5].pack('N'), "zebra"),
26
+ Cassandra::Composite.new([5].pack('N'), "aardvark"),
27
+ Cassandra::Composite.new([1].pack('N'), "elephant"),
28
+ Cassandra::Composite.new([10].pack('N'), "kangaroo"),
29
+ ]
24
30
  end
25
31
 
26
32
  def test_inspect
@@ -43,7 +49,7 @@ class CassandraTest < Test::Unit::TestCase
43
49
  end
44
50
 
45
51
  def test_get_key
46
-
52
+
47
53
  @twitter.insert(:Users, key, {'body' => 'v', 'user' => 'v'})
48
54
  assert_equal({'body' => 'v', 'user' => 'v'}, @twitter.get(:Users, key))
49
55
  assert_equal(['body', 'user'].sort, @twitter.get(:Users, key).timestamps.keys.sort)
@@ -501,12 +507,12 @@ class CassandraTest < Test::Unit::TestCase
501
507
 
502
508
  def test_count_columns
503
509
  columns = (1..200).inject(Hash.new){|h,v| h['column' + v.to_s] = v.to_s; h;}
504
-
510
+
505
511
  @twitter.insert(:Statuses, key, columns)
506
512
  assert_equal 200, @twitter.count_columns(:Statuses, key, :count => 200)
507
- assert_equal 100, @twitter.count_columns(:Statuses, key)
513
+ assert_equal 100, @twitter.count_columns(:Statuses, key)
508
514
  assert_equal 55, @twitter.count_columns(:Statuses, key, :count => 55)
509
-
515
+
510
516
  end
511
517
 
512
518
  def test_count_super_columns
@@ -556,24 +562,24 @@ class CassandraTest < Test::Unit::TestCase
556
562
  assert_equal({}, @twitter.get(:Users, k + '2')) # Not yet written
557
563
  assert_equal({}, @twitter.get(:Statuses, k + '3')) # Not yet written
558
564
 
559
- @twitter.remove(:Users, k + '1') # Full row
565
+ @twitter.remove(:Users, k + '1') # Full row
560
566
  assert_equal({'body' => 'v1', 'user' => 'v1'}, @twitter.get(:Users, k + '1')) # Not yet removed
561
567
 
562
568
  @twitter.remove(:Users, k + '0', 'delete_me') # A single column of the row
563
569
  assert_equal({'delete_me' => 'v0', 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # Not yet removed
564
-
570
+
565
571
  @twitter.remove(:Users, k + '4')
566
572
  @twitter.insert(:Users, k + '4', {'body' => 'v4', 'user' => 'v4'})
567
573
  assert_equal({}, @twitter.get(:Users, k + '4')) # Not yet written
568
574
 
569
575
  # SuperColumns
570
576
  # Add and delete new sub columns to the user timeline supercolumn
571
- @twitter.insert(:StatusRelationships, k, {'user_timelines' => new_subcolumns })
577
+ @twitter.insert(:StatusRelationships, k, {'user_timelines' => new_subcolumns })
572
578
  @twitter.remove(:StatusRelationships, k, 'user_timelines' , subcolumn_to_delete ) # Delete the first of the initial_subcolumns from the user_timeline supercolumn
573
579
  assert_equal(initial_subcolumns, @twitter.get(:StatusRelationships, k, 'user_timelines')) # No additions or deletes reflected yet
574
- # Delete a complete supercolumn
580
+ # Delete a complete supercolumn
575
581
  @twitter.remove(:StatusRelationships, k, 'dummy_supercolumn' ) # Delete the full dummy supercolumn
576
- assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn')) # dummy supercolumn not yet deleted
582
+ assert_equal({@uuids[5] => 'value'}, @twitter.get(:StatusRelationships, k, 'dummy_supercolumn')) # dummy supercolumn not yet deleted
577
583
  end
578
584
 
579
585
  assert_equal({'body' => 'v2', 'user' => 'v2'}, @twitter.get(:Users, k + '2')) # Written
@@ -581,9 +587,9 @@ class CassandraTest < Test::Unit::TestCase
581
587
  assert_equal({'body' => 'v4', 'user' => 'v4'}, @twitter.get(:Users, k + '4')) # Written
582
588
  assert_equal({'body' => 'v'}, @twitter.get(:Statuses, k + '3')) # Written
583
589
  assert_equal({}, @twitter.get(:Users, k + '1')) # Removed
584
-
590
+
585
591
  assert_equal({ 'keep_me' => 'v0'}, @twitter.get(:Users, k + '0')) # 'delete_me' column removed
586
-
592
+
587
593
 
588
594
  assert_equal({'body' => 'v2', 'user' => 'v2'}.keys.sort, @twitter.get(:Users, k + '2').timestamps.keys.sort) # Written
589
595
  assert_equal({'body' => 'v3', 'user' => 'v3', 'location' => 'v3'}.keys.sort, @twitter.get(:Users, k + '3').timestamps.keys.sort) # Written and compacted
@@ -593,7 +599,7 @@ class CassandraTest < Test::Unit::TestCase
593
599
  # Final result: initial_subcolumns - initial_subcolumns.first + new_subcolumns
594
600
  resulting_subcolumns = initial_subcolumns.merge(new_subcolumns).reject{|k2,v| k2 == subcolumn_to_delete }
595
601
  assert_equal(resulting_subcolumns, @twitter.get(:StatusRelationships, key, 'user_timelines'))
596
- assert_equal({}, @twitter.get(:StatusRelationships, key, 'dummy_supercolumn')) # dummy supercolumn deleted
602
+ assert_equal({}, @twitter.get(:StatusRelationships, key, 'dummy_supercolumn')) # dummy supercolumn deleted
597
603
 
598
604
  end
599
605
 
@@ -834,8 +840,47 @@ class CassandraTest < Test::Unit::TestCase
834
840
  assert_equal(1, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'today'))
835
841
  assert_equal(2, @twitter.get(:UserCounterAggregates, 'bob', 'DAU', 'tomorrow'))
836
842
  end
843
+
844
+ def test_composite_column_type_conversion
845
+ columns = {}
846
+ @composites.each_with_index do |c, index|
847
+ columns[c] = "value-#{index}"
848
+ end
849
+ @type_conversions.insert(:CompositeColumnConversion, key, columns)
850
+ columns_in_order = [
851
+ Cassandra::Composite.new([1].pack('N'), "elephant"),
852
+ Cassandra::Composite.new([5].pack('N'), "aardvark"),
853
+ Cassandra::Composite.new([5].pack('N'), "zebra"),
854
+ Cassandra::Composite.new([10].pack('N'), "kangaroo"),
855
+ ]
856
+ assert_equal(columns_in_order, @type_conversions.get(:CompositeColumnConversion, key).keys)
857
+
858
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
859
+ :start => Cassandra::Composite.new([1].pack('N')),
860
+ :finish => Cassandra::Composite.new([10].pack('N')),
861
+ ).keys
862
+ assert_equal(columns_in_order[0..-2], column_slice)
863
+
864
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
865
+ :start => Cassandra::Composite.new([5].pack('N')),
866
+ :finish => Cassandra::Composite.new([5].pack('N'), :slice => :after),
867
+ ).keys
868
+ assert_equal(columns_in_order[1..2], column_slice)
869
+
870
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
871
+ :start => Cassandra::Composite.new([5].pack('N'), :slice => :after).to_s,
872
+ ).keys
873
+ assert_equal([columns_in_order[-1]], column_slice)
874
+
875
+ column_slice = @type_conversions.get(:CompositeColumnConversion, key,
876
+ :finish => Cassandra::Composite.new([10].pack('N'), :slice => :before).to_s,
877
+ ).keys
878
+ assert_equal(columns_in_order[0..-2], column_slice)
879
+
880
+ assert_equal('value-2', @type_conversions.get(:CompositeColumnConversion, key, columns_in_order.first))
881
+ end
837
882
  end
838
-
883
+
839
884
  def test_column_timestamps
840
885
  base_time = Time.now
841
886
  @twitter.insert(:Statuses, "time-key", { "body" => "value" })