cassandra 0.5.4 → 0.5.5

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,4 +1,6 @@
1
1
 
2
+ v0.5.5. to_guid for Long. Don't continually re-checkout the Git mirror. Use curl instead of wget, sigh. Use new unified insert API.
3
+
2
4
  v0.5.4. Use wget instead of curl.
3
5
 
4
6
  v0.5.3. Update Multiblog sample schema.
data/Manifest CHANGED
@@ -8,6 +8,7 @@ lib/cassandra/cassandra.rb
8
8
  lib/cassandra/columns.rb
9
9
  lib/cassandra/comparable.rb
10
10
  lib/cassandra/constants.rb
11
+ lib/cassandra/debug.rb
11
12
  lib/cassandra/long.rb
12
13
  lib/cassandra/ordered_hash.rb
13
14
  lib/cassandra/protocol.rb
data/README CHANGED
@@ -27,7 +27,7 @@ Cassandra itself is a rapidly moving target. In order to get a working server, u
27
27
 
28
28
  cassandra_helper cassandra
29
29
 
30
- A server will be installed in <tt>$HOME/cassandra/r$REVISION</tt>, and started in debug mode.
30
+ A server will be installed in <tt>$HOME/cassandra/server</tt>, and started in debug mode.
31
31
 
32
32
  == Usage
33
33
 
data/Rakefile CHANGED
@@ -16,26 +16,28 @@ unless ENV['FROM_BIN_CASSANDRA_HELPER']
16
16
  end
17
17
  end
18
18
 
19
- REVISION = "007df950fc9e9fad255167db74517095a8326f25"
19
+ REVISION = "c4992f48ce9c26ce4fd028240447b4cbe85ecf26"
20
20
 
21
21
  PATCHES = [
22
- "http://issues.apache.org/jira/secure/attachment/12417025/CASSANDRA-377.diff"]
22
+ "http://issues.apache.org/jira/secure/attachment/12417533/388.patch",
23
+ "http://issues.apache.org/jira/secure/attachment/12417682/CASSANDRA-336-code.diff",
24
+ "http://issues.apache.org/jira/secure/attachment/12417683/CASSANDRA-336-thrift.diff"]
23
25
 
24
- CASSANDRA_HOME = "#{ENV['HOME']}/cassandra/r#{REVISION[0, 8]}"
26
+ CASSANDRA_HOME = "#{ENV['HOME']}/cassandra/server"
25
27
 
26
28
  CASSANDRA_TEST = "#{ENV['HOME']}/cassandra/test"
27
29
 
30
+ directory CASSANDRA_TEST
31
+
28
32
  desc "Start Cassandra"
29
- task :cassandra => [:java, :checkout, :patch, :build] do
33
+ task :cassandra => [:build, CASSANDRA_TEST] do
30
34
  # Construct environment
31
35
  env = ""
32
36
  if !ENV["CASSANDRA_INCLUDE"]
33
37
  env << "CASSANDRA_INCLUDE=#{Dir.pwd}/conf/cassandra.in.sh "
34
38
  env << "CASSANDRA_HOME=#{CASSANDRA_HOME} "
35
- env << "CASSANDRA_CONF=#{File.expand_path(File.dirname(__FILE__))}/conf"
36
- end
37
- # Create data dir
38
- Dir.mkdir(CASSANDRA_TEST) if !File.exist?(CASSANDRA_TEST)
39
+ env << "CASSANDRA_CONF=#{File.expand_path(File.dirname(__FILE__))}/conf"
40
+ end
39
41
  # Start server
40
42
  Dir.chdir(CASSANDRA_TEST) do
41
43
  exec("env #{env} #{CASSANDRA_HOME}/bin/cassandra -f")
@@ -53,29 +55,35 @@ task :java do
53
55
  end
54
56
  end
55
57
 
56
- desc "Checkout Cassandra from git"
57
- task :checkout do
58
- # Check git version
58
+ desc "Check Git version"
59
+ task :git do
59
60
  unless `git --version 2>&1` =~ /git version 1.6/
60
61
  puts "You need to install git 1.6."
61
62
  exit(1)
62
63
  end
64
+ end
65
+
66
+ desc "Checkout Cassandra from git"
67
+ task :checkout => [:java, :git] do
63
68
  # Like a git submodule, but all in one more obvious place
64
69
  unless File.exist?(CASSANDRA_HOME)
70
+ puts "Checking Cassandra out from git"
65
71
  cmd = "git clone git://git.apache.org/cassandra.git #{CASSANDRA_HOME}"
66
72
  if !system(cmd)
67
73
  put "Checkout failed. Try:\n #{cmd}"
68
74
  exit(1)
69
75
  end
70
- ENV["RESET"] = "true"
71
- end
76
+ end
72
77
  end
73
78
 
74
79
  desc "Apply patches to Cassandra checkout; use RESET=1 to force"
75
- task :patch do
76
- if ENV["RESET"]
77
- system("rm -rf #{CASSANDRA_TEST}/data")
78
- Dir.chdir(CASSANDRA_HOME) do
80
+ task :patch => [:checkout] do
81
+ # Verify checkout revision and patchset
82
+ Dir.chdir(CASSANDRA_HOME) do
83
+ current_checkout = `git show HEAD~#{PATCHES.size} | head -n1`
84
+ if !current_checkout.include?(REVISION)
85
+ puts "Updating Cassandra and applying patches"
86
+ system("rm -rf #{CASSANDRA_TEST}/data")
79
87
  system("ant clean && git fetch && git reset #{REVISION} --hard")
80
88
  # Delete untracked files, so that the patchs can apply again
81
89
  Array(`git status`[/Untracked files:(.*)$/m, 1].to_s.split("\n")[3..-1]).each do |file|
@@ -83,7 +91,7 @@ task :patch do
83
91
  end
84
92
  # Patch, with a handy commit for each one
85
93
  PATCHES.each do |url|
86
- raise "#{url} failed" unless system("wget -O - #{url} | patch -p1")
94
+ raise "#{url} failed" unless system("curl #{url} | patch -p1")
87
95
  system("git commit -a -m 'Applied patch: #{url.inspect}'")
88
96
  end
89
97
  end
@@ -91,8 +99,9 @@ task :patch do
91
99
  end
92
100
 
93
101
  desc "Rebuild Cassandra"
94
- task :build do
102
+ task :build => [:patch] do
95
103
  unless File.exist?("#{CASSANDRA_HOME}/build")
104
+ puts "Building Cassandra"
96
105
  cmd = "cd #{CASSANDRA_HOME} && ant"
97
106
  if !system(cmd)
98
107
  puts "Could not build Casssandra. Try:\n #{cmd}"
@@ -103,25 +112,27 @@ end
103
112
 
104
113
  desc "Clean Cassandra build"
105
114
  task :clean do
115
+ puts "Cleaning Cassandra"
106
116
  if File.exist?(CASSANDRA_HOME)
107
117
  Dir.chdir(CASSANDRA_HOME) do
108
118
  system("ant clean")
109
119
  end
110
- end
120
+ end
111
121
  end
112
122
 
113
123
  namespace :data do
114
124
  desc "Reset test data"
115
125
  task :reset do
126
+ puts "Resetting test data"
116
127
  system("rm -rf #{CASSANDRA_TEST}/data")
117
128
  end
118
129
  end
119
130
 
120
131
  # desc "Regenerate thrift bindings for Cassandra" # Dev only
121
132
  task :thrift do
