cassandra 0.7.1 → 0.7.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,3 +1,5 @@
1
+ v0.7.2 Switch to newly-extraced simple_uuid gem, minor bugfixes.
2
+
1
3
  v0.7.1 update thrift-generated code to 0.5
2
4
 
3
5
  v0.7 Various improvements.
data/Manifest CHANGED
@@ -1,7 +1,7 @@
1
1
  CHANGELOG
2
2
  LICENSE
3
3
  Manifest
4
- README
4
+ README.mkd
5
5
  Rakefile
6
6
  bin/cassandra_helper
7
7
  conf/cassandra.in.sh
@@ -18,9 +18,9 @@ lib/cassandra/long.rb
18
18
  lib/cassandra/ordered_hash.rb
19
19
  lib/cassandra/protocol.rb
20
20
  lib/cassandra/time.rb
21
- lib/cassandra/uuid.rb
22
21
  test/cassandra_test.rb
23
22
  test/comparable_types_test.rb
23
+ test/ordered_hash_test.rb
24
24
  test/test_helper.rb
25
25
  vendor/gen-rb/cassandra.rb
26
26
  vendor/gen-rb/cassandra_constants.rb
data/README.mkd ADDED
@@ -0,0 +1,72 @@
1
+ # cassandra
2
+
3
+ A Ruby client for the Cassandra distributed database.
4
+
5
+ ## License
6
+
7
+ Copyright 2009 Twitter, Inc. See included LICENSE file. Portions copyright 2004-2009 David Heinemeier Hansson, and used with permission.
8
+
9
+ ## Features
10
+
11
+ * clean encapsulation of the Thrift API
12
+ * compatible UUID and Long classes, for GUID generation
13
+ * Ruby 1.9 compatibility
14
+
15
+ The Github source repository is [here](http://github.com/fauna/cassandra/). Patches and contributions are very welcome.
16
+
17
+ ## Installation
18
+
19
+ You need Ruby 1.8 or 1.9. If you have those, just run:
20
+
21
+ sudo gem install cassandra
22
+
23
+ Cassandra itself is a rapidly moving target. In order to get a working server, use the `bin/cassandra_helper` script:
24
+
25
+ cassandra_helper cassandra
26
+
27
+ A server will be installed in `$HOME/cassandra/server`, and started in debug mode.
28
+
29
+ WARNING: Don't use the test folder for your data, as it will get overwritten when you update the gem.
30
+
31
+ ## Usage
32
+
33
+ Now, start IRb and require the library:
34
+
35
+ require 'cassandra'
36
+
37
+ Connect to a server and keyspace:
38
+
39
+ client = Cassandra.new('Twitter', '127.0.0.1:9160')
40
+
41
+ Insert into a column family. You can insert a `Cassandra::OrderedHash`, or a regular Hash, if order doesn't matter:
42
+
43
+ client.insert(:Users, "5", {'screen_name' => "buttonscat"})
44
+
45
+ Insert into a super column family:
46
+
47
+ client.insert(:UserRelationships, "5", {"user_timeline" => {UUID.new => "1"}})
48
+
49
+ Query a super column:
50
+
51
+ timeline = client.get(:UserRelationships, "5", "user_timeline")
52
+
53
+ The returned result will always be a Cassandra::OrderedHash.
54
+
55
+ See Cassandra for more methods.
56
+
57
+ ## Configuration
58
+
59
+ By default, cassandra is setup to listen on localhost. If you want to move your clients to another host, you're going to need to change which interface it binds to in the storage-conf.xml. You should also change the seed address.
60
+
61
+ ## Node Auto-Discovery
62
+
63
+ The list of hosts you pass to the client is only used to auto-discover all the nodes in your cluster. You don't need to give the client a list of all of your nodes.
64
+
65
+ ## Further reading
66
+
67
+ * [Up and Running With Cassandra](http://blog.evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra)
68
+
69
+ ## Reporting problems
70
+
71
+ The Github issue tracker is [here](http://github.com/fauna/cassandra/issues). If you have problems with this library or Cassandra itself, please use the [cassandra-user mailing list](http://mail-archives.apache.org/mod_mbox/incubator-cassandra-user/).
72
+
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  unless ENV['FROM_BIN_CASSANDRA_HELPER']
3
2
  require 'rubygems'
4
3
  require 'echoe'
@@ -8,7 +7,7 @@ unless ENV['FROM_BIN_CASSANDRA_HELPER']
8
7
  p.project = "fauna"
9
8
  p.summary = "A Ruby client for the Cassandra distributed database."
10
9
  p.rubygems_version = ">= 0.8"
11
- p.dependencies = ['thrift_client', 'json', 'rake']
10
+ p.dependencies = ['thrift_client', 'json', 'rake', ['simple_uuid', '>= 0.0.2']]
12
11
  p.ignore_pattern = /^(data|vendor\/cassandra|cassandra|vendor\/thrift)/
13
12
  p.rdoc_pattern = /^(lib|bin|tasks|ext)|^README|^CHANGELOG|^TODO|^LICENSE|^COPYING$/
14
13
  p.url = "http://blog.evanweaver.com/files/doc/fauna/cassandra/"
@@ -16,7 +15,7 @@ unless ENV['FROM_BIN_CASSANDRA_HELPER']
16
15
  end
17
16
  end
18
17
 
19
- REVISION = "c4cc3505855c157a0887611cd9abe6f996bde345"
18
+ REVISION = "450cfa10f0b82d9d5af9ffda182a5097afee402b"
20
19
 
21
20
  PATCHES = []
22
21
 
data/cassandra.gemspec CHANGED
@@ -2,26 +2,26 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{cassandra}
5
- s.version = "0.7.1"
5
+ s.version = "0.7.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/ryan/.gemkeys/gem-public_cert.pem"]
10
- s.date = %q{2010-01-11}
10
+ s.date = %q{2010-01-25}
11
11
  s.default_executable = %q{cassandra_helper}
12
12
  s.description = %q{A Ruby client for the Cassandra distributed database.}
13
13
  s.email = %q{}
14
14
  s.executables = ["cassandra_helper"]
15
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "lib/cassandra/uuid.rb"]
16
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "bin/cassandra_helper", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "lib/cassandra/uuid.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/test_helper.rb", "vendor/gen-rb/cassandra.rb", "vendor/gen-rb/cassandra_constants.rb", "vendor/gen-rb/cassandra_types.rb", "cassandra.gemspec"]
15
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README.mkd", "bin/cassandra_helper", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb"]
16
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README.mkd", "Rakefile", "bin/cassandra_helper", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "lib/cassandra.rb", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/debug.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/time.rb", "test/cassandra_test.rb", "test/comparable_types_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb", "vendor/gen-rb/cassandra.rb", "vendor/gen-rb/cassandra_constants.rb", "vendor/gen-rb/cassandra_types.rb", "cassandra.gemspec"]
17
17
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/cassandra/}
18
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cassandra", "--main", "README"]
18
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cassandra", "--main", "README.mkd"]
19
19
  s.require_paths = ["lib"]
