cassandra_client 0.1 → 0.2

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.
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