133
+ puts "Generating Thrift bindings"
122
134
  system(
123
135
  "cd vendor &&
124
136
  rm -rf gen-rb &&
125
137
  thrift -gen rb #{CASSANDRA_HOME}/interface/cassandra.thrift")
126
138
  end
127
-
@@ -2,18 +2,18 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{cassandra}
5
- s.version = "0.5.4"
5
+ s.version = "0.5.5"
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-08-19}
10
+ s.date = %q{2009-08-27}
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 = ["bin/cassandra_helper", "CHANGELOG", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/safe_client.rb", "lib/cassandra/time.rb", "lib/cassandra/uuid.rb", "lib/cassandra.rb", "LICENSE", "README"]
16
- s.files = ["bin/cassandra_helper", "CHANGELOG", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "lib/cassandra/array.rb", "lib/cassandra/cassandra.rb", "lib/cassandra/columns.rb", "lib/cassandra/comparable.rb", "lib/cassandra/constants.rb", "lib/cassandra/long.rb", "lib/cassandra/ordered_hash.rb", "lib/cassandra/protocol.rb", "lib/cassandra/safe_client.rb", "lib/cassandra/time.rb", "lib/cassandra/uuid.rb", "lib/cassandra.rb", "LICENSE", "Manifest", "Rakefile", "README", "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 = ["bin/cassandra_helper", "CHANGELOG", "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/safe_client.rb", "lib/cassandra/time.rb", "lib/cassandra/uuid.rb", "lib/cassandra.rb", "LICENSE", "README"]
16
+ s.files = ["bin/cassandra_helper", "CHANGELOG", "conf/cassandra.in.sh", "conf/log4j.properties", "conf/storage-conf.xml", "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/safe_client.rb", "lib/cassandra/time.rb", "lib/cassandra/uuid.rb", "lib/cassandra.rb", "LICENSE", "Manifest", "Rakefile", "README", "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"]
17
17
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/cassandra/}
18
18
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cassandra", "--main", "README"]
19
19
  s.require_paths = ["lib"]
@@ -45,6 +45,12 @@
45
45
  <ColumnFamily CompareWith="TimeUUIDType" Name="Blogs"/>
46
46
  <ColumnFamily CompareWith="TimeUUIDType" Name="Comments"/>
47
47
  </Keyspace>
48
+
49
+ <Keyspace Name="MultiblogLong">
50
+ <KeysCachedFraction>0.01</KeysCachedFraction>
51
+ <ColumnFamily CompareWith="LongType" Name="Blogs"/>
52
+ <ColumnFamily CompareWith="LongType" Name="Comments"/>
53
+ </Keyspace>
48
54
  </Keyspaces>
49
55
 
50
56
  <!-- Partitioner: any IPartitioner may be used, including your own
@@ -20,3 +20,4 @@ require 'cassandra/columns'
20
20
  require 'cassandra/protocol'
21
21
  require 'cassandra/cassandra'
22
22
  require 'cassandra/constants'
23
+ require 'cassandra/debug' if ENV['DEBUG']
@@ -3,12 +3,12 @@
3
3
  Create a new Cassandra client instance. Accepts a keyspace name, and optional host and port.
4
4
 
5
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
+
9
9
  client.insert(:UserRelationships, "5", {"user_timeline" => {UUID.new => "1"}})
10
10
  client.get(:UserRelationships, "5", "user_timeline")
11
-
11
+
12
12
  For read methods, valid option parameters are:
13
13
 
14
14
  <tt>:count</tt>:: How many results to return. Defaults to 100.
@@ -18,9 +18,9 @@ For read methods, valid option parameters are:
18
18
  <tt>:consistency</tt>:: The consistency level of the request. Defaults to <tt>Cassandra::Consistency::ONE</tt> (one node must respond). Other valid options are <tt>Cassandra::Consistency::ZERO</tt>, <tt>Cassandra::Consistency::QUORUM</tt>, and <tt>Cassandra::Consistency::ALL</tt>.
19
19
 
20
20
  Note that some read options have no relevance in some contexts.
21
-
21
+
22
22
  For write methods, valid option parameters are:
23
-
23
+
24
24
  <tt>:timestamp </tt>:: The transaction timestamp. Defaults to the current time in milliseconds. This is used for conflict resolution by the server; you normally never need to change it.
25
25
  <tt>:consistency</tt>:: See above.
26
26
 
@@ -38,18 +38,18 @@ class Cassandra
38
38
  end
39
39
 
40
40
  MAX_INT = 2**31 - 1
41
-
42
- WRITE_DEFAULTS = {
41
+
42
+ WRITE_DEFAULTS = {
43
43
  :count => MAX_INT,
44
44
  :timestamp => nil,
45
- :consistency => Consistency::ONE
45
+ :consistency => Consistency::ONE
46
46
  }.freeze
47
47
 
48
48
  READ_DEFAULTS = {
49
- :count => 100,
50
- :start => nil,
51
- :finish => nil,
52
- :reversed => false,
49
+ :count => 100,
50
+ :start => nil,
51
+ :finish => nil,
52
+ :reversed => false,
53
53
  :consistency => Consistency::ONE
54
54
  }.freeze
55
55
 
@@ -91,46 +91,49 @@ class Cassandra
91
91
  # a nested hash for a super column family. Supports the <tt>:consistency</tt>
92
92
  # and <tt>:timestamp</tt> options.
93
93
  def insert(column_family, key, hash, options = {})
94
- column_family, _, _, options = params(column_family, [options], WRITE_DEFAULTS)
94
+ column_family, _, _, options =
95
+ validate_params(column_family, key, [options], WRITE_DEFAULTS)
95
96
 
96
- mutation = if is_super(column_family)
97
- CassandraThrift::BatchMutationSuper.new(
98
- :key => key,
99
- :cfmap => {column_family =>
100
- hash_to_super_columns(column_family, hash, options[:timestamp] || Time.stamp)})
101
- else
102
- CassandraThrift::BatchMutation.new(
103
- :key => key,
104
- :cfmap => {column_family =>
105
- hash_to_columns(column_family, hash, options[:timestamp] || Time.stamp)})
106
- end
107
-
108
- args = [mutation, options[:consistency]]
109
- @batch ? @batch << args : _insert(*args)
97
+ args = [column_family, hash, options[:timestamp] || Time.stamp]
98
+ columns = is_super(column_family) ? hash_to_super_columns(*args) : hash_to_columns(*args)
99
+ mutation = CassandraThrift::BatchMutation.new(
100
+ :key => key,
101
+ :cfmap => {column_family => columns},
102
+ :column_paths => [])
103
+
104
+ @batch ? @batch << mutation : _mutate([mutation], options[:consistency])
110
105
  end
111
106
 
112
107
  ## Delete
113
108
 
114
- # Remove the element at the column_family:key:[column]:[sub_column]
109
+ # _mutate the element at the column_family:key:[column]:[sub_column]
115
110
  # path you request. Supports the <tt>:consistency</tt> and <tt>:timestamp</tt>
116
111
  # options.
117
112
  def remove(column_family, key, *columns_and_options)
118
- column_family, column, sub_column, options = params(column_family, columns_and_options, WRITE_DEFAULTS)
119
- args = [column_family, key, column, sub_column, options[:consistency], options[:timestamp] || Time.stamp]
120
- @batch ? @batch << args : _remove(*args)
113
+ column_family, column, sub_column, options =
114
+ validate_params(column_family, key, columns_and_options, WRITE_DEFAULTS)
115
+
116
+ args = {:column_family => column_family, :timestamp => options[:timestamp] || Time.stamp}
117
+ columns = is_super(column_family) ? {:super_column => column, :column => sub_column} : {:column => column}
118
+ mutation = CassandraThrift::BatchMutation.new(
119
+ :key => key,
120
+ :cfmap => {},
121
+ :column_paths => [CassandraThrift::ColumnPath.new(args.merge(columns))])
122
+
123
+ @batch ? @batch << mutation : _mutate([mutation], options[:consistency])
121
124
  end
122
125
 
123
- # Remove all rows in the column family you request. Supports options
126
+ # Remove all rows in the column family you request. Supports options
124
127
  # <tt>:consistency</tt> and <tt>:timestamp</tt>.
125
- # FIXME May not currently delete all records without multiple calls. Waiting
128
+ # FIXME May not currently delete all records without multiple calls. Waiting
126
129
  # for ranged remove support in Cassandra.
127
130
  def clear_column_family!(column_family, options = {})
128
131
  get_range(column_family).each { |key| remove(column_family, key, options) }
129
132
  end
130
133
 
131
- # Remove all rows in the keyspace. Supports options <tt>:consistency</tt> and
134
+ # Remove all rows in the keyspace. Supports options <tt>:consistency</tt> and
132
135
  # <tt>:timestamp</tt>.
133
- # FIXME May not currently delete all records without multiple calls. Waiting
136
+ # FIXME May not currently delete all records without multiple calls. Waiting
134
137
  # for ranged remove support in Cassandra.
135
138
  def clear_keyspace!(options = {})
136
139
  @schema.keys.each { |column_family| clear_column_family!(column_family, options) }
@@ -139,10 +142,11 @@ class Cassandra
139
142
  ### Read
140
143
 
141
144
  # Count the elements at the column_family:key:[super_column] path you
142
- # request. Supports options <tt>:count</tt>, <tt>:start</tt>, <tt>:finish</tt>,
145
+ # request. Supports options <tt>:count</tt>, <tt>:start</tt>, <tt>:finish</tt>,
143
146
  # <tt>:reversed</tt>, and <tt>:consistency</tt>.
144
147
  def count_columns(column_family, key, *columns_and_options)
145
- column_family, super_column, _, options = params(column_family, columns_and_options, READ_DEFAULTS)
148
+ column_family, super_column, _, options =
149
+ validate_params(column_family, key, columns_and_options, READ_DEFAULTS)
146
150
  _count_columns(column_family, key, super_column, options[:consistency])
147
151
  end
148
152
 
@@ -153,14 +157,15 @@ class Cassandra
153
157
  end
154
158
 
155
159
  # Return a list of single values for the elements at the
156
- # column_family:key:column[s]:[sub_columns] path you request. Supports the
160
+ # column_family:key:column[s]:[sub_columns] path you request. Supports the
157
161
  # <tt>:consistency</tt> option.
158
162
  def get_columns(column_family, key, *columns_and_options)
159
- column_family, columns, sub_columns, options = params(column_family, columns_and_options, READ_DEFAULTS)
163
+ column_family, columns, sub_columns, options =
164
+ validate_params(column_family, key, columns_and_options, READ_DEFAULTS)
160
165
  _get_columns(column_family, key, columns, sub_columns, options[:consistency])
161
166
  end
162
167
 
163
- # Multi-key version of Cassandra#get_columns. Supports the <tt>:consistency</tt>
168
+ # Multi-key version of Cassandra#get_columns. Supports the <tt>:consistency</tt>
164
169
  # option.
165
170
  def multi_get_columns(column_family, keys, *options)
166
171
  OrderedHash[*keys.map { |key| [key, get_columns(column_family, key, *options)] }._flatten_once]
@@ -168,16 +173,17 @@ class Cassandra
168
173
 
169
174
  # Return a hash (actually, a Cassandra::OrderedHash) or a single value
170
175
  # representing the element at the column_family:key:[column]:[sub_column]
171
- # path you request. Supports options <tt>:count</tt>, <tt>:start</tt>,
176
+ # path you request. Supports options <tt>:count</tt>, <tt>:start</tt>,
172
177
  # <tt>:finish</tt>, <tt>:reversed</tt>, and <tt>:consistency</tt>.
173
178
  def get(column_family, key, *columns_and_options)
174
- column_family, column, sub_column, options = params(column_family, columns_and_options, READ_DEFAULTS)
179
+ column_family, column, sub_column, options =
180
+ validate_params(column_family, key, columns_and_options, READ_DEFAULTS)
175
181
  _get(column_family, key, column, sub_column, options[:count], options[:start], options[:finish], options[:reversed], options[:consistency])
176
182
  rescue CassandraThrift::NotFoundException
177
183
  is_super(column_family) && !sub_column ? OrderedHash.new : nil
178
184
  end
179
185
 
180
- # Multi-key version of Cassandra#get. Supports options <tt>:count</tt>,
186
+ # Multi-key version of Cassandra#get. Supports options <tt>:count</tt>,
181
187
  # <tt>:start</tt>, <tt>:finish</tt>, <tt>:reversed</tt>, and <tt>:consistency</tt>.
182
188
  def multi_get(column_family, keys, *options)
183
189
  OrderedHash[*keys.map { |key| [key, get(column_family, key, *options)] }._flatten_once]
@@ -186,23 +192,25 @@ class Cassandra
186
192
  # Return true if the column_family:key:[column]:[sub_column] path you
187
193
  # request exists. Supports the <tt>:consistency</tt> option.
188
194
  def exists?(column_family, key, *columns_and_options)
189
- column_family, column, sub_column, options = params(column_family, columns_and_options, READ_DEFAULTS)
195
+ column_family, column, sub_column, options =
196
+ validate_params(column_family, key, columns_and_options, READ_DEFAULTS)
190
197
  _get(column_family, key, column, sub_column, 1, nil, nil, nil, options[:consistency])
191
198
  true
192
199
  rescue CassandraThrift::NotFoundException
193
200
  end
194
201
 
195
202
  # Return a list of keys in the column_family you request. Requires the
196
- # table to be partitioned with OrderPreservingHash. Supports the
197
- # <tt>:count</tt>, <tt>:start</tt>, <tt>:finish</tt>, and <tt>:consistency</tt>
203
+ # table to be partitioned with OrderPreservingHash. Supports the
204
+ # <tt>:count</tt>, <tt>:start</tt>, <tt>:finish</tt>, and <tt>:consistency</tt>
198
205
  # options.
199
206
  def get_range(column_family, options = {})
200
- column_family, _, _, options = params(column_family, [options], READ_DEFAULTS)
207
+ column_family, _, _, options =
208
+ validate_params(column_family, "", [options], READ_DEFAULTS)
201
209
  _get_range(column_family, options[:start], options[:finish], options[:count], options[:consistency])
202
210
  end
203
211
 
204
212
  # Count all rows in the column_family you request. Requires the table
205
- # to be partitioned with OrderPreservingHash. Supports the <tt>:start</tt>,
213
+ # to be partitioned with OrderPreservingHash. Supports the <tt>:start</tt>,
206
214
  # <tt>:finish</tt>, and <tt>:consistency</tt> options.
207
215
  # FIXME will count only MAX_INT records
208
216
  def count_range(column_family, options = {})
@@ -210,33 +218,42 @@ class Cassandra
210
218
  end
211
219
 
212
220
  # Open a batch operation and yield. Inserts and deletes will be queued until
213
- # the block closes, and then sent atomically to the server.
214
- # FIXME Make deletes truly atomic.
215
- def batch
221
+ # the block closes, and then sent atomically to the server. Supports the
222
+ # <tt>:consistency</tt> option, which overrides the consistency set in
223
+ # the individual commands.
224
+ def batch(options = {})
225
+ _, _, _, options =
226
+ validate_params(@schema.keys.first, "", [options], WRITE_DEFAULTS)
227
+
216
228
  @batch = []
217
229
  yield
218
- compact_mutations
219
- dispatch_mutations
230
+ compact_mutations!
231
+ _mutate(@batch, options[:consistency])
220
232
  @batch = nil
221
233
  end
222
-
234
+
223
235
  private
224
-
236
+
225
237
  # Extract and validate options.
226
- def params(column_family, args, options)
227
- if args.last.is_a?(Hash)
228
- if (extras = args.last.keys - options.keys).any?
229
- this = "#{self.class}##{caller[0].split('`').last[0..-2]}"
230
- raise ArgumentError, "Invalid options #{extras.inspect[1..-2]} for #{this}"
231
- end
238
+ # FIXME Should be done as a decorator
239
+ def validate_params(column_family, key, args, options)
240
+ if !key.is_a?(String)
241
+ raise ArgumentError, "Key #{key.inspect} must be a String for #{calling_method}"
242
+ elsif args.last.is_a?(Hash)
243
+ extras = args.last.keys - options.keys
244
+ raise ArgumentError, "Invalid options #{extras.inspect[1..-2]} for #{calling_method}" if extras.any?
232
245
  options = options.merge(args.pop)
233
- end
246
+ end
234
247
 
235
248
  column_family, column, sub_column = column_family.to_s, args[0], args[1]
236
- assert_column_name_classes(column_family, column, sub_column)
249
+ assert_column_name_classes(column_family, column, sub_column)
237
250
  [column_family, map_to_s(column), map_to_s(sub_column), options]
238
251
  end
239
252
 
253
+ def calling_method
254
+ "#{self.class}##{caller[0].split('`').last[0..-3]}"
255
+ end
256
+
240
257
  # Convert stuff to strings.
241
258
  def map_to_s(el)
242
259
  case el
@@ -247,52 +264,28 @@ class Cassandra
247
264
  raise Comparable::TypeError, "Can't map #{el.inspect}"
248
265
  end
249
266
  end
250
-
251
- # Roll up queued mutations as much as possible, to improve atomicity.
252
- def compact_mutations
253
- compact_batch = []
267
+
268
+ # Roll up queued mutations, to improve atomicity.
269
+ def compact_mutations!
254
270
  mutations = {}
255
271
 
256
- @batch << nil # Close it
272
+ # Nested hash merge
257
273
  @batch.each do |m|
258
- case m
259
- when Array, nil
260
- # Flush compacted mutations
261
- compact_batch.concat(mutations.values.map {|x| x.values}.flatten)
262
- mutations = {}
263
- # Insert delete operation
264
- compact_batch << m
265
- else # BatchMutation, BatchMutationSuper
266
- # Do a nested hash merge
267
- if mutation_class = mutations[m.class]
268
- if mutation = mutation_class[m.key]
269
- if columns = mutation.cfmap[m.cfmap.keys.first]
270
- columns.concat(m.cfmap.values.first)
271
- else
272
- mutation.cfmap.merge!(m.cfmap)
273
- end
274
- else
275
- mutation_class[m.key] = m
276
- end
274
+ if mutation = mutations[m.key]
275
+ # Inserts
276
+ if columns = mutation.cfmap[m.cfmap.keys.first]
277
+ columns.concat(m.cfmap.values.first)
277
278
  else
278
- mutations[m.class] = {m.key => m}
279
+ mutation.cfmap.merge!(m.cfmap)
279
280
  end
281
+ # Deletes
282
+ mutation.column_paths.concat(m.column_paths)
283
+ else
284
+ mutations[m.key] = m
280
285
  end
281
286
  end
282
287
 
283
- @batch = compact_batch
288
+ # FIXME Return atomic thrift thingy
289
+ @batch = mutations.values
284
290
  end
285
-
286
- # Send all the queued mutations to the server.
287
- def dispatch_mutations
288
- @batch.compact!
289
- @batch.each do |args|
290
- case args.first
291
- when CassandraThrift::BatchMutationSuper, CassandraThrift::BatchMutation
292
- _insert(*args)
293
- else
294
- _remove(*args)
295
- end
296
- end
297
- end
298
291
  end
@@ -63,23 +63,24 @@ class Cassandra
63
63
  end
64
64
  hash
65
65
  end
66
-
66
+
67
67
  def hash_to_columns(column_family, hash, timestamp)
68
68
  assert_column_name_classes(column_family, hash.keys)
69
- hash_to_columns_without_assertion(column_family, hash, timestamp)
70
- end
71
-
72
- def hash_to_columns_without_assertion(column_family, hash, timestamp)
73
69
  hash.map do |column, value|
74
- CassandraThrift::Column.new(:name => column.to_s, :value => value, :timestamp => timestamp)
70
+ CassandraThrift::ColumnOrSuperColumn.new(:column =>
71
+ CassandraThrift::Column.new(:name => column.to_s, :value => value, :timestamp => timestamp))
75
72
  end
76
- end
73
+ end
77
74
 
78
75
  def hash_to_super_columns(column_family, hash, timestamp)
79
76
  assert_column_name_classes(column_family, hash.keys)
80
77
  hash.map do |column, sub_hash|
81
78
  assert_column_name_classes(column_family, nil, sub_hash.keys)
82
- CassandraThrift::SuperColumn.new(:name => column.to_s, :columns => hash_to_columns_without_assertion(column_family, sub_hash, timestamp))
79
+ sub_columns = sub_hash.map do |sub_column, value|
80
+ CassandraThrift::Column.new(:name => sub_column.to_s, :value => value, :timestamp => timestamp)
81
+ end
82
+ CassandraThrift::ColumnOrSuperColumn.new(:super_column =>
83
+ CassandraThrift::SuperColumn.new(:name => column.to_s, :columns => sub_columns))
83
84
  end
84
85
  end
85
86
  end
@@ -0,0 +1,7 @@
1
+
2
+ class CassandraThrift::Cassandra::Client
3
+ def send_message(*args)
4
+ pp args
5
+ super
6
+ end
7
+ end
@@ -2,18 +2,26 @@
2
2
  class Cassandra
3
3
  # A temporally-ordered Long class for use in Cassandra column names
4
4
  class Long < Comparable
5
-
6
- def initialize(bytes = nil)
5
+
6
+ def initialize(bytes = nil)
7
7
  case bytes
8
8
  when String
9
- raise TypeError, "8 bytes required" if bytes.size != 8
10
- @bytes = bytes
9
+ case bytes.size
10
+ when 8 # Raw byte array
11
+ @bytes = bytes
12
+ when 18 # Human-readable UUID-like representation; inverse of #to_guid
13
+ elements = bytes.split("-")
14
+ raise TypeError, "Malformed UUID-like representation" if elements.size != 3
15
+ @bytes = elements.join.to_a.pack('H32')
16
+ else
17
+ raise TypeError, "8 bytes required for byte array, or 18 characters required for UUID-like representation"
18
+ end
11
19
  when Integer
12
20
  raise TypeError, "Integer must be between 0 and 2**64" if bytes < 0 or bytes > 2**64
13
21
  @bytes = [bytes >> 32, bytes % 2**32].pack("NN")
14
- when NilClass
22
+ when NilClass, Time
15
23
  # Time.stamp is 52 bytes, so we have 12 bytes of entropy left over
16
- int = (Time.stamp << 12) + rand(2**12)
24
+ int = ((bytes || Time).stamp << 12) + rand(2**12)
17
25
  @bytes = [int >> 32, int % 2**32].pack("NN")
18
26
  else
19
27
  raise TypeError, "Can't convert from #{bytes.class}"
@@ -23,11 +31,15 @@ class Cassandra
23
31
  def to_i
24
32
  @to_i ||= begin
25
33
  ints = @bytes.unpack("NN")
26
- (ints[0] << 32) +
34
+ (ints[0] << 32) +
27
35
  ints[1]
28
36
  end
29
- end
37
+ end
30
38
 
39
+ def to_guid
40
+ "%08x-%04x-%04x" % @bytes.unpack("Nnn")
41
+ end
42
+
31
43
  def inspect
32
44
  "<Cassandra::Long##{object_id} time: #{
33
45
  Time.at((to_i >> 12) / 1_000_000).inspect
@@ -35,7 +47,9 @@ class Cassandra
35
47
  (to_i >> 12) % 1_000_000
36
48
  }, jitter: #{
37
49
  to_i % 2**12
50
+ }, guid: #{
51
+ to_guid
38
52
  }>"