20
20
  s.rubyforge_project = %q{fauna}
21
21
  s.rubygems_version = %q{1.3.5}
22
22
  s.signing_key = %q{/Users/ryan/.gemkeys/gem-private_key.pem}
23
23
  s.summary = %q{A Ruby client for the Cassandra distributed database.}
24
- s.test_files = ["test/cassandra_test.rb", "test/comparable_types_test.rb", "test/test_helper.rb"]
24
+ s.test_files = ["test/cassandra_test.rb", "test/comparable_types_test.rb", "test/ordered_hash_test.rb", "test/test_helper.rb"]
25
25
 
26
26
  if s.respond_to? :specification_version then
27
27
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -31,14 +31,17 @@ Gem::Specification.new do |s|
31
31
  s.add_runtime_dependency(%q<thrift_client>, [">= 0"])
32
32
  s.add_runtime_dependency(%q<json>, [">= 0"])
33
33
  s.add_runtime_dependency(%q<rake>, [">= 0"])
34
+ s.add_runtime_dependency(%q<simple_uuid>, [">= 0.0.2"])
34
35
  else
35
36
  s.add_dependency(%q<thrift_client>, [">= 0"])
36
37
  s.add_dependency(%q<json>, [">= 0"])
37
38
  s.add_dependency(%q<rake>, [">= 0"])
39
+ s.add_dependency(%q<simple_uuid>, [">= 0.0.2"])
38
40
  end
39
41
  else
40
42
  s.add_dependency(%q<thrift_client>, [">= 0"])
