cassandra_client 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,2 +1,4 @@
1
1
 
2
+ v0.2. Re-factor table vs. column family interface per discussion with jbellis.
3
+
2
4
  v0.1. First release.
data/Manifest CHANGED
@@ -2,10 +2,11 @@ CHANGELOG
2
2
  conf/cassandra.in.sh
3
3
  conf/log4j.properties
4
4
  conf/storage-conf.xml
5
- lib/cassandra_client/client.rb
5
+ lib/cassandra_client/cassandra_client.rb
6
+ lib/cassandra_client/helper.rb
6
7
  lib/cassandra_client/ordered_hash.rb
8
+ lib/cassandra_client/safe_client.rb
7
9
  lib/cassandra_client/serialization.rb
8
- lib/cassandra_client/table.rb
9
10
  lib/cassandra_client.rb
10
11
  LICENSE
11
12
  Manifest
data/README CHANGED
@@ -19,7 +19,9 @@ The public certificate for this gem is here[http://rubyforge.org/frs/download.ph
19
19
 
20
20
  This is an alpha release and does not yet support the full Thrift API.
21
21
 
22
- Cassandra is a rapidly moving target; this library is currently tested againt Cassandra trunk revision 789419.
22
+ Cassandra is a rapidly moving target; this library is currently tested against {Cassandra trunk revision 789419}[http://blog.evanweaver.com/files/cassandra/cassandra-r789419.tar.bz2].
23
+
24
+ The Github source repository is {here}[http://github.com/fauna/cassandra_client/]; patches and contributions are very welcome.
23
25
 
24
26
  == Installation
25
27
 
@@ -35,32 +37,27 @@ Require the library:
35
37
 
36
38
  require 'cassandra_client'
37
39
 
38
- Connect to a server:
40
+ Connect to a server and keyspace:
39
41
 
40
- client = CassandraClient.new("127.0.0.1")
42
+ client = CassandraClient.new('Twitter', "127.0.0.1")
41
43
 
42
- Get a keyspace:
43
-
44
- users = client.table('Users')
45
-
46
44
  Insert into a column family. You can insert a CassandraClient::OrderedHash, or a regular Hash, if order doesn't matter:
47
45
 
48
- users.insert("5", :row, {'screen_name' => "buttonscat"})
46
+ client.insert(:Users, "5", {'screen_name' => "buttonscat"})
49
47
 
50
48
  Insert into a super column family:
51
49
 
52
- users.insert("5", :relationships, {"user_timeline" => {"1" => ""}})
50
+ client.insert(:UserRelationships, "5", {"user_timeline" => {"1" => ""}})
53
51
 
54
52
  Query a super column:
55
53
 
56
- timeline = users.get("5", :relationships, "user_timeline")
54
+ timeline = client.get(:UserRelationships, "5", "user_timeline")
57
55
 
58
56
  The returned result will always be a CassandraClient::OrderedHash.
59
57
 
60
- See CassandraClient::Table for more methods.
58
+ See CassandraClient and CassandraClient::Table for more methods.
61
59
 
62
60
  == Reporting problems
63
61
 
64
62
  The Github issue tracker is {here}[http://github.com/fauna/cassandra_client/issues]. If you have problems with Cassandra itself, please use the {cassandra-user mailing list}[http://mail-archives.apache.org/mod_mbox/incubator-cassandra-user/].
65
63
 
66
- Patches and contributions are very welcome. Please note that contributors are required to assign copyright for their additions to Twitter, Inc.
data/Rakefile CHANGED
@@ -7,6 +7,7 @@ Echoe.new("cassandra_client") do |p|
7
7
  p.rubygems_version = ">= 0.8"
8
8
  p.dependencies = ['json']
9
9
  p.ignore_pattern = /^(data|vendor\/cassandra|cassandra-r789419|vendor\/thrift)/
10
+ p.rdoc_pattern = /^(lib|bin|tasks|ext)|_types.rb|_constants.rb|^README|^CHANGELOG|^TODO|^LICENSE|^COPYING$/
10
11
  p.url = "http://blog.evanweaver.com/files/doc/fauna/cassandra_client/"
11
12
  p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
12
13
  end
@@ -2,16 +2,16 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{cassandra_client}
5
- s.version = "0.1"
5
+ s.version = "0.2"
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"]
9
9
  s.cert_chain = ["/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-public_cert.pem"]
10
- s.date = %q{2009-07-04}
10
+ s.date = %q{2009-07-06}
11
11
  s.description = %q{A Ruby client for CassandraDB.}
12
12
  s.email = %q{}
13
- s.extra_rdoc_files = ["CHANGELOG", "lib/cassandra_client/client.rb", "lib/cassandra_client/ordered_hash.rb", "lib/cassandra_client/serialization.rb", "lib/cassandra_client/table.rb", "lib/cassandra_client.rb", "LICENSE", "README"]
14
- s.files = ["CHANGELOG", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "lib/cassandra_client/client.rb", "lib/cassandra_client/ordered_hash.rb", "lib/cassandra_client/serialization.rb", "lib/cassandra_client/table.rb", "lib/cassandra_client.rb", "LICENSE", "Manifest", "quickstart.sh", "Rakefile", "README", "test/cassandra_client_test.rb", "vendor/gen-rb/cassandra.rb", "vendor/gen-rb/cassandra_constants.rb", "vendor/gen-rb/cassandra_types.rb", "cassandra_client.gemspec"]
13
+ s.extra_rdoc_files = ["CHANGELOG", "lib/cassandra_client/cassandra_client.rb", "lib/cassandra_client/helper.rb", "lib/cassandra_client/ordered_hash.rb", "lib/cassandra_client/safe_client.rb", "lib/cassandra_client/serialization.rb", "lib/cassandra_client.rb", "LICENSE", "README", "vendor/gen-rb/cassandra_constants.rb", "vendor/gen-rb/cassandra_types.rb"]
14
+ s.files = ["CHANGELOG", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "lib/cassandra_client/cassandra_client.rb", "lib/cassandra_client/helper.rb", "lib/cassandra_client/ordered_hash.rb", "lib/cassandra_client/safe_client.rb", "lib/cassandra_client/serialization.rb", "lib/cassandra_client.rb", "LICENSE", "Manifest", "quickstart.sh", "Rakefile", "README", "test/cassandra_client_test.rb", "vendor/gen-rb/cassandra.rb", "vendor/gen-rb/cassandra_constants.rb", "vendor/gen-rb/cassandra_types.rb", "cassandra_client.gemspec"]
15
15
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/cassandra_client/}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cassandra_client", "--main", "README"]
17
17
  s.require_paths = ["lib"]
@@ -20,7 +20,7 @@
20
20
  <!--======================================================================-->
21
21
  <!-- Basic Configuration -->
22
22
  <!--======================================================================-->
23
- <ClusterName>Up and Running</ClusterName>
23
+ <ClusterName>Test</ClusterName>
24
24
 
25
25
  <!-- Tables and ColumnFamilies
26
26
  Think of a table as a namespace, not a relational table.
@@ -29,22 +29,19 @@
29
29
  There is an implicit table named 'system' for Cassandra internals.
30
30
  -->
31
31
  <Tables>
32
- <Table Name="Users">
33
- <ColumnFamily ColumnSort="Name" Name="row" />
34
- <ColumnFamily ColumnSort="Name" Name="audit" />
35
- <ColumnFamily ColumnType="Super" ColumnSort="Name" Name="relationships" />
36
- <ColumnFamily ColumnSort="Time" Name="usernames" />
32
+ <Table Name="Twitter">
33
+ <ColumnFamily ColumnSort="Name" Name="Users" />
34
+ <ColumnFamily ColumnSort="Name" Name="UserAudits" />
35
+ <ColumnFamily ColumnType="Super" ColumnSort="Name" Name="UserRelationships" />
36
+ <ColumnFamily ColumnSort="Time" Name="Usernames" />
37
+ <ColumnFamily ColumnSort="Time" Name="Statuses" />
38
+ <ColumnFamily ColumnSort="Name" Name="StatusAudits" />
39
+ <ColumnFamily ColumnType="Super" ColumnSort="Name" Name="StatusRelationships" />
37
40
  </Table>
38
41
 
39
- <Table Name="Statuses">
40
- <ColumnFamily ColumnSort="Time" Name="row" />
41
- <ColumnFamily ColumnSort="Name" Name="audit" />
42
- <ColumnFamily ColumnType="Super" ColumnSort="Name" Name="relationships" />
43
- </Table>
44
-
45
- <Table Name="Blogs">
46
- <ColumnFamily ColumnSort="Time" Name="posts"/>
47
- <ColumnFamily ColumnSort="Time" Name="comments"/>
42
+ <Table Name="Multiblog">
43
+ <ColumnFamily ColumnSort="Time" Name="Blogs"/>
44
+ <ColumnFamily ColumnSort="Time" Name="Comments"/>
48
45
  </Table>
49
46
  </Tables>
50
47
 
@@ -5,10 +5,11 @@ require 'thrift'
5
5
 
6
6
  HERE = File.expand_path(File.dirname(__FILE__))
7
7
 
8
- require "#{HERE}/cassandra_client/client"
9
- require "#{HERE}/cassandra_client/table"
8
+ require "#{HERE}/cassandra_client/helper"
9
+ require "#{HERE}/cassandra_client/safe_client"
10
10
  require "#{HERE}/cassandra_client/serialization"
11
11
  require "#{HERE}/cassandra_client/ordered_hash"
12
+ require "#{HERE}/cassandra_client/cassandra_client"
12
13
 
13
14
  $LOAD_PATH << "#{HERE}/../vendor/gen-rb"
14
15
  require 'cassandra'
@@ -0,0 +1,170 @@
1
+ class CassandraClient
2
+ include Helper
3
+ class AccessError < StandardError; end
4
+
5
+ MAX_INT = 2**31 - 1
6
+
7
+ attr_reader :keyspace, :host, :port, :quorum, :serialization, :transport, :client, :schema
8
+
9
+ # Instantiate a new CassandraClient and open the connection.
10
+ def initialize(keyspace, host = '127.0.0.1', port = 9160, quorum = 1, serialization = CassandraClient::Serialization::JSON)
11
+ @keyspace = keyspace
12
+ @host = host
13
+ @port = port
14
+ @quorum = quorum
15
+ @serialization = serialization
16
+
17
+ extend(@serialization)
18
+
19
+ @transport = Thrift::BufferedTransport.new(Thrift::Socket.new(@host, @port))
20
+ @transport.open
21
+ @client = Cassandra::SafeClient.new(
22
+ Cassandra::Client.new(Thrift::BinaryProtocol.new(@transport)),
23
+ @transport)
24
+
25
+ keyspaces = @client.getStringListProperty("tables")
26
+ unless keyspaces.include?(@keyspace)
27
+ raise AccessError, "Keyspace #{@keyspace.inspect} not found. Available: #{keyspaces.inspect}"
28
+ end
29
+
30
+ @schema = @client.describeTable(@keyspace)
31
+ end
32
+
33
+ def inspect
34
+ "#<CassandraClient:#{object_id}, @keyspace=#{keyspace.inspect}, @schema={#{
35
+ schema.map {|name, hash| ":#{name} => #{hash['type'].inspect}"}.join(', ')
36
+ }}, @host=#{host.inspect}, @port=#{port}, @quorum=#{quorum}, @serialization=#{serialization.name}>"
37
+ end
38
+
39
+ ## Write
40
+
41
+ # Insert a row for a key. Pass a flat hash for a regular column family, and
42
+ # a nested hash for a super column family.
43
+ def insert(column_family, key, hash, timestamp = now)
44
+ column_family = column_family.to_s
45
+ insert = is_super(column_family) ? :insert_super : :insert_standard
46
+ send(insert, column_family, key, hash, timestamp)
47
+ end
48
+
49
+ private
50
+
51
+ def insert_standard(column_family, key, hash, timestamp = now)
52
+ mutation = Batch_mutation_t.new(
53
+ :table => @keyspace,
54
+ :key => key,
55
+ :cfmap => {column_family => hash_to_columns(hash, timestamp)})
56
+ @client.batch_insert(mutation, @quorum)
57
+ end
58
+
59
+ def insert_super(column_family, key, hash, timestamp = now)
60
+ mutation = Batch_mutation_super_t.new(
61
+ :table => @keyspace,
62
+ :key => key,
63
+ :cfmap => {column_family => hash_to_super_columns(hash, timestamp)})
64
+ @client.batch_insert_superColumn(mutation, @quorum)
65
+ end
66
+
67
+ public
68
+
69
+ ## Delete
70
+
71
+ # Remove the element at the column_family:key:super_column:column
72
+ # path you request.
73
+ def remove(column_family, key, super_column = nil, column = nil, timestamp = now)
74
+ column_family = column_family.to_s
75
+ column_family += ":#{super_column}" if super_column
76
+ column_family += ":#{column}" if column
77
+ @client.remove(@keyspace, key, column_family, timestamp, @quorum)
78
+ end
79
+
80
+ # Remove all rows in the column family you request.
81
+ def clear_column_family!(column_family)
82
+ get_key_range(column_family).each do |key|
83
+ remove(column_family, key)
84
+ end
85
+ end
86
+
87
+ # Remove all rows in the keyspace
88
+ def clear_keyspace!
89
+ @schema.keys.each do |column_family|
90
+ clear_column_family!(column_family)
91
+ end
92
+ end
93
+
94
+ ## Read
95
+
96
+ # Count the elements at the column_family:key:super_column path you
97
+ # request.
98
+ def count_columns(column_family, key, super_column = nil)
99
+ column_family = column_family.to_s
100
+ column_family += ":#{super_column}" if super_column
101
+ @client.get_column_count(@keyspace, key, column_family)
102
+ end
103
+
104
+ # Return a list of single values for the elements at the
105
+ # column_family:key:super_column:column path you request.
106
+ def get_columns(column_family, key, super_columns, columns = nil)
107
+ column_family = column_family.to_s
108
+ get_slice_by_names = (is_super(column_family) && !columns) ? :get_slice_super_by_names : :get_slice_by_names
109
+ if super_columns and columns
110
+ column_family += ":#{super_columns}"
111
+ columns = Array(columns)
112
+ else
113
+ columns = Array(super_columns)
114
+ end
115
+
116
+ hash = columns_to_hash(@client.send(get_slice_by_names, @keyspace, key, column_family, columns))
117
+ columns.map { |column| hash[column] }
118
+ end
119
+
120
+ # Return a hash (actually, a CassandraClient::OrderedHash) or a single value
121
+ # representing the element at the column_family:key:super_column:column
122
+ # path you request.
123
+ def get(column_family, key, super_column = nil, column = nil, offset = -1, limit = 100)
124
+ column_family = column_family.to_s
125
+ column_family += ":#{super_column}" if super_column
126
+ column_family += ":#{column}" if column
127
+
128
+ # You have got to be kidding
129
+ if is_super(column_family)
130
+ if column
131
+ load(@client.get_column(@keyspace, key, column_family).value)
132
+ elsif super_column
133
+ columns_to_hash(@client.get_superColumn(@keyspace, key, column_family).columns)
134
+ else
135
+ columns_to_hash(@client.get_slice_super(@keyspace, key, "#{column_family}:", offset, limit))
136
+ end
137
+ else
138
+ if super_column
139
+ load(@client.get_column(@keyspace, key, column_family).value)
140
+ elsif is_sorted_by_time(column_family)
141
+ result = columns_to_hash(@client.get_columns_since(@keyspace, key, column_family, 0))
142
+
143
+ # FIXME Hack until get_slice on a time-sorted column family works again
144
+ result = OrderedHash[*flatten_once(result.to_a[offset, limit])] if offset > -1
145
+ result
146
+ else
147
+ columns_to_hash(@client.get_slice(@keyspace, key, "#{column_family}:", offset, limit))
148
+ end
149
+ end
150
+ rescue NotFoundException
151
+ is_super(column_family) && !column ? {} : nil
152
+ end
153
+
154
+ # FIXME
155
+ # def get_recent(column_family, key, super_column = nil, column = nil, timestamp = 0)
156
+ # end
157
+
158
+ # Return a list of keys in the column_family you request. Requires the
159
+ # table to be partitioned with OrderPreservingHash.
160
+ def get_key_range(column_family, key_range = ''..'', limit = 100)
161
+ column_families = Array(column_family).map {|c| c.to_s}
162
+ @client.get_key_range(@keyspace, column_families, key_range.begin, key_range.end, limit)
163
+ end
164
+
165
+ # Count all rows in the column_family you request. Requires the table
166
+ # to be partitioned with OrderPreservingHash.
167
+ def count(column_family, key_range = ''..'', limit = MAX_INT)
168
+ get_key_range(column_family, key_range, limit).size
169
+ end
170
+ end
@@ -0,0 +1,57 @@
1
+ class CassandraClient
2
+ module Helper
3
+
4
+ private
5
+
6
+ def is_super(column_family)
7
+ column_family_property(column_family, 'type') == 'Super'
8
+ end
9
+
10
+ def is_sorted_by_time(column_family)
11
+ column_family_property(column_family, 'sort') == 'Time'
12
+ end
13
+
14
+ def column_family_property(column_family_or_path, key)
15
+ column_family = column_family_or_path.to_s.split(':').first
16
+ @schema[column_family][key]
17
+ rescue NoMethodError
18
+ raise AccessError, "Invalid column family \":#{column_family}\""
19
+ end
20
+
21
+ def columns_to_hash(columns)
22
+ hash = ::CassandraClient::OrderedHash.new
23
+ Array(columns).each do |c|
24
+ if c.is_a?(SuperColumn_t)
25
+ hash[c.name] = columns_to_hash(c.columns)
26
+ else
27
+ hash[c.columnName] = load(c.value)
28
+ end
29
+ end
30
+ hash
31
+ end
32
+
33
+ def hash_to_columns(hash, timestamp)
34
+ hash.map do |column, value|
35
+ Column_t.new(:columnName => column, :value => dump(value), :timestamp => timestamp)
36
+ end
37
+ end
38
+
39
+ def hash_to_super_columns(hash, timestamp)
40
+ hash.map do |super_column, columns|
41
+ SuperColumn_t.new(:name => super_column, :columns => hash_to_columns(columns, timestamp))
42
+ end
43
+ end
44
+
45
+ def time_in_microseconds
46
+ time = Time.now
47
+ time.to_i * 1_000_000 + time.usec
48
+ end
49
+ alias :now :time_in_microseconds
50
+
51
+ def flatten_once(array)
52
+ result = []
53
+ array.each { |el| result.concat(el) }
54
+ result
55
+ end
56
+ end
57
+ end
@@ -1,30 +1,31 @@
1
- # Copyright (c) 2004-2009 David Heinemeier Hansson
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining
4
- # a copy of this software and associated documentation files (the
5
- # "Software"), to deal in the Software without restriction, including
6
- # without limitation the rights to use, copy, modify, merge, publish,
7
- # distribute, sublicense, and/or sell copies of the Software, and to
8
- # permit persons to whom the Software is furnished to do so, subject to
9
- # the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be
12
- # included in all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
1
 
22
2
  class CassandraClient
23
3
  # Hash is ordered in Ruby 1.9!
24
4
  if RUBY_VERSION >= '1.9'
25
5
  OrderedHash = ::Hash
26
- else
27
- class OrderedHash < Hash #:nodoc:
6
+ else
7
+ # Copyright (c) 2004-2009 David Heinemeier Hansson
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+
28
+ class OrderedHash < Hash
28
29
  require 'enumerator'
29
30
 
30
31
  def self.[](*array)
@@ -0,0 +1,18 @@
1
+
2
+ module Cassandra
3
+ class SafeClient
4
+ def initialize(client, transport)
5
+ @client = client
6
+ @transport = transport
7
+ end
8
+
9
+ def method_missing(*args)
10
+ @client.send(*args)
11
+ rescue IOError
12
+ @transport.open
13
+ raise if defined?(once)
14
+ once = true
15
+ retry
16
+ end
17
+ end
18
+ end
@@ -6,194 +6,198 @@ begin; require 'ruby-debug'; rescue LoadError; end
6
6
 
7
7
  class CassandraClientTest < Test::Unit::TestCase
8
8
  def setup
9
- @client = CassandraClient.new('127.0.0.1')
10
- @client.remove_all
11
- @statuses = @client.table('Statuses')
12
- @users = @client.table('Users')
9
+ @twitter = CassandraClient.new('Twitter', '127.0.0.1')
10
+ @twitter.clear_keyspace!
11
+ @blogs = CassandraClient.new('Multiblog', '127.0.0.1')
12
+ @blogs.clear_keyspace!
13
13
  end
14
14
 
15
15
  def test_inspect
16
16
  assert_nothing_raised do
17
- @statuses.inspect
18
- @client.inspect
17
+ @blogs.inspect
18
+ @twitter.inspect
19
19
  end
20
20
  end
21
21
 
22
22
  def test_connection_reopens
23
23
  assert_raises(NoMethodError) do
24
- @statuses.insert(1, :row, {'body' => 'v'})
24
+ @twitter.insert(:Statuses, 1, {'body' => 'v'})
25
25
  end
26
26
  assert_nothing_raised do
27
- @statuses.insert(key, :row, {'body' => 'v'})
27
+ @twitter.insert(:Statuses, key, {'body' => 'v'})
28
28
  end
29
29
  end
30
30
 
31
31
  def test_get_key_name_sorted
32
- @users.insert(key, :row, {'body' => 'v', 'user' => 'v'})
33
- assert_equal({'body' => 'v', 'user' => 'v'}, @users.get(key, :row))
34
- assert_equal({}, @users.get('bogus', :row))
32
+ @twitter.insert(:Users, key, {'body' => 'v', 'user' => 'v'})
33
+ assert_equal({'body' => 'v', 'user' => 'v'}, @twitter.get(:Users, key))
34
+ assert_equal({}, @twitter.get(:Users, 'bogus'))
35
35
  end
36
36
 
37
37
  def test_get_key_name_sorted_preserving_order
38
38
  # In-order hash is preserved
39
39
  hash = CassandraClient::OrderedHash['a', '', 'b', '', 'c', '', 'd', '',]
40
- @users.insert(key, :row, hash)
41
- assert_equal(hash.keys, @users.get(key, :row).keys)
40
+ @twitter.insert(:Users, key, hash)
41
+ assert_equal(hash.keys, @twitter.get(:Users, key).keys)
42
42
 
43
- @users.remove(key, :row)
43
+ @twitter.remove(:Users, key)
44
44
 
45
45
  # Out-of-order hash is returned sorted
46
46
  hash = CassandraClient::OrderedHash['b', '', 'c', '', 'd', '', 'a', '']
47
- @users.insert(key, :row, hash)
48
- assert_equal(hash.keys.sort, @users.get(key, :row).keys)
49
- assert_not_equal(hash.keys, @users.get(key, :row).keys)
47
+ @twitter.insert(:Users, key, hash)
48
+ assert_equal(hash.keys.sort, @twitter.get(:Users, key).keys)
49
+ assert_not_equal(hash.keys, @twitter.get(:Users, key).keys)
50
50
  end
51
51
 
52
52
  def test_get_key_time_sorted
53
- @statuses.insert(key, :row, {'body' => 'v', 'user' => 'v'})
54
- assert_equal({'body' => 'v', 'user' => 'v'}, @statuses.get(key, :row))
55
- assert_equal({}, @statuses.get('bogus', :row))
53
+ @twitter.insert(:Statuses, key, {'body' => 'v', 'user' => 'v'})
54
+ assert_equal({'body' => 'v', 'user' => 'v'}, @twitter.get(:Statuses, key))
55
+ assert_equal({}, @twitter.get(:Statuses, 'bogus'))
56
56
  end
57
57
 
58
58
  def test_get_key_time_sorted_with_limit
59
- @statuses.insert(key, :row, {'first' => 'v'})
60
- @statuses.insert(key, :row, {'second' => 'v'})
61
- assert_equal({'second' => 'v'}, @statuses.get(key, :row, nil, nil, 0, 1))
59
+ @twitter.insert(:Statuses, key, {'first' => 'v'})
60
+ @twitter.insert(:Statuses, key, {'second' => 'v'})
61
+ assert_equal({'second' => 'v'}, @twitter.get(:Statuses, key, nil, nil, 0, 1))
62
62
  end
63
63
 
64
64
  def test_get_value
65
- @statuses.insert(key, :row, {'body' => 'v'})
66
- assert_equal 'v', @statuses.get(key, :row, 'body')
67
- assert_nil @statuses.get('bogus', :row, 'body')
65
+ @twitter.insert(:Statuses, key, {'body' => 'v'})
66
+ assert_equal 'v', @twitter.get(:Statuses, key, 'body')
67
+ assert_nil @twitter.get(:Statuses, 'bogus', 'body')
68
68
  end
69
69
 
70
70
  def test_get_super_key
71
- @statuses.insert(key, :relationships, {'user_timelines' => {'4' => 'v', '5' => 'v'}})
72
- assert_equal({'user_timelines' => {'4' => 'v', '5' => 'v'}}, @statuses.get(key, :relationships))
73
- assert_equal({}, @statuses.get('bogus', :relationships))
71
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'4' => 'v', '5' => 'v'}})
72
+ assert_equal({'user_timelines' => {'4' => 'v', '5' => 'v'}}, @twitter.get(:StatusRelationships, key))
73
+ assert_equal({}, @twitter.get(:StatusRelationships, 'bogus'))
74
74
  end