39
- end
40
- end
53
+ end
54
+ end
41
55
  end
@@ -4,20 +4,8 @@ class Cassandra
4
4
  module Protocol #:nodoc:
5
5
  private
6
6
 
7
- def _insert(mutation, consistency)
8
- case mutation
9
- when CassandraThrift::BatchMutationSuper then @client.batch_insert_super_column(@keyspace, mutation, consistency)
10
- when CassandraThrift::BatchMutation then @client.batch_insert(@keyspace, mutation, consistency)
11
- end
12
- end
13
-
14
- def _remove(column_family, key, column, sub_column, consistency, timestamp)
15
- column_path_or_parent = if is_super(column_family)
16
- CassandraThrift::ColumnPath.new(:column_family => column_family, :super_column => column, :column => sub_column)
17
- else
18
- CassandraThrift::ColumnPath.new(:column_family => column_family, :column => column)
19
- end
20
- @client.remove(@keyspace, key, column_path_or_parent, timestamp, consistency)
7
+ def _mutate(mutation, consistency)
8
+ @client.batch_mutate(@keyspace, mutation, consistency)
21
9
  end
22
10
 
23
11
  def _count_columns(column_family, key, super_column, consistency)
@@ -8,45 +8,45 @@ class Cassandra
8
8
  end