41
43
  s.add_dependency(%q<json>, [">= 0"])
42
44
  s.add_dependency(%q<rake>, [">= 0"])
45
+ s.add_dependency(%q<simple_uuid>, [">= 0.0.2"])
43
46
  end
44
47
  end
@@ -38,6 +38,7 @@
38
38
  <ColumnFamily CompareWith="UTF8Type" Name="Statuses" />
39
39
  <ColumnFamily CompareWith="UTF8Type" Name="StatusAudits" />
40
40
  <ColumnFamily CompareWith="UTF8Type" CompareSubcolumnsWith="TimeUUIDType" ColumnType="Super" Name="StatusRelationships" />
41
+ <ColumnFamily CompareWith="UTF8Type" ColumnType="Super" Name="Index" />
41
42
  </Keyspace>
42
43
 
43
44
  <Keyspace Name="Multiblog">
data/lib/cassandra.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'thrift_client'
3
3
  require 'json'
4
-
4
+ require 'simple_uuid'
5
5
  here = File.expand_path(File.dirname(__FILE__))
6
6
 
7
7
  $LOAD_PATH << "#{here}/../vendor/gen-rb"
@@ -11,7 +11,6 @@ $LOAD_PATH << "#{here}"
11
11
  require 'cassandra/array'
12
12
  require 'cassandra/time'
13
13
  require 'cassandra/comparable'
14
- require 'cassandra/uuid'
15
14
  require 'cassandra/long'
16
15
  require 'cassandra/ordered_hash'
17
16
  require 'cassandra/columns'
@@ -2,7 +2,7 @@
2
2
  =begin rdoc
3
3
  Create a new Cassandra client instance. Accepts a keyspace name, and optional host and port.
4
4
 
5
- client = Cassandra.new('twitter', '127.0.0.1', 9160)
5
+ client = Cassandra.new('twitter', '127.0.0.1:9160')
6
6
 
7
7
  You can then make calls to the server via the <tt>client</tt> instance.
8
8
 
@@ -68,7 +68,6 @@ class Cassandra
68
68
  @servers = Array(servers)
69
69
  end
70
70
 
71
-
72
71
  def client
73
72
  return @client if defined?(@client)
74
73
  client!
@@ -83,7 +83,7 @@ class Cassandra
83
83
  :columns => sub_columns.collect { |sub_column_name, sub_column_value|
84
84
  CassandraThrift::Column.new(
85
85
  :name => sub_column_name_class(column_family).new(sub_column_name).to_s,
86
- :value => sub_column_value,
86
+ :value => sub_column_value.to_s,
87
87
  :timestamp => timestamp
88
88
  )
89
89
  }
@@ -1,44 +1,39 @@
1
-
1
+ # OrderedHash is namespaced to prevent conflicts with other implementations
2
2
  class Cassandra
3
3
  # Hash is ordered in Ruby 1.9!
4
4
  if RUBY_VERSION >= '1.9'
5
5
  OrderedHash = ::Hash
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 #:nodoc: all
29
- require 'enumerator'
30
-
31
- def self.[](*array)
32
- hash = new
33
- array.each_slice(2) { |key, value| hash[key] = value }
34
- hash
35
- end
36
-
6
+ else
7
+ class OrderedHash < Hash #:nodoc:
37
8
  def initialize(*args, &block)
38
9
  super
39
10
  @keys = []
40
11
  end
41
12
 
13
+ def self.[](*args)
14
+ ordered_hash = new
15
+
16
+ if (args.length == 1 && args.first.is_a?(Array))
17
+ args.first.each do |key_value_pair|
18
+ next unless (key_value_pair.is_a?(Array))
19
+ ordered_hash[key_value_pair[0]] = key_value_pair[1]
20
+ end
21
+
22
+ return ordered_hash
23
+ end
24
+
25
+ unless (args.size % 2 == 0)
26
+ raise ArgumentError.new("odd number of arguments for Hash")
27
+ end
28
+
29
+ args.each_with_index do |val, ind|
30
+ next if (ind % 2 != 0)
31
+ ordered_hash[val] = args[ind + 1]
32
+ end
33
+
34
+ ordered_hash
35
+ end
36
+
42
37
  def initialize_copy(other)
43
38
  super
44
39
  # make a deep copy of keys
@@ -86,6 +81,10 @@ class Cassandra
86
81
  self
87
82
  end