75
75
 
76
76
  def test_get_super_key_multi
77
- @statuses.insert(key, :relationships, {
77
+ @twitter.insert(:StatusRelationships, key, {
78
78
  'user_timelines' => {'1' => 'v1'},
79
79
  'mentions_timelines' => {'2' => 'v2'}})
80
80
  assert_equal({
81
81
  'user_timelines' => {'1' => 'v1'},
82
- 'mentions_timelines' => {'2' => 'v2'}}, @statuses.get(key, :relationships))
83
- assert_equal({}, @statuses.get('bogus', :relationships))
82
+ 'mentions_timelines' => {'2' => 'v2'}}, @twitter.get(:StatusRelationships, key))
83
+ assert_equal({}, @twitter.get(:StatusRelationships, 'bogus'))
84
84
  end
85
85
 
86
86
  def test_get_super_sub_key
87
- @statuses.insert(key, :relationships, {'user_timelines' => {'4' => 'v', '5' => 'v'}})
88
- assert_equal({'4' => 'v', '5' => 'v'}, @statuses.get(key, :relationships, 'user_timelines'))
89
- assert_equal({}, @statuses.get('bogus', :relationships, 'user_timelines'))
87
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'4' => 'v', '5' => 'v'}})
88
+ assert_equal({'4' => 'v', '5' => 'v'}, @twitter.get(:StatusRelationships, key, 'user_timelines'))
89
+ assert_equal({}, @twitter.get(:StatusRelationships, 'bogus', 'user_timelines'))
90
90
  end
