mcmire-cassandra 0.12.2 → 0.12.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -2
- data/Gemfile +8 -0
- data/Manifest +16 -0
- data/conf/0.8/schema.json +4 -1
- data/conf/0.8/schema.txt +1 -1
- data/conf/1.0/cassandra.in.sh +41 -0
- data/conf/1.0/cassandra.yaml +415 -0
- data/conf/1.0/log4j-server.properties +40 -0
- data/conf/1.0/schema.json +69 -0
- data/conf/1.0/schema.txt +51 -0
- data/lib/cassandra.rb +1 -0
- data/lib/cassandra/1.0.rb +7 -0
- data/lib/cassandra/1.0/cassandra.rb +10 -0
- data/lib/cassandra/1.0/columns.rb +4 -0
- data/lib/cassandra/1.0/protocol.rb +23 -0
- data/lib/cassandra/columns.rb +2 -1
- data/lib/cassandra/composite.rb +118 -0
- data/mcmire-cassandra.gemspec +5 -5
- data/test/cassandra_mock_test.rb +6 -0
- data/test/cassandra_test.rb +58 -13
- data/test/composite_type_test.rb +29 -0
- data/vendor/1.0/gen-rb/cassandra.rb +2215 -0
- data/vendor/1.0/gen-rb/cassandra_constants.rb +12 -0
- data/vendor/1.0/gen-rb/cassandra_types.rb +857 -0
- metadata +32 -11
@@ -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
|
+
}
|
data/conf/1.0/schema.txt
ADDED
@@ -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)';
|
data/lib/cassandra.rb
CHANGED
@@ -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,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
|
data/lib/cassandra/columns.rb
CHANGED
@@ -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
|
data/mcmire-cassandra.gemspec
CHANGED
@@ -2,23 +2,23 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "mcmire-cassandra"
|
5
|
-
s.version = "0.12.
|
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-
|
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", "
|
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
|
data/test/cassandra_mock_test.rb
CHANGED
@@ -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
|
data/test/cassandra_test.rb
CHANGED
@@ -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" })
|