88
83
 
84
+ def to_a
85
+ @keys.map { |key| [ key, self[key] ] }
86
+ end
87
+
89
88
  def each_key
90
89
  @keys.each { |key| yield key }
91
90
  end
@@ -121,6 +120,13 @@ class Cassandra
121
120
  dup.merge!(other_hash)
122
121
  end
123
122
 
123
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
124
+ def replace(other)
125
+ super
126
+ @keys = other.keys
127
+ self
128
+ end
129
+
124
130
  def inspect
125
131
  "#<OrderedHash #{super}>"
126
132
  end
@@ -132,4 +138,4 @@ class Cassandra
132
138
  end
133
139
  end
134
140
  end
135
- end
141
+ end
@@ -4,7 +4,7 @@ class CassandraTest < Test::Unit::TestCase
4
4
  include Cassandra::Constants
5
5
 
6
6
  def setup
7
- @twitter = Cassandra.new('Twitter', "127.0.0.1:9160", :retries => 2)
7
+ @twitter = Cassandra.new('Twitter', "127.0.0.1:9160", :retries => 2, :exception_classes => [])
8
8
  @twitter.clear_keyspace!
9
9
 
10
10
  @blogs = Cassandra.new('Multiblog')
@@ -322,6 +322,10 @@ class CassandraTest < Test::Unit::TestCase
322
322
  end
323
323
  end
324
324
 
325
+ def test_nil_sub_column_value
326
+ @twitter.insert(:Index, 'asdf', {"thing" => {'jkl' => nil} })
327
+ end
328
+
325
329
  private
326
330
 
327
331
  def key
@@ -8,44 +8,34 @@ class ComparableTypesTest < Test::Unit::TestCase
8
8
  10.times { ary << Long.new }
9
9
  assert_equal ary.sort, ary
10
10
  end
11
-
11
+
12
12
  def test_long_equality
13
13
  long = Long.new
14
- assert_equal long, Long.new(long)
15
- assert_equal long, Long.new(long.to_s)
16
- assert_equal long, Long.new(long.to_i)
17
- assert_equal long, Long.new(long.to_guid)
14
+ assert_equal long, Long.new(long)
15
+ assert_equal long, Long.new(long.to_s)
16
+ assert_equal long, Long.new(long.to_i)
17
+ assert_equal long, Long.new(long.to_guid)
18
18
  end
19
-
19
+
20
20
  def test_long_error
21
21
  assert_raises(Cassandra::Comparable::TypeError) do
22
22
  Long.new("bogus")
23
23
  end
24
24
  end
25
25
 
26
- def test_uuid_sort
27
- ary = []
28
- 5.times { ary << UUID.new(Time.at(rand(2**31))) }
29
- assert_equal ary.map { |_| _.seconds }.sort, ary.sort.map { |_| _.seconds }
30
- assert_not_equal ary.sort, ary.sort_by {|_| _.to_guid }
31
- end
32
-
33
- def test_uuid_equality
34
- uuid = UUID.new
35
- assert_equal uuid, UUID.new(uuid)
36
- assert_equal uuid, UUID.new(uuid.to_s)
37
- assert_equal uuid, UUID.new(uuid.to_i)
38
- assert_equal uuid, UUID.new(uuid.to_guid)
26
+ def test_types_behave_well
27
+ assert !(Long.new() == false)
39
28
  end
40
-
41
- def test_uuid_error
29
+
30
+ def test_casting_unknown_class
42
31
  assert_raises(Cassandra::Comparable::TypeError) do
43
- UUID.new("bogus")
32
+ Cassandra::Long.new({})
44
33
  end
45
34
  end
46
-
47
- def test_types_behave_well
48
- assert !(UUID.new() == false)
49
- assert !(Long.new() == false)
35
+
36
+ def test_long_inspect
37
+ obj = Long.new("\000\000\000\000\000\000\000\000")
38
+ assert_equal "<Cassandra::Long##{obj.object_id} time: Wed Dec 31 16:00:00 -0800 1969, usecs: 0, jitter: 0, guid: 00000000-0000-0000>", obj.inspect
50
39
  end
40
+
51
41
  end