91
91
 
92
92
  def test_get_super_value
93
- @statuses.insert(key, :relationships, {'user_timelines' => {'1' => 'v'}})
94
- assert_equal('v', @statuses.get(key, :relationships, 'user_timelines', '1'))
95
- assert_nil @statuses.get('bogus', :relationships, 'user_timelines', '1')
93
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'1' => 'v'}})
94
+ assert_equal('v', @twitter.get(:StatusRelationships, key, 'user_timelines', '1'))
95
+ assert_nil @twitter.get(:StatusRelationships, 'bogus', 'user_timelines', '1')
96
96
  end
97
97
 
98
98
  def test_get_key_range
99
- @statuses.insert('3', :row, {'body' => 'v'})
100
- @statuses.insert('4', :row, {'body' => 'v'})
101
- @statuses.insert('5', :row, {'body' => 'v'})
102
- assert_equal(['3', '4', '5'], @statuses.get_key_range('3'..'5', :row))
99
+ @twitter.insert(:Statuses, '2', {'body' => '1'})
100
+ @twitter.insert(:Statuses, '3', {'body' => '1'})
101
+ @twitter.insert(:Statuses, '4', {'body' => '1'})
102
+ @twitter.insert(:Statuses, '5', {'body' => '1'})
103
+ @twitter.insert(:Statuses, '6', {'body' => '1'})
104
+ assert_equal(['3', '4', '5'], @twitter.get_key_range(:Statuses, '3'..'5'))
103
105
  end