9
9
 
10
10
  GREGORIAN_EPOCH_OFFSET = 0x01B2_1DD2_1381_4000 # Oct 15, 1582
11
-
11
+
12
12
  VARIANT = 0b1000_0000_0000_0000
13
13
 
14
14
  def initialize(bytes = nil)
15
15
  case bytes
16
16
  when String
17
17
  case bytes.size
18
- when 16
19
- @bytes = bytes
20
- when 36
18
+ when 16 # Raw byte array
19
+ @bytes = bytes
20
+ when 36 # Human-readable UUID representation; inverse of #to_guid
21
21
  elements = bytes.split("-")
22
22
  raise TypeError, "Malformed UUID representation" if elements.size != 5
23
- @bytes = elements.join.to_a.pack('H32')
23
+ @bytes = elements.join.to_a.pack('H32')
24
24
  else
25
25
  raise TypeError, "16 bytes required for byte array, or 36 characters required for UUID representation"
26
26
  end
27
-
27
+
28
28
  when Integer
29
29
  raise TypeError, "Integer must be between 0 and 2**128" if bytes < 0 or bytes > 2**128
30
30
  @bytes = [
31
- (bytes >> 96) & 0xFFFF_FFFF,
32
- (bytes >> 64) & 0xFFFF_FFFF,
33
- (bytes >> 32) & 0xFFFF_FFFF,
31
+ (bytes >> 96) & 0xFFFF_FFFF,
32
+ (bytes >> 64) & 0xFFFF_FFFF,
33
+ (bytes >> 32) & 0xFFFF_FFFF,
34
34
  bytes & 0xFFFF_FFFF
35
35
  ].pack("NNNN")