@@ -0,0 +1,201 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class OrderedHashTest < Test::Unit::TestCase
4
+ def setup
5
+ @keys = %w( blue green red pink orange )
6
+ @values = %w( 000099 009900 aa0000 cc0066 cc6633 )
7
+ @hash = Hash.new
8
+ @ordered_hash = Cassandra::OrderedHash.new
9
+
10
+ @keys.each_with_index do |key, index|
11
+ @hash[key] = @values[index]
12
+ @ordered_hash[key] = @values[index]
13
+ end
14
+ end
15
+
16
+ def test_order
17
+ assert_equal @keys, @ordered_hash.keys
18
+ assert_equal @values, @ordered_hash.values
19
+ end
20
+
21
+ def test_access
22
+ assert @hash.all? { |k, v| @ordered_hash[k] == v }
23
+ end
24
+
25
+ def test_assignment
26
+ key, value = 'purple', '5422a8'
27
+
28
+ @ordered_hash[key] = value
29
+ assert_equal @keys.length + 1, @ordered_hash.length
30
+ assert_equal key, @ordered_hash.keys.last
31
+ assert_equal value, @ordered_hash.values.last
32
+ assert_equal value, @ordered_hash[key]
33
+ end
34
+
35
+ def test_delete
36
+ key, value = 'white', 'ffffff'
37
+ bad_key = 'black'
38
+
39
+ @ordered_hash[key] = value
40
+ assert_equal @keys.length + 1, @ordered_hash.length
41
+ assert_equal @ordered_hash.keys.length, @ordered_hash.length
42
+
43
+ assert_equal value, @ordered_hash.delete(key)
44
+ assert_equal @keys.length, @ordered_hash.length
45
+ assert_equal @ordered_hash.keys.length, @ordered_hash.length
46
+
47
+ assert_nil @ordered_hash.delete(bad_key)
48
+ end
49
+
50
+ def test_to_hash
51
+ assert_same @ordered_hash, @ordered_hash.to_hash
52
+ end
53
+
54
+ def test_to_a
55
+ assert_equal @keys.zip(@values), @ordered_hash.to_a
56
+ end
57
+
58
+ def test_has_key
59
+ assert_equal true, @ordered_hash.has_key?('blue')
60
+ assert_equal true, @ordered_hash.key?('blue')
61
+ assert_equal true, @ordered_hash.include?('blue')
62
+ assert_equal true, @ordered_hash.member?('blue')
63
+
64
+ assert_equal false, @ordered_hash.has_key?('indigo')
65
+ assert_equal false, @ordered_hash.key?('indigo')
66
+ assert_equal false, @ordered_hash.include?('indigo')
67
+ assert_equal false, @ordered_hash.member?('indigo')
68
+ end
69
+
70
+ def test_has_value
71
+ assert_equal true, @ordered_hash.has_value?('000099')
72
+ assert_equal true, @ordered_hash.value?('000099')
73
+ assert_equal false, @ordered_hash.has_value?('ABCABC')
74
+ assert_equal false, @ordered_hash.value?('ABCABC')
75
+ end
76
+
77
+ def test_each_key
78
+ keys = []
79
+ @ordered_hash.each_key { |k| keys << k }
80
+ assert_equal @keys, keys
81
+ end
82
+
83
+ def test_each_value
84
+ values = []
85
+ @ordered_hash.each_value { |v| values << v }
86
+ assert_equal @values, values
87
+ end
88
+
89
+ def test_each
90
+ values = []
91
+ @ordered_hash.each {|key, value| values << value}
92
+ assert_equal @values, values
93
+ end
94
+
95
+ def test_each_with_index
96
+ @ordered_hash.each_with_index { |pair, index| assert_equal [@keys[index], @values[index]], pair}
97
+ end
98
+
99
+ def test_each_pair
100
+ values = []
101
+ keys = []
102
+ @ordered_hash.each_pair do |key, value|
103
+ keys << key
104
+ values << value
105
+ end
106
+ assert_equal @values, values
107
+ assert_equal @keys, keys
108
+ end
109
+
110
+ def test_delete_if
111
+ copy = @ordered_hash.dup
112
+ copy.delete('pink')
113
+ assert_equal copy, @ordered_hash.delete_if { |k, _| k == 'pink' }
114
+ assert !@ordered_hash.keys.include?('pink')
115
+ end
116
+
117
+ def test_reject!
118
+ (copy = @ordered_hash.dup).delete('pink')
119
+ @ordered_hash.reject! { |k, _| k == 'pink' }
120
+ assert_equal copy, @ordered_hash
121
+ assert !@ordered_hash.keys.include?('pink')
122
+ end
123
+
124
+ def test_reject
125
+ copy = @ordered_hash.dup
126
+ new_ordered_hash = @ordered_hash.reject { |k, _| k == 'pink' }
127
+ assert_equal copy, @ordered_hash
128
+ assert !new_ordered_hash.keys.include?('pink')
129
+ assert @ordered_hash.keys.include?('pink')
130
+ end
131
+
132
+ def test_clear
133
+ @ordered_hash.clear
134
+ assert_equal [], @ordered_hash.keys
135
+ end
136
+
137
+ def test_merge
138
+ other_hash = Cassandra::OrderedHash.new
139
+ other_hash['purple'] = '800080'
140
+ other_hash['violet'] = 'ee82ee'
141
+ merged = @ordered_hash.merge other_hash
142
+ assert_equal merged.length, @ordered_hash.length + other_hash.length
143
+ assert_equal @keys + ['purple', 'violet'], merged.keys
144
+
145
+ @ordered_hash.merge! other_hash
146
+ assert_equal @ordered_hash, merged
147
+ assert_equal @ordered_hash.keys, merged.keys
148
+ end
149
+
150
+ def test_shift
151
+ pair = @ordered_hash.shift
152
+ assert_equal [@keys.first, @values.first], pair
153
+ assert !@ordered_hash.keys.include?(pair.first)
154
+ end
155
+
156
+ def test_keys
157
+ original = @ordered_hash.keys.dup
158
+ @ordered_hash.keys.pop
159
+ assert_equal original, @ordered_hash.keys
160
+ end
161
+
162
+ def test_inspect
163
+ assert @ordered_hash.inspect.include?(@hash.inspect)
164
+ end
165
+
166
+ def test_alternate_initialization_with_splat
167
+ alternate = Cassandra::OrderedHash[1,2,3,4]
168
+ assert_kind_of Cassandra::OrderedHash, alternate
169
+ assert_equal [1, 3], alternate.keys
170
+ end
171
+
172
+ def test_alternate_initialization_with_array
173
+ alternate = Cassandra::OrderedHash[ [
174
+ [1, 2],
175
+ [3, 4],
176
+ "bad key value pair",
177
+ [ 'missing value' ]
178
+ ]]
179
+
180
+ assert_kind_of Cassandra::OrderedHash, alternate
181
+ assert_equal [1, 3, 'missing value'], alternate.keys
182
+ assert_equal [2, 4, nil ], alternate.values
183
+ end
184
+
185
+ def test_alternate_initialization_raises_exception_on_odd_length_args
186
+ begin
187
+ alternate = Cassandra::OrderedHash[1,2,3,4,5]
188
+ flunk "Hash::[] should have raised an exception on initialization " +
189
+ "with an odd number of parameters"
190
+ rescue
191
+ assert_equal "odd number of arguments for Hash", $!.message
192
+ end
193
+ end
194
+
195
+ def test_replace_updates_keys
196
+ @other_ordered_hash = Cassandra::OrderedHash[:black, '000000', :white, '000000']
197
+ original = @ordered_hash.replace(@other_ordered_hash)
198
+ assert_same original, @ordered_hash
199
+ assert_equal @other_ordered_hash.keys, @ordered_hash.keys
200
+ end
201
+ end
data/test/test_helper.rb CHANGED
@@ -4,7 +4,7 @@ require "#{File.expand_path(File.dirname(__FILE__))}/../lib/cassandra"
4
4
  begin; require 'ruby-debug'; rescue LoadError; end