104
106
 
105
107
  # Not supported
106
108
  # def test_get_key_range_super
107
- # @statuses.insert('3', :relationships, {'user_timelines' => {'1' => 'v'}})
108
- # @statuses.insert('4', :relationships, {'user_timelines' => {'1' => 'v'}})
109
- # @statuses.insert('5', :relationships, {'user_timelines' => {'1' => 'v'}})
110
- # assert_equal(['3', '4', '5'], @statuses.get_key_range('3'..'5', :relationships, 'user_timelines'))
109
+ # @twitter.insert(:StatusRelationships, '2', {'user_timelines' => {'1' => 'v'}})
110
+ # @twitter.insert(:StatusRelationships, '3', {'user_timelines' => {'1' => 'v'}})
111
+ # @twitter.insert(:StatusRelationships, '4', {'user_timelines' => {'1' => 'v'}})
112
+ # @twitter.insert(:StatusRelationships, '5', {'user_timelines' => {'1' => 'v'}})
113
+ # @twitter.insert(:StatusRelationships, '6', {'user_timelines' => {'1' => 'v'}})
114
+ # assert_equal(['3', '4', '5'], @twitter.get_key_range(:StatusRelationships, '3'..'5', 'user_timelines'))
111
115
  # end
112
116
 
113
117
  def test_remove_key