36
-
36
+
37
37
  when NilClass, Time
38
38
  time = (bytes || Time).stamp * 10 + GREGORIAN_EPOCH_OFFSET
39
39
  # See http://github.com/spectra/ruby-uuid/
40
40
  @bytes = [
41
- time & 0xFFFF_FFFF,
42
- time >> 32,
43
- ((time >> 48) & 0x0FFF) | 0x1000,
44
- # Top 3 bytes reserved
41
+ time & 0xFFFF_FFFF,
42
+ time >> 32,
43
+ ((time >> 48) & 0x0FFF) | 0x1000,
44
+ # Top 3 bytes reserved
45
45
  rand(2**13) | VARIANT,
46
46
  rand(2**16),
47
47
  rand(2**32)
48
48
  ].pack("NnnnnN")
49
-
49
+
50
50
  else
51
51
  raise TypeError, "Can't convert from #{bytes.class}"
52
52
  end
@@ -54,9 +54,9 @@ class Cassandra
54
54
 
55
55
  def to_i
56
56
  ints = @bytes.unpack("NNNN")
57
- (ints[0] << 96) +
58
- (ints[1] << 64) +
59
- (ints[2] << 32) +
57
+ (ints[0] << 96) +
58
+ (ints[1] << 64) +
59
+ (ints[2] << 32) +
60
60
  ints[3]
61
61
  end
62
62
 
@@ -65,7 +65,7 @@ class Cassandra
65
65
  version = (time_high & 0xF000).to_s(16)[0].chr.to_i
66
66
  version > 0 and version < 6 ? version : -1
67
67
  end
68
-
68
+
69
69
  def variant
70
70
  @bytes.unpack('QnnN')[1] >> 13
71
71
  end
@@ -76,19 +76,19 @@ class Cassandra
76
76
  elements[-1] = '%02x%02x%02x%02x%02x%02x' % node
77
77
  "%08x-%04x-%04x-%02x%02x-%s" % elements
78
78
  end
79
-
79
+
80
80
  def seconds
81
81
  total_usecs / 1_000_000
82
82
  end
83
-
83
+
84
84
  def usecs
85
- total_usecs % 1_000_000
85
+ total_usecs % 1_000_000
86
86
  end
87
-
87
+
88
88
  def <=>(other)
89
89
  total_usecs <=> other.send(:total_usecs)
90
90
  end
91
-
91
+
92
92
  def inspect(long = false)
93
93
  "<Cassandra::UUID##{object_id} time: #{
94
94
  Time.at(seconds).inspect
@@ -97,13 +97,13 @@ class Cassandra
97
97
  } jitter: #{
98
98
  @bytes.unpack('QQ')[1]
99
99
  }" + (long ? ", version: #{version}, variant: #{variant}, guid: #{to_guid}>" : ">")
100
- end
101
-
100
+ end
101
+
102
102
  private
103
-
103
+
104
104
  def total_usecs
105
105
  elements = @bytes.unpack("NnnQ")