5
5
 
6
6
  begin
7
- @test_client = Cassandra.new('Twitter')
7
+ @test_client = Cassandra.new('Twitter', 'localhost:9160', {:exception_classes => []})
8
8
  rescue Thrift::TransportException => e
9
9
  #FIXME Make server automatically start if not running
10
10
  if e.message =~ /Could not connect/
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Weaver
@@ -30,7 +30,7 @@ cert_chain:
30
30
  zyKMYVRO0z/58g==
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2010-01-11 00:00:00 -08:00
33
+ date: 2010-01-25 00:00:00 -08:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -63,6 +63,16 @@ dependencies:
63
63
  - !ruby/object:Gem::Version
64
64
  version: "0"
65
65
  version:
66
+ - !ruby/object:Gem::Dependency
67
+ name: simple_uuid
68
+ type: :runtime
69
+ version_requirement:
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 0.0.2
75
+ version:
66
76
  description: A Ruby client for the Cassandra distributed database.
67
77
  email: ""
68
78
  executables:
@@ -72,7 +82,7 @@ extensions: []
72
82
  extra_rdoc_files:
73
83
  - CHANGELOG
74
84
  - LICENSE
75
- - README
85
+ - README.mkd
76
86
  - bin/cassandra_helper
77
87
  - lib/cassandra.rb
