cassandra 0.5.4 → 0.5.5

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