114
- @statuses.insert(key, :row, {'body' => 'v'})
115
- @statuses.remove(key, :row)
116
- assert_equal({}, @statuses.get(key, :row))
118
+ @twitter.insert(:Statuses, key, {'body' => 'v'})
119
+ @twitter.remove(:Statuses, key)
120
+ assert_equal({}, @twitter.get(:Statuses, key))
117
121
  end
118
122
 
119
123
  def test_remove_value
120
- @statuses.insert(key, :row, {'body' => 'v'})
121
- @statuses.remove(key, :row, 'body')
122
- assert_nil @statuses.get(key, :row, 'body')
124
+ @twitter.insert(:Statuses, key, {'body' => 'v'})
125
+ @twitter.remove(:Statuses, key, 'body')
126
+ assert_nil @twitter.get(:Statuses, key, 'body')
123
127
  end
124
128
 
125
129
  def test_remove_super_key
126
- @statuses.insert(key, :relationships, {'user_timelines' => {'1' => 'v'}})
127
- @statuses.remove(key, :relationships)
128
- assert_equal({}, @statuses.get(key, :relationships))
130
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'1' => 'v'}})
131
+ @twitter.remove(:StatusRelationships, key)
132
+ assert_equal({}, @twitter.get(:StatusRelationships, key))
129
133
  end