78
88
  - lib/cassandra/array.rb
@@ -85,12 +95,11 @@ extra_rdoc_files:
85
95
  - lib/cassandra/ordered_hash.rb
86
96
  - lib/cassandra/protocol.rb
87
97
  - lib/cassandra/time.rb
88
- - lib/cassandra/uuid.rb
89
98
  files:
90
99
  - CHANGELOG
91
100
  - LICENSE
92
101
  - Manifest
93
- - README
102
+ - README.mkd
94
103
  - Rakefile
95
104
  - bin/cassandra_helper
96
105
  - conf/cassandra.in.sh
@@ -107,9 +116,9 @@ files:
107
116
  - lib/cassandra/ordered_hash.rb
108
117
  - lib/cassandra/protocol.rb
109
118
  - lib/cassandra/time.rb
110
- - lib/cassandra/uuid.rb
111
119
  - test/cassandra_test.rb
112
120
  - test/comparable_types_test.rb
121
+ - test/ordered_hash_test.rb
113
122
  - test/test_helper.rb
114
123
  - vendor/gen-rb/cassandra.rb
115
124
  - vendor/gen-rb/cassandra_constants.rb
@@ -126,7 +135,7 @@ rdoc_options:
126
135
  - --title
127
136
  - Cassandra
128
137
  - --main
129
- - README
138
+ - README.mkd
130
139
  require_paths:
131
140
  - lib
132
141
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -151,4 +160,5 @@ summary: A Ruby client for the Cassandra distributed database.
151
160
  test_files:
152
161
  - test/cassandra_test.rb
153
162
  - test/comparable_types_test.rb
163
+ - test/ordered_hash_test.rb
154
164
  - test/test_helper.rb