106
- (elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
106
+ (elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
107
107
  end
108
108
  end
109
109
  end
@@ -6,9 +6,15 @@ class CassandraTest < Test::Unit::TestCase
6
6
  def setup
7
7
  @twitter = Cassandra.new('Twitter', '127.0.0.1')
8
8
  @twitter.clear_keyspace!
9
+
9
10
  @blogs = Cassandra.new('Multiblog', '127.0.0.1')
10
11
  @blogs.clear_keyspace!
11
- @uuids = (0..6).map {|i| UUID.new(Time.at(2**(24+i))) }
12
+
13
+ @blogs_long = Cassandra.new('MultiblogLong', '127.0.0.1')
14
+ @blogs_long.clear_keyspace!
15
+
16
+ @uuids = (0..6).map {|i| UUID.new(Time.at(2**(24+i))) }
17
+ @longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
12
18
  end
13
19
 
14
20
  def test_inspect
@@ -19,21 +25,21 @@ class CassandraTest < Test::Unit::TestCase
19
25
  end
20
26
 
21
27
  def test_connection_reopens
22
- assert_raises(NoMethodError) do
23
- @twitter.insert(:Statuses, 1, {'body' => 'v'})
28
+ assert_raises(Thrift::ProtocolException) do
29
+ @twitter.send("_mutate", [], -5)
24
30
  end
25
31
  assert_nothing_raised do
26
32
  @twitter.insert(:Statuses, key, {'body' => 'v'})
27
33
  end
28
34
  end
29
35
 
30
- def test_get_key_name_sorted
36
+ def test_get_key
31
37
  @twitter.insert(:Users, key, {'body' => 'v', 'user' => 'v'})
32
38
  assert_equal({'body' => 'v', 'user' => 'v'}, @twitter.get(:Users, key))
33
39
  assert_equal({}, @twitter.get(:Users, 'bogus'))
34
40
  end
35
41
 
36
- def test_get_key_name_sorted_preserving_order
42
+ def test_get_key_preserving_order
37
43
  # In-order hash is preserved
38
44
  hash = OrderedHash['a', '', 'b', '', 'c', '', 'd', '',]
39
45
  @twitter.insert(:Users, key, hash)
@@ -48,17 +54,38 @@ class CassandraTest < Test::Unit::TestCase
48
54
  assert_not_equal(hash.keys, @twitter.get(:Users, key).keys)
49
55
  end
50
56
 
51
- def test_get_key_time_sorted
52
- @blogs.insert(:Blogs, key, {@uuids[0] => 'I like this cat'})
53
- assert_equal({@uuids[0] => 'I like this cat'}, @blogs.get(:Blogs, key))
57
+ def test_get_first_time_uuid_column
58
+ @blogs.insert(:Blogs, key,
59
+ {@uuids[0] => 'I like this cat', @uuids[1] => 'Buttons is cuter', @uuids[2] => 'I disagree'})
60
+
61
+ assert_equal({@uuids[0] => 'I like this cat'}, @blogs.get(:Blogs, key, :count => 1))
62
+ assert_equal({@uuids[2] => 'I disagree'}, @blogs.get(:Blogs, key, :count => 1, :reversed => true))
54
63
  assert_equal({}, @blogs.get(:Blogs, 'bogus'))
55
64
  end
56
65
 
66
+ def test_get_first_long_column
67
+ @blogs_long.insert(:Blogs, key,
68
+ {@longs[0] => 'I like this cat', @longs[1] => 'Buttons is cuter', @longs[2] => 'I disagree'})
69
+
70
+ assert_equal({@longs[0] => 'I like this cat'}, @blogs_long.get(:Blogs, key, :count => 1))
71
+ assert_equal({@longs[2] => 'I disagree'}, @blogs_long.get(:Blogs, key, :count => 1, :reversed => true))
72
+ assert_equal({}, @blogs_long.get(:Blogs, 'bogus'))
73
+ end
74
+
75
+ def test_long_remove_bug
76
+ @blogs_long.insert(:Blogs, key, {@longs[0] => 'I like this cat'})
77
+ @blogs_long.remove(:Blogs, key)
78
+ assert_equal({}, @blogs_long.get(:Blogs, key, :count => 1))
79
+
80
+ @blogs_long.insert(:Blogs, key, {@longs[0] => 'I like this cat'})
81
+ assert_equal({@longs[0] => 'I like this cat'}, @blogs_long.get(:Blogs, key, :count => 1))
82
+ end
83
+
57
84
  def test_get_with_count
58
85
  @twitter.insert(:Statuses, key, {'1' => 'v', '2' => 'v', '3' => 'v'})
59
86
  assert_equal 1, @twitter.get(:Statuses, key, :count => 1).size
60
87
  assert_equal 2, @twitter.get(:Statuses, key, :count => 2).size
61
- end
88
+ end
62
89
 
63
90
  def test_get_value
64
91
  @twitter.insert(:Statuses, key, {'body' => 'v'})
@@ -68,7 +95,7 @@ class CassandraTest < Test::Unit::TestCase
68
95
  assert @twitter.exists?(:Statuses, key, 'body')
69
96
  assert_nil @twitter.exists?(:Statuses, 'bogus', 'body')
70
97
  end
71
-
98
+
72
99
  def test_get_super_key
73
100
  columns = {'user_timelines' => {@uuids[4] => '4', @uuids[5] => '5'}}
74
101
  @twitter.insert(:StatusRelationships, key, columns)
@@ -87,25 +114,25 @@ class CassandraTest < Test::Unit::TestCase
87
114
  end
88
115
 
89
116
  def test_get_super_sub_keys_with_count
90
- @twitter.insert(:StatusRelationships, key,
117
+ @twitter.insert(:StatusRelationships, key,
91
118
  {'user_timelines' => {@uuids[1] => 'v1', @uuids[2] => 'v2', @uuids[3] => 'v3'}})
92
- assert_equal({@uuids[1] => 'v1'},
119
+ assert_equal({@uuids[1] => 'v1'},
93
120
  @twitter.get(:StatusRelationships, key, "user_timelines", :count => 1))
94
- assert_equal({@uuids[3] => 'v3'},
121
+ assert_equal({@uuids[3] => 'v3'},
95
122
  @twitter.get(:StatusRelationships, key, "user_timelines", :count => 1, :reversed => true))
96
123
  end
97
124
 
98
- def test_get_super_sub_keys_with_ranges
99
- @twitter.insert(:StatusRelationships, key,
125
+ def test_get_super_sub_keys_with_ranges
126
+ @twitter.insert(:StatusRelationships, key,
100
127
  {'user_timelines' => {
101
- @uuids[1] => 'v1',
102
- @uuids[2] => 'v2',
128
+ @uuids[1] => 'v1',
129
+ @uuids[2] => 'v2',
103
130
  @uuids[3] => 'v3',
104
- @uuids[4] => 'v4',
131
+ @uuids[4] => 'v4',
105
132
  @uuids[5] => 'v5'}})
106
133
 
107
134
  keys = @twitter.get(:StatusRelationships, key, "user_timelines").keys
108
- assert_equal keys.sort, keys
135
+ assert_equal keys.sort, keys
109
136
  assert_equal({@uuids[1] => 'v1'}, @twitter.get(:StatusRelationships, key, "user_timelines", :finish => @uuids[2], :count => 1))
110
137
  assert_equal({@uuids[2] => 'v2'}, @twitter.get(:StatusRelationships, key, "user_timelines", :start => @uuids[2], :count => 1))
111
138
  assert_equal 4, @twitter.get(:StatusRelationships, key, "user_timelines", :start => @uuids[2], :finish => @uuids[5]).size
@@ -222,15 +249,6 @@ class CassandraTest < Test::Unit::TestCase
222
249
  @twitter.multi_get_columns(:Users, [key + '2', 'bogus', key + '1'], ['body', 'user']))
223
250
  end
224
251
 
225
- # Not supported
226
- # def test_get_columns_super_sub
227
- # @twitter.insert(:StatusRelationships, key, {
228
- # 'user_timelines' => {@uuids[1] => 'v1'},
229
- # 'mentions_timelines' => {@uuids[2] => 'v2'}})
230
- # assert_equal ['v1', 'v2'],
231
- # @twitter.get_columns(:StatusRelationships, key, 'user_timelines', ['1', key])
232
- # end
233
-
234
252
  def test_count_keys
235
253
  @twitter.insert(:Statuses, key + "1", {'body' => '1'})
236
254
  @twitter.insert(:Statuses, key + "2", {'body' => '2'})
@@ -266,7 +284,7 @@ class CassandraTest < Test::Unit::TestCase
266
284
  @twitter.multi_count_columns(:Users, [key + '2', 'bogus', key + '1']))
267
285
  end
268
286
 
269
- def test_batch_insert
287
+ def test_batch_mutate
270
288
  @twitter.insert(:Users, key + '1', {'body' => 'v1', 'user' => 'v1'})
271
289
 
272
290
  @twitter.batch do
@@ -13,6 +13,7 @@ class ComparableTypesTest < Test::Unit::TestCase
13
13
  long = Long.new
14
14
  assert_equal long, Long.new(long.to_s)
15
15
  assert_equal long, Long.new(long.to_i)
16
+ assert_equal long, Long.new(long.to_guid)
16
17
  end
17
18
 
18
19
  def test_long_error
@@ -78,17 +78,17 @@ require 'cassandra_types'
78
78
  return
79
79
  end
80
80
 
81
- def batch_insert(keyspace, batch_mutation, consistency_level)
82
- send_batch_insert(keyspace, batch_mutation, consistency_level)
83
- recv_batch_insert()
81
+ def batch_mutate(keyspace, batch_mutations, consistency_level)
82
+ send_batch_mutate(keyspace, batch_mutations, consistency_level)
83
+ recv_batch_mutate()
84
84
  end
85
85
 
86
- def send_batch_insert(keyspace, batch_mutation, consistency_level)
87
- send_message('batch_insert', Batch_insert_args, :keyspace => keyspace, :batch_mutation => batch_mutation, :consistency_level => consistency_level)
86
+ def send_batch_mutate(keyspace, batch_mutations, consistency_level)
87
+ send_message('batch_mutate', Batch_mutate_args, :keyspace => keyspace, :batch_mutations => batch_mutations, :consistency_level => consistency_level)
88
88
  end
89
89
 
90
- def recv_batch_insert()
91
- result = receive_message(Batch_insert_result)
90
+ def recv_batch_mutate()
91
+ result = receive_message(Batch_mutate_result)
92
92
  raise result.ire unless result.ire.nil?
93
93
  raise result.ue unless result.ue.nil?
94
94
  return
@@ -110,22 +110,6 @@ require 'cassandra_types'
110
110
  return
111
111
  end
112
112
 
113
- def batch_insert_super_column(keyspace, batch_mutation_super, consistency_level)
114
- send_batch_insert_super_column(keyspace, batch_mutation_super, consistency_level)
115
- recv_batch_insert_super_column()
116
- end
117
-
118
- def send_batch_insert_super_column(keyspace, batch_mutation_super, consistency_level)
119
- send_message('batch_insert_super_column', Batch_insert_super_column_args, :keyspace => keyspace, :batch_mutation_super => batch_mutation_super, :consistency_level => consistency_level)
120
- end
121
-
122
- def recv_batch_insert_super_column()
123
- result = receive_message(Batch_insert_super_column_result)
124
- raise result.ire unless result.ire.nil?
125
- raise result.ue unless result.ue.nil?
126
- return
127
- end
128
-
129
113
  def get_key_range(keyspace, column_family, start, finish, count)
130
114
  send_get_key_range(keyspace, column_family, start, finish, count)
131
115
  return recv_get_key_range()
@@ -243,17 +227,17 @@ require 'cassandra_types'
243
227
  write_result(result, oprot, 'insert', seqid)
244
228
  end
245
229
 
246
- def process_batch_insert(seqid, iprot, oprot)
247
- args = read_args(iprot, Batch_insert_args)
248
- result = Batch_insert_result.new()
230
+ def process_batch_mutate(seqid, iprot, oprot)
231
+ args = read_args(iprot, Batch_mutate_args)
232
+ result = Batch_mutate_result.new()
249
233
  begin
250
- @handler.batch_insert(args.keyspace, args.batch_mutation, args.consistency_level)
234
+ @handler.batch_mutate(args.keyspace, args.batch_mutations, args.consistency_level)
251
235
  rescue CassandraThrift::InvalidRequestException => ire
252
236
  result.ire = ire
253
237
  rescue CassandraThrift::UnavailableException => ue
254
238
  result.ue = ue
255
239
  end
256
- write_result(result, oprot, 'batch_insert', seqid)
240
+ write_result(result, oprot, 'batch_mutate', seqid)
257
241
  end
258
242
 
259
243
  def process_remove(seqid, iprot, oprot)
@@ -269,19 +253,6 @@ require 'cassandra_types'
269
253
  write_result(result, oprot, 'remove', seqid)
270
254
  end
271
255
 
272
- def process_batch_insert_super_column(seqid, iprot, oprot)
273
- args = read_args(iprot, Batch_insert_super_column_args)
274
- result = Batch_insert_super_column_result.new()
275
- begin
276
- @handler.batch_insert_super_column(args.keyspace, args.batch_mutation_super, args.consistency_level)
277
- rescue CassandraThrift::InvalidRequestException => ire
278
- result.ire = ire
279
- rescue CassandraThrift::UnavailableException => ue
280
- result.ue = ue
281
- end
282
- write_result(result, oprot, 'batch_insert_super_column', seqid)
283
- end
284
-
285
256
  def process_get_key_range(seqid, iprot, oprot)
286
257
  args = read_args(iprot, Get_key_range_args)
287
258
  result = Get_key_range_result.new()
@@ -504,16 +475,16 @@ require 'cassandra_types'
504
475
 
505
476
  end
506
477
 
507
- class Batch_insert_args
478
+ class Batch_mutate_args
508
479
  include ::Thrift::Struct
509
480
  KEYSPACE = 1
510
- BATCH_MUTATION = 2
481
+ BATCH_MUTATIONS = 2
511
482
  CONSISTENCY_LEVEL = 3
512
483
 
513
- ::Thrift::Struct.field_accessor self, :keyspace, :batch_mutation, :consistency_level
484
+ ::Thrift::Struct.field_accessor self, :keyspace, :batch_mutations, :consistency_level
514
485
  FIELDS = {
515
486
  KEYSPACE => {:type => ::Thrift::Types::STRING, :name => 'keyspace'},
516
- BATCH_MUTATION => {:type => ::Thrift::Types::STRUCT, :name => 'batch_mutation', :class => CassandraThrift::BatchMutation},
487
+ BATCH_MUTATIONS => {:type => ::Thrift::Types::LIST, :name => 'batch_mutations', :element => {:type => ::Thrift::Types::STRUCT, :class => CassandraThrift::BatchMutation}},
517
488
  CONSISTENCY_LEVEL => {:type => ::Thrift::Types::I32, :name => 'consistency_level', :default => 0, :enum_class => CassandraThrift::ConsistencyLevel}
518
489
  }
519
490
 
@@ -527,7 +498,7 @@ require 'cassandra_types'
527
498
 
528
499
  end
529
500
 
530
- class Batch_insert_result
501
+ class Batch_mutate_result
531
502
  include ::Thrift::Struct
532
503
  IRE = 1
533
504
  UE = 2
@@ -590,47 +561,6 @@ require 'cassandra_types'
590
561
 
591
562
  end
592
563
 
593
- class Batch_insert_super_column_args
594
- include ::Thrift::Struct
595
- KEYSPACE = 1
596
- BATCH_MUTATION_SUPER = 2
597
- CONSISTENCY_LEVEL = 3
598
-
599
- ::Thrift::Struct.field_accessor self, :keyspace, :batch_mutation_super, :consistency_level
600
- FIELDS = {
601
- KEYSPACE => {:type => ::Thrift::Types::STRING, :name => 'keyspace'},
602
- BATCH_MUTATION_SUPER => {:type => ::Thrift::Types::STRUCT, :name => 'batch_mutation_super', :class => CassandraThrift::BatchMutationSuper},
603
- CONSISTENCY_LEVEL => {:type => ::Thrift::Types::I32, :name => 'consistency_level', :default => 0, :enum_class => CassandraThrift::ConsistencyLevel}
604
- }
605
-
606
- def struct_fields; FIELDS; end
607
-
608
- def validate
609
- unless @consistency_level.nil? || CassandraThrift::ConsistencyLevel::VALID_VALUES.include?(@consistency_level)
610
- raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field consistency_level!')
611
- end
612
- end
613
-
614
- end
615
-
616
- class Batch_insert_super_column_result
617
- include ::Thrift::Struct
618
- IRE = 1
619
- UE = 2
620
-
621
- ::Thrift::Struct.field_accessor self, :ire, :ue
622
- FIELDS = {
623
- IRE => {:type => ::Thrift::Types::STRUCT, :name => 'ire', :class => CassandraThrift::InvalidRequestException},
624
- UE => {:type => ::Thrift::Types::STRUCT, :name => 'ue', :class => CassandraThrift::UnavailableException}
625
- }
626
-
627
- def struct_fields; FIELDS; end
628
-
629
- def validate
630
- end
631
-
632
- end
633
-
634
564
  class Get_key_range_args
635
565
  include ::Thrift::Struct
636
566
  KEYSPACE = 1
@@ -35,24 +35,6 @@ module CassandraThrift
35
35
 
36
36
  end
37
37
 
38
- class BatchMutation
39
- include ::Thrift::Struct
40
- KEY = 1
41
- CFMAP = 2
42
-
43
- ::Thrift::Struct.field_accessor self, :key, :cfmap
44
- FIELDS = {
45
- KEY => {:type => ::Thrift::Types::STRING, :name => 'key'},
46
- CFMAP => {:type => ::Thrift::Types::MAP, :name => 'cfmap', :key => {:type => ::Thrift::Types::STRING}, :value => {:type => ::Thrift::Types::LIST, :element => {:type => ::Thrift::Types::STRUCT, :class => CassandraThrift::Column}}}
47
- }
48
-
49
- def struct_fields; FIELDS; end
50
-
51
- def validate
52
- end
53
-
54
- end
55
-
56
38
  class SuperColumn
57
39
  include ::Thrift::Struct
58
40
  NAME = 1
@@ -71,15 +53,15 @@ module CassandraThrift
71
53
 
72
54
  end
73
55
 
74
- class BatchMutationSuper
56
+ class ColumnOrSuperColumn
75
57
  include ::Thrift::Struct
76
- KEY = 1
77
- CFMAP = 2
58
+ COLUMN = 1
59
+ SUPER_COLUMN = 2
78
60
 
79
- ::Thrift::Struct.field_accessor self, :key, :cfmap
61
+ ::Thrift::Struct.field_accessor self, :column, :super_column
80
62
  FIELDS = {
81
- KEY => {:type => ::Thrift::Types::STRING, :name => 'key'},
82
- CFMAP => {:type => ::Thrift::Types::MAP, :name => 'cfmap', :key => {:type => ::Thrift::Types::STRING}, :value => {:type => ::Thrift::Types::LIST, :element => {:type => ::Thrift::Types::STRUCT, :class => CassandraThrift::SuperColumn}}}
63
+ COLUMN => {:type => ::Thrift::Types::STRUCT, :name => 'column', :class => CassandraThrift::Column, :optional => true},
64
+ SUPER_COLUMN => {:type => ::Thrift::Types::STRUCT, :name => 'super_column', :class => CassandraThrift::SuperColumn, :optional => true}
83
65
  }
84
66
 
85
67
  def struct_fields; FIELDS; end
@@ -163,12 +145,14 @@ module CassandraThrift
163
145
  COLUMN_FAMILY = 3
164
146
  SUPER_COLUMN = 4
165
147
  COLUMN = 5
148
+ TIMESTAMP = 6
166
149
 
167
- ::Thrift::Struct.field_accessor self, :column_family, :super_column, :column
150
+ ::Thrift::Struct.field_accessor self, :column_family, :super_column, :column, :timestamp
168
151
  FIELDS = {
169
152
  COLUMN_FAMILY => {:type => ::Thrift::Types::STRING, :name => 'column_family'},
170
153
  SUPER_COLUMN => {:type => ::Thrift::Types::STRING, :name => 'super_column', :optional => true},
171
- COLUMN => {:type => ::Thrift::Types::STRING, :name => 'column', :optional => true}
154
+ COLUMN => {:type => ::Thrift::Types::STRING, :name => 'column', :optional => true},
155
+ TIMESTAMP => {:type => ::Thrift::Types::I64, :name => 'timestamp', :optional => true}
172
156
  }
173
157
 
174
158
  def struct_fields; FIELDS; end
@@ -218,15 +202,17 @@ module CassandraThrift
218
202
 
219
203
  end
220
204
 
221
- class ColumnOrSuperColumn
205
+ class BatchMutation
222
206
  include ::Thrift::Struct
223
- COLUMN = 1
224
- SUPER_COLUMN = 2
207
+ KEY = 1
208
+ CFMAP = 2
209
+ COLUMN_PATHS = 3
225
210
 
226
- ::Thrift::Struct.field_accessor self, :column, :super_column
211
+ ::Thrift::Struct.field_accessor self, :key, :cfmap, :column_paths
227
212
  FIELDS = {
228
- COLUMN => {:type => ::Thrift::Types::STRUCT, :name => 'column', :class => CassandraThrift::Column, :optional => true},
229
- SUPER_COLUMN => {:type => ::Thrift::Types::STRUCT, :name => 'super_column', :class => CassandraThrift::SuperColumn, :optional => true}
213
+ KEY => {:type => ::Thrift::Types::STRING, :name => 'key'},
214
+ CFMAP => {:type => ::Thrift::Types::MAP, :name => 'cfmap', :key => {:type => ::Thrift::Types::STRING}, :value => {:type => ::Thrift::Types::LIST, :element => {:type => ::Thrift::Types::STRUCT, :class => CassandraThrift::ColumnOrSuperColumn}}},
215
+ COLUMN_PATHS => {:type => ::Thrift::Types::LIST, :name => 'column_paths', :element => {:type => ::Thrift::Types::STRUCT, :class => CassandraThrift::ColumnPath}}
230
216
  }
231
217
 
232
218
  def struct_fields; FIELDS; end
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.5.4
4
+ version: 0.5.5
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-08-19 00:00:00 -04:00
33
+ date: 2009-08-27 00:00:00 -07:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
@@ -67,6 +67,7 @@ extra_rdoc_files:
67
67
  - lib/cassandra/columns.rb
68
68
  - lib/cassandra/comparable.rb
69
69
  - lib/cassandra/constants.rb
70
+ - lib/cassandra/debug.rb
70
71
  - lib/cassandra/long.rb
71
72
  - lib/cassandra/ordered_hash.rb
72
73
  - lib/cassandra/protocol.rb
@@ -87,6 +88,7 @@ files:
87
88
  - lib/cassandra/columns.rb
88
89
  - lib/cassandra/comparable.rb
89
90
  - lib/cassandra/constants.rb
91
+ - lib/cassandra/debug.rb
90
92
  - lib/cassandra/long.rb
91
93
  - lib/cassandra/ordered_hash.rb
92
94
  - lib/cassandra/protocol.rb
metadata.gz.sig CHANGED
Binary file