130
134
 
131
135
  def test_remove_super_sub_key
132
- @statuses.insert(key, :relationships, {'user_timelines' => {'1' => 'v'}})
133
- @statuses.remove(key, :relationships, 'user_timelines')
134
- assert_equal({}, @statuses.get(key, :relationships, 'user_timelines'))
136
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'1' => 'v'}})
137
+ @twitter.remove(:StatusRelationships, key, 'user_timelines')
138
+ assert_equal({}, @twitter.get(:StatusRelationships, key, 'user_timelines'))
135
139
  end
136
140
 
137
141
  def test_remove_super_value
138
- @statuses.insert(key, :relationships, {'user_timelines' => {'1' => 'v'}})
139
- @statuses.remove(key, :relationships, 'user_timelines', '1')
140
- assert_nil @statuses.get(key, :relationships, 'user_timelines', '1')
142
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'1' => 'v'}})
143
+ @twitter.remove(:StatusRelationships, key, 'user_timelines', '1')
144
+ assert_nil @twitter.get(:StatusRelationships, key, 'user_timelines', '1')
141
145
  end
142
146
 
143
147
  def test_insert_key
144
- @statuses.insert(key, :row, {'body' => 'v', 'user' => 'v'})
145
- assert_equal({'body' => 'v', 'user' => 'v'}, @statuses.get(key, :row))
148
+ @twitter.insert(:Statuses, key, {'body' => 'v', 'user' => 'v'})
149
+ assert_equal({'body' => 'v', 'user' => 'v'}, @twitter.get(:Statuses, key))
146
150
  end
147
151
 
148
152
  def test_insert_super_key
149
- @statuses.insert(key, :relationships, {'user_timelines' => {'1' => 'v', key => 'v'}})
150
- assert_equal({'1' => 'v' , key => 'v'}, @statuses.get(key, :relationships, 'user_timelines'))
153
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'1' => 'v', key => 'v'}})
154
+ assert_equal({'1' => 'v' , key => 'v'}, @twitter.get(:StatusRelationships, key, 'user_timelines'))
151
155
  end
152
156
 
153
157
  def test_get_column_values
154
- @statuses.insert(key, :row, {'body' => 'v1', 'user' => 'v2'})
155
- assert_equal(['v1' , 'v2'], @statuses.get_columns(key, :row, ['body', 'user']))
158
+ @twitter.insert(:Statuses, key, {'body' => 'v1', 'user' => 'v2'})
159
+ assert_equal(['v1' , 'v2'], @twitter.get_columns(:Statuses, key,['body', 'user']))
156
160
  end
157
161
 
158
162
  def test_get_column_values_super