metadata.gz.sig CHANGED
Binary file
data/README DELETED
@@ -1,64 +0,0 @@
1
- cassandra
2
-
3
- A Ruby client for the Cassandra distributed database.
4
-
5
- == License
6
-
7
- Copyright 2009 Twitter, Inc. See included LICENSE file. Portions copyright 2004-2009 David Heinemeier Hansson, and used with permission.
8
-
9
- The public certificate for this gem is here[http://rubyforge.org/frs/download.php/25331/evan_weaver-original-public_cert.pem].
10
-
11
- == Features
12
-
13
- * clean encapsulation of the Thrift API
14
- * compatible UUID and Long classes, for GUID generation
15
- * Ruby 1.9 compatibility
16
-
17
- The Github source repository is {here}[http://github.com/fauna/cassandra/]. Patches and contributions are very welcome.
18
-
19
- == Installation
20
-
21
- You need Ruby 1.8 or 1.9. If you have those, just run:
22
-
23
- sudo gem install cassandra
24
-
25
- Cassandra itself is a rapidly moving target. In order to get a working server, use the <tt>bin/cassandra_helper</tt> script:
26
-
27
- cassandra_helper cassandra
28
-
29
- A server will be installed in <tt>$HOME/cassandra/server</tt>, and started in debug mode.
30
-
31
- == Usage
32
-
33
- Now, start IRb and require the library:
34
-
35
- require 'cassandra'
36
-
37
- Connect to a server and keyspace:
38
-
39
- client = Cassandra.new('Twitter', '127.0.0.1:9160')
40
-
41
- Insert into a column family. You can insert a Cassandra::OrderedHash, or a regular Hash, if order doesn't matter:
42
-
43
- client.insert(:Users, "5", {'screen_name' => "buttonscat"})
44
-
45
- Insert into a super column family:
46
-
47
- client.insert(:UserRelationships, "5", {"user_timeline" => {UUID.new => "1"}})
48
-
49
- Query a super column:
50
-
51
- timeline = client.get(:UserRelationships, "5", "user_timeline")
52
-
53
- The returned result will always be a Cassandra::OrderedHash.
54
-
55
- See Cassandra for more methods.
56
-
57
- == Further reading
58
-
59
- * {Up and Running With Cassandra}[http://blog.evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra]
60
-
61
- == Reporting problems
62
-
63
- The Github issue tracker is {here}[http://github.com/fauna/cassandra/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/].
64
-
@@ -1,115 +0,0 @@
1
-
2
- class Cassandra
3
-
4
- # UUID format version 1, as specified in RFC 4122, with jitter in place of the mac address and sequence counter.
5
- class UUID < Comparable
6
-
7
- class InvalidVersion < StandardError #:nodoc:
8
- end
9
-
10
- GREGORIAN_EPOCH_OFFSET = 0x01B2_1DD2_1381_4000 # Oct 15, 1582
11
-
12
- VARIANT = 0b1000_0000_0000_0000
13
-
14
- def initialize(bytes = nil)
15
- case bytes
16
- when self.class # UUID
17
- @bytes = bytes.to_s
18
- when String
19
- case bytes.size
20
- when 16 # Raw byte array
21
- @bytes = bytes
22
- when 36 # Human-readable UUID representation; inverse of #to_guid
23
- elements = bytes.split("-")
24
- raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (malformed UUID representation)" if elements.size != 5
25
- @bytes = elements.join.to_a.pack('H32')
26
- else
27
- raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (invalid bytecount)"
28
- end
29
-
30
- when Integer
31
- raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (integer out of range)" if bytes < 0 or bytes > 2**128
32
- @bytes = [
33
- (bytes >> 96) & 0xFFFF_FFFF,
34
- (bytes >> 64) & 0xFFFF_FFFF,
35
- (bytes >> 32) & 0xFFFF_FFFF,
36
- bytes & 0xFFFF_FFFF
37
- ].pack("NNNN")
38
-
39
- when NilClass, Time
40
- time = (bytes || Time).stamp * 10 + GREGORIAN_EPOCH_OFFSET
41
- # See http://github.com/spectra/ruby-uuid/
42
- @bytes = [
43
- time & 0xFFFF_FFFF,
44
- time >> 32,
45
- ((time >> 48) & 0x0FFF) | 0x1000,
46
- # Top 3 bytes reserved
47
- rand(2**13) | VARIANT,
48
- rand(2**16),
49
- rand(2**32)
50
- ].pack("NnnnnN")
51
-
52
- else
53
- raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (unknown source class)"
54
- end
55
- end
56
-
57
- def to_i
58
- ints = @bytes.unpack("NNNN")
59
- (ints[0] << 96) +
60
- (ints[1] << 64) +
61
- (ints[2] << 32) +
62
- ints[3]
63
- end
64
-
65
- def version
66
- time_high = @bytes.unpack("NnnQ")[2]
67
- version = (time_high & 0xF000).to_s(16)[0].chr.to_i
68
- version > 0 and version < 6 ? version : -1
69
- end
70
-
71
- def variant
72
- @bytes.unpack('QnnN')[1] >> 13
73
- end
74
-
75
- def to_guid
76
- elements = @bytes.unpack("NnnCCa6")
77
- node = elements[-1].unpack('C*')
78
- elements[-1] = '%02x%02x%02x%02x%02x%02x' % node
79
- "%08x-%04x-%04x-%02x%02x-%s" % elements
80
- end
81
-
82
- def seconds
83
- total_usecs / 1_000_000
84
- end
85
-
86
- def usecs
87
- total_usecs % 1_000_000
88
- end
89
-
90
- def <=>(other)
91
- total_usecs <=> other.send(:total_usecs)
92
- end
93
-
94
- def ==(other)
95
- to_s == other.to_s
96
- end
97
-
98
- def inspect(long = false)
99
- "<Cassandra::UUID##{object_id} time: #{
100
- Time.at(seconds).inspect
101
- }, usecs: #{
102
- usecs
103
- } jitter: #{
104
- @bytes.unpack('QQ')[1]
105
- }" + (long ? ", version: #{version}, variant: #{variant}, guid: #{to_guid}>" : ">")
106
- end
107
-
108
- private
109
-
110
- def total_usecs
111
- elements = @bytes.unpack("NnnQ")
112
- (elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
113
- end
114
- end
115
- end