159
- @statuses.insert(key, :relationships, {
163
+ @twitter.insert(:StatusRelationships, key, {
160
164
  'user_timelines' => {'1' => 'v1'},
161
165
  'mentions_timelines' => {'2' => 'v2'}})
162
166
  assert_equal [{'1' => 'v1'}, {'2' => 'v2'}],
163
- @statuses.get_columns(key, :relationships, ['user_timelines', 'mentions_timelines'])
167
+ @twitter.get_columns(:StatusRelationships, key, ['user_timelines', 'mentions_timelines'])
164
168
  end
165
169
 
166
170
  # Not supported
167
171
  # def test_get_columns_super_sub
168
- # @statuses.insert(key, :relationships, {
172
+ # @twitter.insert(:StatusRelationships, key, {
169
173
  # 'user_timelines' => {'1' => 'v1'},
170
174
  # 'mentions_timelines' => {'2' => 'v2'}})
171
175
  # assert_equal ['v1', 'v2'],
172
- # @statuses.get_columns(key, :relationships, 'user_timelines', ['1', key])
176
+ # @twitter.get_columns(:StatusRelationships, key, 'user_timelines', ['1', key])
173
177
  # end
174
178
 
175
179
  def test_count_keys
176
- @statuses.insert(key + "1", :row, {'body' => 'v1'})
177
- @statuses.insert(key + "2", :row, {'body' => 'v1'})
178
- @statuses.insert(key + "3", :row, {'body' => 'v1'})
179
- assert_equal 3, @statuses.count(:row)
180
+ @twitter.insert(:Statuses, key + "1", {'body' => '1'})
181
+ @twitter.insert(:Statuses, key + "2", {'body' => '2'})
182
+ @twitter.insert(:Statuses, key + "3", {'body' => '3'})
183
+ assert_equal 3, @twitter.count(:Statuses)
180
184
  end
181
185
 
182
186
  def test_count_columns
183
- @statuses.insert(key, :row, {'body' => 'v1', 'user' => 'v2'})
184
- assert_equal 2, @statuses.count_columns(key, :row)
187
+ @twitter.insert(:Statuses, key, {'body' => 'v1', 'user' => 'v2'})
188
+ assert_equal 2, @twitter.count_columns(:Statuses, key)
185
189
  end
186
190
 
187
191
  def test_count_super_columns
188
- @statuses.insert(key, :relationships, {
192
+ @twitter.insert(:StatusRelationships, key, {
189
193
  'user_timelines' => {'1' => 'v1'},
190
194
  'mentions_timelines' => {'2' => 'v2'}})
191
- assert_equal 2, @statuses.count_columns(key, :relationships)
195
+ assert_equal 2, @twitter.count_columns(:StatusRelationships, key)
192
196
  end
193
197
 
194
198
  def test_count_super_sub_columns
195
- @statuses.insert(key, :relationships, {'user_timelines' => {'1' => 'v1', key => 'v2'}})
196
- assert_equal 2, @statuses.count_columns(key, :relationships, 'user_timelines')
199
+ @twitter.insert(:StatusRelationships, key, {'user_timelines' => {'1' => 'v1', key => 'v2'}})
200
+ assert_equal 2, @twitter.count_columns(:StatusRelationships, key, 'user_timelines')
197
201
  end
198
202
 
199
203
  private
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandra_client
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.1"
4
+ version: "0.2"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Weaver
@@ -30,7 +30,7 @@ cert_chain:
30
30
  yZ0=
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2009-07-04 00:00:00 -07:00
33
+ date: 2009-07-06 00:00:00 -07:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -51,22 +51,26 @@ extensions: []
51
51
 
52
52
  extra_rdoc_files:
53
53
  - CHANGELOG
54
- - lib/cassandra_client/client.rb
54
+ - lib/cassandra_client/cassandra_client.rb
55
+ - lib/cassandra_client/helper.rb
55
56
  - lib/cassandra_client/ordered_hash.rb
57
+ - lib/cassandra_client/safe_client.rb
56
58
  - lib/cassandra_client/serialization.rb
57
- - lib/cassandra_client/table.rb
58
59
  - lib/cassandra_client.rb
59
60
  - LICENSE
60
61
  - README
62
+ - vendor/gen-rb/cassandra_constants.rb
63
+ - vendor/gen-rb/cassandra_types.rb
61
64
  files:
62
65
  - CHANGELOG
63
66
  - conf/cassandra.in.sh
64
67
  - conf/log4j.properties
65
68
  - conf/storage-conf.xml
66
- - lib/cassandra_client/client.rb
69
+ - lib/cassandra_client/cassandra_client.rb
70
+ - lib/cassandra_client/helper.rb
67
71
  - lib/cassandra_client/ordered_hash.rb
72
+ - lib/cassandra_client/safe_client.rb
68
73
  - lib/cassandra_client/serialization.rb
69
- - lib/cassandra_client/table.rb
70
74
  - lib/cassandra_client.rb
71
75
  - LICENSE
72
76
  - Manifest
metadata.gz.sig CHANGED
Binary file
@@ -1,65 +0,0 @@
1
- class CassandraClient
2
- attr_reader :client, :transport, :tables, :host, :port, :block_for, :serialization
3
-
4
- class AccessError < StandardError; end
5
-
6
- # Instantiate a new CassandraClient and open the connection.
7
- def initialize(host = '127.0.0.1', port = 9160, block_for = 1, serialization = CassandraClient::Serialization::JSON)
8
- @host = host
9
- @port = port
10
- @serialization = serialization
11
- @block_for = block_for
12
-
13
- @transport = Thrift::BufferedTransport.new(Thrift::Socket.new(@host, @port))
14
- @transport.open
15
-
16
- @client = SafeClient.new(
17
- Cassandra::Client.new(Thrift::BinaryProtocol.new(@transport)),
18
- @transport)
19
-
20
- @tables = @client.getStringListProperty("tables").map do |table_name|
21
- ::CassandraClient::Table.new(table_name, self)
22
- end
23
- end
24
-
25
- def inspect(full = true)
26
- string = "#<CassandraClient:#{object_id}, @host=#{host.inspect}, @port=#{@port.inspect}"
27
- string += ", @block_for=#{block_for.inspect}, @tables=[#{tables.map {|t| t.inspect(false) }.join(', ')}]" if full
28
- string + ">"
29
- end
30
-
31
- # Return the CassandraClient::Table instance for the table_name you
32
- # request. You can get an array of all available tables with the #tables
33
- # method.
34
- def table(table_name)
35
- table = @tables.detect {|table| table.name == table_name }
36
- raise AccessError, "No such table #{table_name.inspect}" unless table
37
- table
38
- end
39
-
40
- # Remove all rows in all column families in all tables.
41
- def remove_all
42
- tables.each do |table|
43
- table.schema.keys.each do |column_family|
44
- table.remove_all(column_family)
45
- end
46
- end
47
- end
48
-
49
- class SafeClient
50
- def initialize(client, transport)
51
- @client = client
52
- @transport = transport
53
- end
54
-
55
- def method_missing(*args)
56
- @client.send(*args)
57
- rescue IOError
58
- @transport.open
59
- raise if defined?(once)
60
- once = true
61
- retry
62
- end
63
- end
64
-
65
- end
@@ -1,202 +0,0 @@
1
- class CassandraClient
2
- class Table
3
- attr_reader :name, :schema, :parent
4
-
5
- MAX_INT = 2**31 - 1
6
-
7
- def initialize(name, parent)
8
- @parent = parent
9
- @client = parent.client
10
- @block_for = parent.block_for
11
-
12
- @name = name
13
- @schema = @client.describeTable(@name)
14
- extend(parent.serialization)
15
- end
16
-
17
- def inspect(full = true)
18
- string = "#<CassandraClient::Table:#{object_id}, @name=#{name.inspect}"
19
- string += ", @schema={#{schema.map {|name, hash| ":#{name} => #{hash['type'].inspect}"}.join(', ')}}, @parent=#{parent.inspect(false)}" if full
20
- string + ">"
21
- end
22
-
23
- ## Write
24
-
25
- # Insert a row for a key. Pass a flat hash for a regular column family, and
26
- # a nested hash for a super column family.
27
- def insert(key, column_family, hash, timestamp = now)
28
- column_family = column_family.to_s
29
- insert = is_super(column_family) ? :insert_super : :insert_standard
30
- send(insert, key, column_family, hash, timestamp)
31
- end
32
-
33
- private
34
-
35
- def insert_standard(key, column_family, hash, timestamp = now)
36
- mutation = Batch_mutation_t.new(
37
- :table => @name,
38
- :key => key,
39
- :cfmap => {column_family => hash_to_columns(hash, timestamp)})
40
- @client.batch_insert(mutation, @block_for)
41
- end
42
-
43
- def insert_super(key, column_family, hash, timestamp = now)
44
- mutation = Batch_mutation_super_t.new(
45
- :table => @name,
46
- :key => key,
47
- :cfmap => {column_family => hash_to_super_columns(hash, timestamp)})
48
- @client.batch_insert_superColumn(mutation, @block_for)
49
- end
50
-
51
- public
52
-
53
- ## Delete
54
-
55
- # Remove the element at the column_family:key:super_column:column
56
- # path you request.
57
- def remove(key, column_family, super_column = nil, column = nil, timestamp = now)
58
- column_family = column_family.to_s
59
- column_family += ":#{super_column}" if super_column
60
- column_family += ":#{column}" if column
61
- @client.remove(@name, key, column_family, timestamp, @block_for )
62
- end
63
-
64
- # Remove all rows in the column family you request.
65
- def remove_all(column_family)
66
- get_key_range(column_family).each do |key|
67
- remove(key, column_family)
68
- end
69
- end
70
-
71
- ## Read
72
-
73
- # Count the elements at the column_family:key:super_column path you
74
- # request.
75
- def count_columns(key, column_family, super_column = nil)
76
- column_family = column_family.to_s
77
- column_family += ":#{super_column}" if super_column
78
- @client.get_column_count(@name, key, column_family)
79
- end
80
-
81
- # Return a list of single values for the elements at the
82
- # column_family:key:super_column:column path you request.
83
- def get_columns(key, column_family, super_columns, columns = nil)
84
- column_family = column_family.to_s
85
- get_slice_by_names = (is_super(column_family) && !columns) ? :get_slice_super_by_names : :get_slice_by_names
86
- if super_columns and columns
87
- column_family += ":#{super_columns}"
88
- columns = Array(columns)
89
- else
90
- columns = Array(super_columns)
91
- end
92
-
93
- hash = columns_to_hash(@client.send(get_slice_by_names, @name, key, column_family, columns))
94
- columns.map { |column| hash[column] }
95
- end
96
-
97
- # Return a hash (actually, a CassandraClient::OrderedHash) or a single value
98
- # representing the element at the column_family:key:super_column:column
99
- # path you request.
100
- def get(key, column_family, super_column = nil, column = nil, offset = -1, limit = 100)
101
- column_family = column_family.to_s
102
- column_family += ":#{super_column}" if super_column
103
- column_family += ":#{column}" if column
104
-
105
- # You have got to be kidding
106
- if is_super(column_family)
107
- if column
108
- load(@client.get_column(@name, key, column_family).value)
109
- elsif super_column
110
- columns_to_hash(@client.get_superColumn(@name, key, column_family).columns)
111
- else
112
- columns_to_hash(@client.get_slice_super(@name, key, "#{column_family}:", offset, limit))
113
- end
114
- else
115
- if super_column
116
- load(@client.get_column(@name, key, column_family).value)
117
- elsif is_sorted_by_time(column_family)
118
- result = columns_to_hash(@client.get_columns_since(@name, key, column_family, 0))
119
-
120
- # FIXME Hack until get_slice on a time-sorted column family works again
121
- result = OrderedHash[*flatten_once(result.to_a[offset, limit])] if offset > -1
122
- result
123
- else
124
- columns_to_hash(@client.get_slice(@name, key, "#{column_family}:", offset, limit))
125
- end
126
- end
127
- rescue NotFoundException
128
- is_super(column_family) && !column ? {} : nil
129
- end
130
-
131
- # FIXME
132
- # def get_recent(key, column_family, super_column = nil, column = nil, timestamp = 0)
133
- # end
134
-
135
- # Return a list of keys in the column_family you request. Requires the
136
- # table to be partitioned with OrderPreservingHash.
137
- def get_key_range(key_range, column_family = nil, limit = 100)
138
- column_family, key_range = key_range, ''..'' unless column_family
139
- column_families = Array(column_family).map {|c| c.to_s}
140
- @client.get_key_range(@name, column_families, key_range.begin, key_range.end, limit)
141
- end
142
-
143
- # Count all rows in the column_family you request. Requires the table
144
- # to be partitioned with OrderPreservingHash.
145
- def count(key_range, column_family = nil, limit = MAX_INT)
146
- get_key_range(key_range, column_family, limit).size
147
- end
148
-
149
- private
150
-
151
- def is_super(column_family)
152
- column_family_property(column_family, 'type') == 'Super'
153
- end
154
-
155
- def is_sorted_by_time(column_family)
156
- column_family_property(column_family, 'sort') == 'Time'
157
- end
158
-
159
- def column_family_property(column_family_or_path, key)
160
- column_family = column_family_or_path.to_s.split(':').first
161
- @schema[column_family][key]
162
- rescue NoMethodError
163
- raise AccessError, "Invalid column family \":#{column_family}\""
164
- end
165
-
166
- def columns_to_hash(columns)
167
- hash = ::CassandraClient::OrderedHash.new
168
- Array(columns).each do |c|
169
- if c.is_a?(SuperColumn_t)
170
- hash[c.name] = columns_to_hash(c.columns)
171
- else
172
- hash[c.columnName] = load(c.value)
173
- end
174
- end
175
- hash
176
- end
177
-
178
- def hash_to_columns(hash, timestamp)
179
- hash.map do |column, value|
180
- Column_t.new(:columnName => column, :value => dump(value), :timestamp => timestamp)
181
- end
182
- end
183
-
184
- def hash_to_super_columns(hash, timestamp)
185
- hash.map do |super_column, columns|
186
- SuperColumn_t.new(:name => super_column, :columns => hash_to_columns(columns, timestamp))
187
- end
188
- end
189
-
190
- def time_in_microseconds
191
- time = Time.now
192
- time.to_i * 1_000_000 + time.usec
193
- end
194
- alias :now :time_in_microseconds
195
-
196
- def flatten_once(array)
197
- result = []
198
- array.each { |el| result.concat(el) }
199
- result
200
- end
201
- end
202
- end