cassandra-driver 1.0.0.beta.2-java

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.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +4 -0
  3. data/README.md +125 -0
  4. data/lib/cassandra/auth/providers/password.rb +73 -0
  5. data/lib/cassandra/auth/providers.rb +16 -0
  6. data/lib/cassandra/auth.rb +97 -0
  7. data/lib/cassandra/client/batch.rb +212 -0
  8. data/lib/cassandra/client/client.rb +591 -0
  9. data/lib/cassandra/client/column_metadata.rb +54 -0
  10. data/lib/cassandra/client/connection_manager.rb +72 -0
  11. data/lib/cassandra/client/connector.rb +277 -0
  12. data/lib/cassandra/client/execute_options_decoder.rb +59 -0
  13. data/lib/cassandra/client/null_logger.rb +37 -0
  14. data/lib/cassandra/client/peer_discovery.rb +50 -0
  15. data/lib/cassandra/client/prepared_statement.rb +314 -0
  16. data/lib/cassandra/client/query_result.rb +230 -0
  17. data/lib/cassandra/client/request_runner.rb +71 -0
  18. data/lib/cassandra/client/result_metadata.rb +48 -0
  19. data/lib/cassandra/client/void_result.rb +78 -0
  20. data/lib/cassandra/client.rb +144 -0
  21. data/lib/cassandra/cluster/client.rb +768 -0
  22. data/lib/cassandra/cluster/connector.rb +244 -0
  23. data/lib/cassandra/cluster/control_connection.rb +425 -0
  24. data/lib/cassandra/cluster/metadata.rb +124 -0
  25. data/lib/cassandra/cluster/options.rb +42 -0
  26. data/lib/cassandra/cluster/registry.rb +198 -0
  27. data/lib/cassandra/cluster/schema/partitioners/murmur3.rb +47 -0
  28. data/lib/cassandra/cluster/schema/partitioners/ordered.rb +37 -0
  29. data/lib/cassandra/cluster/schema/partitioners/random.rb +37 -0
  30. data/lib/cassandra/cluster/schema/partitioners.rb +21 -0
  31. data/lib/cassandra/cluster/schema/replication_strategies/network_topology.rb +92 -0
  32. data/lib/cassandra/cluster/schema/replication_strategies/none.rb +39 -0
  33. data/lib/cassandra/cluster/schema/replication_strategies/simple.rb +44 -0
  34. data/lib/cassandra/cluster/schema/replication_strategies.rb +21 -0
  35. data/lib/cassandra/cluster/schema/type_parser.rb +138 -0
  36. data/lib/cassandra/cluster/schema.rb +340 -0
  37. data/lib/cassandra/cluster.rb +215 -0
  38. data/lib/cassandra/column.rb +92 -0
  39. data/lib/cassandra/compression/compressors/lz4.rb +72 -0
  40. data/lib/cassandra/compression/compressors/snappy.rb +66 -0
  41. data/lib/cassandra/compression.rb +66 -0
  42. data/lib/cassandra/driver.rb +111 -0
  43. data/lib/cassandra/errors.rb +79 -0
  44. data/lib/cassandra/execution/info.rb +51 -0
  45. data/lib/cassandra/execution/options.rb +80 -0
  46. data/lib/cassandra/execution/trace.rb +152 -0
  47. data/lib/cassandra/future.rb +675 -0
  48. data/lib/cassandra/host.rb +79 -0
  49. data/lib/cassandra/keyspace.rb +133 -0
  50. data/lib/cassandra/listener.rb +87 -0
  51. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +149 -0
  52. data/lib/cassandra/load_balancing/policies/round_robin.rb +132 -0
  53. data/lib/cassandra/load_balancing/policies/token_aware.rb +119 -0
  54. data/lib/cassandra/load_balancing/policies/white_list.rb +90 -0
  55. data/lib/cassandra/load_balancing/policies.rb +19 -0
  56. data/lib/cassandra/load_balancing.rb +113 -0
  57. data/lib/cassandra/protocol/cql_byte_buffer.rb +307 -0
  58. data/lib/cassandra/protocol/cql_protocol_handler.rb +323 -0
  59. data/lib/cassandra/protocol/frame_decoder.rb +128 -0
  60. data/lib/cassandra/protocol/frame_encoder.rb +48 -0
  61. data/lib/cassandra/protocol/request.rb +38 -0
  62. data/lib/cassandra/protocol/requests/auth_response_request.rb +47 -0
  63. data/lib/cassandra/protocol/requests/batch_request.rb +76 -0
  64. data/lib/cassandra/protocol/requests/credentials_request.rb +47 -0
  65. data/lib/cassandra/protocol/requests/execute_request.rb +103 -0
  66. data/lib/cassandra/protocol/requests/options_request.rb +39 -0
  67. data/lib/cassandra/protocol/requests/prepare_request.rb +50 -0
  68. data/lib/cassandra/protocol/requests/query_request.rb +153 -0
  69. data/lib/cassandra/protocol/requests/register_request.rb +38 -0
  70. data/lib/cassandra/protocol/requests/startup_request.rb +49 -0
  71. data/lib/cassandra/protocol/requests/void_query_request.rb +24 -0
  72. data/lib/cassandra/protocol/response.rb +38 -0
  73. data/lib/cassandra/protocol/responses/auth_challenge_response.rb +41 -0
  74. data/lib/cassandra/protocol/responses/auth_success_response.rb +41 -0
  75. data/lib/cassandra/protocol/responses/authenticate_response.rb +41 -0
  76. data/lib/cassandra/protocol/responses/detailed_error_response.rb +60 -0
  77. data/lib/cassandra/protocol/responses/error_response.rb +50 -0
  78. data/lib/cassandra/protocol/responses/event_response.rb +39 -0
  79. data/lib/cassandra/protocol/responses/prepared_result_response.rb +64 -0
  80. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +43 -0
  81. data/lib/cassandra/protocol/responses/ready_response.rb +44 -0
  82. data/lib/cassandra/protocol/responses/result_response.rb +48 -0
  83. data/lib/cassandra/protocol/responses/rows_result_response.rb +139 -0
  84. data/lib/cassandra/protocol/responses/schema_change_event_response.rb +60 -0
  85. data/lib/cassandra/protocol/responses/schema_change_result_response.rb +57 -0
  86. data/lib/cassandra/protocol/responses/set_keyspace_result_response.rb +42 -0
  87. data/lib/cassandra/protocol/responses/status_change_event_response.rb +44 -0
  88. data/lib/cassandra/protocol/responses/supported_response.rb +41 -0
  89. data/lib/cassandra/protocol/responses/topology_change_event_response.rb +34 -0
  90. data/lib/cassandra/protocol/responses/void_result_response.rb +39 -0
  91. data/lib/cassandra/protocol/type_converter.rb +384 -0
  92. data/lib/cassandra/protocol.rb +93 -0
  93. data/lib/cassandra/reconnection/policies/constant.rb +48 -0
  94. data/lib/cassandra/reconnection/policies/exponential.rb +79 -0
  95. data/lib/cassandra/reconnection/policies.rb +20 -0
  96. data/lib/cassandra/reconnection.rb +49 -0
  97. data/lib/cassandra/result.rb +215 -0
  98. data/lib/cassandra/retry/policies/default.rb +47 -0
  99. data/lib/cassandra/retry/policies/downgrading_consistency.rb +71 -0
  100. data/lib/cassandra/retry/policies/fallthrough.rb +39 -0
  101. data/lib/cassandra/retry/policies.rb +21 -0
  102. data/lib/cassandra/retry.rb +142 -0
  103. data/lib/cassandra/session.rb +202 -0
  104. data/lib/cassandra/statement.rb +22 -0
  105. data/lib/cassandra/statements/batch.rb +95 -0
  106. data/lib/cassandra/statements/bound.rb +48 -0
  107. data/lib/cassandra/statements/prepared.rb +81 -0
  108. data/lib/cassandra/statements/simple.rb +58 -0
  109. data/lib/cassandra/statements/void.rb +33 -0
  110. data/lib/cassandra/statements.rb +23 -0
  111. data/lib/cassandra/table.rb +299 -0
  112. data/lib/cassandra/time_uuid.rb +142 -0
  113. data/lib/cassandra/util.rb +167 -0
  114. data/lib/cassandra/uuid.rb +104 -0
  115. data/lib/cassandra/version.rb +21 -0
  116. data/lib/cassandra.rb +428 -0
  117. data/lib/cassandra_murmur3.jar +0 -0
  118. metadata +211 -0
@@ -0,0 +1,299 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2014 DataStax, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #++
18
+
19
+ module Cassandra
20
+ # Represents a cassandra table
21
+ # @see Cassandra::Keyspace#each_table
22
+ # @see Cassandra::Keyspace#table
23
+ class Table
24
+ # @private
25
+ class Options
26
+ attr_reader :comment, :read_repair_chance, :local_read_repair_chance,
27
+ :gc_grace_seconds, :caching, :bloom_filter_fp_chance,
28
+ :populate_io_cache_on_flush, :memtable_flush_period_in_ms,
29
+ :default_time_to_live, :speculative_retry, :index_interval,
30
+ :replicate_on_write, :compaction_strategy, :compact_storage,
31
+ :compression_parameters
32
+
33
+ def initialize(data, compaction_strategy, compression_parameters, compact_storage, cassandra_version)
34
+ @comment = data['comment']
35
+ @read_repair_chance = data['read_repair_chance']
36
+ @local_read_repair_chance = data['local_read_repair_chance']
37
+ @gc_grace_seconds = data['gc_grace_seconds']
38
+ @caching = data['caching']
39
+ @bloom_filter_fp_chance = data['bloom_filter_fp_chance'] || 0.01
40
+ @populate_io_cache_on_flush = data['populate_io_cache_on_flush'] || false
41
+ @memtable_flush_period_in_ms = data['memtable_flush_period_in_ms'] || 0
42
+ @default_time_to_live = data['default_time_to_live'] || 0
43
+ @speculative_retry = data['speculative_retry'] || 'NONE'
44
+ @index_interval = data['index_interval'] || 128
45
+ @replicate_on_write = data['replicate_on_write'] || true
46
+ @compaction_strategy = compaction_strategy
47
+ @compression_parameters = compression_parameters
48
+ @compact_storage = compact_storage
49
+ @cassandra_version = cassandra_version
50
+ end
51
+
52
+ def replicate_on_write?
53
+ @replicate_on_write
54
+ end
55
+
56
+ def populate_io_cache_on_flush?
57
+ @populate_io_cache_on_flush
58
+ end
59
+
60
+ def compact_storage?
61
+ @compact_storage
62
+ end
63
+
64
+ def to_cql
65
+ options = []
66
+
67
+ options << 'COMPACT STORAGE' if @compact_storage
68
+ options << "bloom_filter_fp_chance = #{@bloom_filter_fp_chance}"
69
+ options << "caching = '#{@caching}'"
70
+ options << "comment = '#{@comment}'" if @comment
71
+ options << "compaction = #{@compaction_strategy.to_cql}"
72
+ options << "compression = #{Util.encode_hash(@compression_parameters)}"
73
+ options << "dclocal_read_repair_chance = #{@local_read_repair_chance}"
74
+ options << "default_time_to_live = #{@default_time_to_live}" if !@cassandra_version.start_with?('1')
75
+ options << "gc_grace_seconds = #{@gc_grace_seconds}"
76
+ options << "index_interval = #{@index_interval}" if !@cassandra_version.start_with?('1')
77
+ options << "populate_io_cache_on_flush = '#{@populate_io_cache_on_flush}'"
78
+ options << "read_repair_chance = #{@read_repair_chance}"
79
+ options << "replicate_on_write = '#{@replicate_on_write}'" if @cassandra_version.start_with?('1') || @cassandra_version.start_with?('2.0')
80
+ options << "speculative_retry = '#{@speculative_retry}'" if !@cassandra_version.start_with?('1')
81
+
82
+ options.join("\nAND ")
83
+ end
84
+
85
+ def eql?(other)
86
+ other.is_a?(Options) &&
87
+ @comment == other.comment &&
88
+ @read_repair_chance == other.read_repair_chance &&
89
+ @local_read_repair_chance == other.local_read_repair_chance &&
90
+ @gc_grace_seconds == other.gc_grace_seconds &&
91
+ @caching == other.caching &&
92
+ @bloom_filter_fp_chance == other.bloom_filter_fp_chance &&
93
+ @populate_io_cache_on_flush == other.populate_io_cache_on_flush &&
94
+ @memtable_flush_period_in_ms == other.memtable_flush_period_in_ms &&
95
+ @default_time_to_live == other.default_time_to_live &&
96
+ @speculative_retry == other.speculative_retry &&
97
+ @index_interval == other.index_interval &&
98
+ @replicate_on_write == other.replicate_on_write &&
99
+ @compaction_strategy == other.compaction_strategy &&
100
+ @compression_parameters == other.compression_parameters &&
101
+ @compact_storage == other.compact_storage &&
102
+ @cassandra_version == other.cassandra_version
103
+ end
104
+ alias :== :eql?
105
+
106
+ attr_reader :cassandra_version
107
+ protected :cassandra_version
108
+ end
109
+
110
+ # @private
111
+ class Compaction
112
+ attr_reader :klass, :options
113
+
114
+ def initialize(klass, options)
115
+ @klass = klass
116
+ @options = options
117
+ end
118
+
119
+ def to_cql
120
+ compaction = {'class' => @klass}
121
+ compaction.merge!(@options)
122
+
123
+ Util.encode_hash(compaction)
124
+ end
125
+
126
+ def eql?(other)
127
+ other.is_a?(Compaction) &&
128
+ @klass == other.klass &&
129
+ @options == other.options
130
+ end
131
+ alias :== :eql?
132
+ end
133
+
134
+ # @private
135
+ attr_reader :keyspace
136
+ # @return [String] table name
137
+ attr_reader :name
138
+ # @private
139
+ attr_reader :options
140
+
141
+ # @private
142
+ def initialize(keyspace, name, partition_key, clustering_columns, columns, options, clustering_order)
143
+ @keyspace = keyspace
144
+ @name = name
145
+ @partition_key = partition_key
146
+ @clustering_columns = clustering_columns
147
+ @columns = columns
148
+ @options = options
149
+ @clustering_order = clustering_order
150
+ end
151
+
152
+ # @param name [String] column name
153
+ # @return [Boolean] whether this table has a given column
154
+ def has_column?(name)
155
+ @columns.has_key?(name)
156
+ end
157
+
158
+ # @param name [String] column name
159
+ # @return [Cassandra::Column, nil] a column or nil
160
+ def column(name)
161
+ @columns[name]
162
+ end
163
+
164
+ # Yield or enumerate each column defined in this table
165
+ # @overload each_column
166
+ # @yieldparam column [Cassandra::Column] current column
167
+ # @return [Cassandra::Table] self
168
+ # @overload each_column
169
+ # @return [Array<Cassandra::Column>] a list of columns
170
+ def each_column(&block)
171
+ if block_given?
172
+ @columns.each_value(&block)
173
+ self
174
+ else
175
+ @columns.values
176
+ end
177
+ end
178
+ alias :columns :each_column
179
+
180
+ # @return [String] a cql representation of this table
181
+ def to_cql
182
+ cql = "CREATE TABLE #{Util.escape_name(@keyspace)}.#{Util.escape_name(@name)} (\n"
183
+ first = true
184
+ @columns.each do |(_, column)|
185
+ if first
186
+ first = false
187
+ else
188
+ cql << ",\n" unless first
189
+ end
190
+ cql << " #{column.to_cql}"
191
+ end
192
+ cql << ",\n PRIMARY KEY ("
193
+ if @partition_key.one?
194
+ cql << @partition_key.first.name
195
+ else
196
+ cql << '('
197
+ first = true
198
+ @partition_key.each do |column|
199
+ if first
200
+ first = false
201
+ else
202
+ cql << ', '
203
+ end
204
+ cql << column.name
205
+ end
206
+ cql << ')'
207
+ end
208
+ @clustering_columns.each do |column|
209
+ cql << ", #{column.name}"
210
+ end
211
+ cql << ')'
212
+
213
+ cql << "\n)\nWITH "
214
+
215
+ if @clustering_order.any? {|o| o != :asc}
216
+ cql << "CLUSTERING ORDER BY ("
217
+ first = true
218
+ @clustering_columns.zip(@clustering_order) do |column, order|
219
+ if first
220
+ first = false
221
+ else
222
+ cql << ', '
223
+ end
224
+ cql << "#{column.name} #{order.to_s.upcase}"
225
+ end
226
+ cql << ")\n AND "
227
+ end
228
+
229
+ cql << @options.to_cql.split("\n").join("\n ")
230
+
231
+ cql << ';'
232
+ end
233
+
234
+ # @return [Boolean] whether this table is equal to the other
235
+ def eql?(other)
236
+ other.is_a?(Table) &&
237
+ @keyspace == other.keyspace &&
238
+ @name == other.name &&
239
+ @partition_key == other.partition_key &&
240
+ @clustering_columns == other.clustering_columns &&
241
+ @columns == other.raw_columns &&
242
+ @options == other.options &&
243
+ @clustering_order == other.clustering_order
244
+ end
245
+ alias :== :eql?
246
+
247
+ # @private
248
+ def create_partition_key(values)
249
+ partition_key = @partition_key
250
+ return nil unless partition_key.size == values.size
251
+
252
+ if partition_key.one?
253
+ column = partition_key.first
254
+ column_name = column.name
255
+ return nil unless values.has_key?(column_name)
256
+
257
+ buffer = Protocol::CqlByteBuffer.new
258
+
259
+ TYPE_CONVERTER.to_bytes(buffer, column.type, values[column_name])
260
+ buffer.discard(4)
261
+ else
262
+ buf = nil
263
+ buffer = nil
264
+
265
+ partition_key.each do |column|
266
+ column_name = column.name
267
+ return nil unless values.has_key?(column_name)
268
+
269
+ buf ||= Protocol::CqlByteBuffer.new
270
+ buffer ||= Protocol::CqlByteBuffer.new
271
+
272
+ TYPE_CONVERTER.to_bytes(buf, column.type, values[column_name])
273
+ buf.discard(4) # discard size
274
+
275
+ size = buf.length
276
+ buffer.append_short(size)
277
+ buffer << buf.read(size) << NULL_BYTE
278
+ end
279
+ end
280
+
281
+ buffer.to_str
282
+ end
283
+
284
+ private
285
+
286
+ NULL_BYTE = "\x00".freeze
287
+ TYPE_CONVERTER = Protocol::TypeConverter.new
288
+
289
+ attr_reader :partition_key, :clustering_columns, :clustering_order
290
+ protected :partition_key, :clustering_columns, :clustering_order
291
+
292
+ protected
293
+
294
+ # @private
295
+ def raw_columns
296
+ @columns
297
+ end
298
+ end
299
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2014 DataStax, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #++
18
+
19
+ module Cassandra
20
+ # A variant of UUID which can extract its time component.
21
+ #
22
+ class TimeUuid < Uuid
23
+ include Comparable
24
+
25
+ # Returns the time component from this UUID as a Time.
26
+ #
27
+ # @return [Time]
28
+ def to_time
29
+ t = time_bits - GREGORIAN_OFFSET
30
+ seconds = t/10_000_000
31
+ microseconds = (t - seconds * 10_000_000)/10.0
32
+ Time.at(seconds, microseconds).utc
33
+ end
34
+
35
+ def <=>(other)
36
+ return nil unless other.kind_of?(Cassandra::Uuid)
37
+ c = self.value <=> other.value
38
+ return c if c == 0
39
+ self.time_bits <=> other.time_bits
40
+ end
41
+
42
+ protected
43
+
44
+ def time_bits
45
+ n = (value >> 64)
46
+ t = 0
47
+ t |= (n & 0x0000000000000fff) << 48
48
+ t |= (n & 0x00000000ffff0000) << 16
49
+ t |= (n & 0xffffffff00000000) >> 32
50
+ t
51
+ end
52
+
53
+ private
54
+
55
+ # @private
56
+ LOWER_HALF_MASK = 0xffffffff_ffffffff
57
+
58
+ public
59
+
60
+ # A UUID version 1, variant 1 generator. It can generate a sequence of UUIDs
61
+ # with reasonable uniqueness guarantees:
62
+ #
63
+ # * The clock ID and node ID components are set to random numbers when the
64
+ # generator is created.
65
+ # * If two calls to {#next} happen within the time afforded by the system
66
+ # clock resolution a counter is incremented and added to the time
67
+ # component.
68
+ # * If the clock moves backwards the clock ID is reset to a new random
69
+ # number.
70
+ #
71
+ # Instances of this class are absolutely not threadsafe. You should
72
+ # never share instances between threads.
73
+ #
74
+ class Generator
75
+ # Create a new UUID generator.
76
+ #
77
+ # @param [Integer] node_id an alternate node ID (defaults to a random number)
78
+ # @param [Integer] clock_id an alternate clock ID (defaults to a random number)
79
+ #
80
+ def initialize(node_id=nil, clock_id=nil, clock=Time)
81
+ @node_id = node_id || (rand(2**47) | 0x010000000000)
82
+ @clock_id = clock_id || rand(2**16)
83
+ @clock = clock
84
+ end
85
+
86
+ # Returns a new UUID with a time component that is the current time.
87
+ #
88
+ # @return [Cassandra::TimeUuid] a new UUID
89
+ #
90
+ def next
91
+ now = @clock.now
92
+ usecs = now.to_i * 1_000_000 + now.usec
93
+ if @last_usecs && @last_usecs - @sequence <= usecs && usecs <= @last_usecs
94
+ @sequence += 1
95
+ elsif @last_usecs && @last_usecs > usecs
96
+ @sequence = 0
97
+ @clock_id = rand(2**16)
98
+ else
99
+ @sequence = 0
100
+ end
101
+ @last_usecs = usecs + @sequence
102
+ from_usecs(@last_usecs)
103
+ end
104
+
105
+ # Returns a new UUID with a time component based on the specified Time.
106
+ # A piece of jitter is added to ensure that multiple calls with the same
107
+ # time do not generate the same UUID (if you want determinism you can set
108
+ # the second parameter to zero).
109
+ #
110
+ # @param [Time] time the time to encode into the UUID
111
+ # @param [Integer] jitter a number of microseconds to add to the time to make it unique
112
+ # @return [Cassandra::TimeUuid] a new UUID
113
+ #
114
+ def from_time(time, jitter=rand(2**16))
115
+ usecs = time.to_i * 1_000_000 + time.usec + jitter
116
+ from_usecs(usecs)
117
+ end
118
+
119
+ # @private
120
+ def from_usecs(usecs)
121
+ t = GREGORIAN_OFFSET + usecs * 10
122
+ time_hi = t & 0x0fff000000000000
123
+ time_mid = t & 0x0000ffff00000000
124
+ time_low = t & 0x00000000ffffffff
125
+ version = 1
126
+ clock_id = @clock_id & 0x3fff
127
+ node_id = @node_id & 0xffffffffffff
128
+ variant = 0x8000
129
+ n = (time_low << 96) | (time_mid << 48) | (time_hi << 16)
130
+ n |= version << 76
131
+ n |= (clock_id | variant) << 48
132
+ n |= node_id
133
+ TimeUuid.new(n)
134
+ end
135
+ end
136
+
137
+ private
138
+
139
+ # @private
140
+ GREGORIAN_OFFSET = 122192928000000000
141
+ end
142
+ end
@@ -0,0 +1,167 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2014 DataStax, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #++
18
+
19
+ module Cassandra
20
+ # @private
21
+ module Util extend self
22
+ def encode_hash(hash, io = StringIO.new)
23
+ first = true
24
+
25
+ io.putc(CRL_OPN)
26
+ hash.each do |k, v|
27
+ if first
28
+ first = false
29
+ else
30
+ io.print(COMMA)
31
+ end
32
+
33
+ encode_object(k, io)
34
+ io.print(COLON)
35
+ encode_object(v, io)
36
+ end
37
+ io.putc(CRL_CLS)
38
+
39
+ io.string
40
+ end
41
+
42
+ def encode_set(set, io = StringIO.new)
43
+ first = true
44
+
45
+ io.putc(CRL_OPN)
46
+ set.each do |object|
47
+ if first
48
+ first = false
49
+ else
50
+ io.print(COMMA)
51
+ end
52
+
53
+ encode_object(object, io)
54
+ end
55
+ io.putc(CRL_CLS)
56
+
57
+ io.string
58
+ end
59
+
60
+ def encode_array(array, io = StringIO.new)
61
+ first = true
62
+
63
+ io.putc(SQR_OPN)
64
+ array.each do |object|
65
+ if first
66
+ first = false
67
+ else
68
+ io.print(COMMA)
69
+ end
70
+
71
+ encode_object(object, io)
72
+ end
73
+ io.putc(SQR_CLS)
74
+
75
+ io.string
76
+ end
77
+
78
+ def encode_string(string, io = StringIO.new)
79
+ io.putc(QUOT)
80
+ string.chars do |c|
81
+ case c
82
+ when QUOT then io.print(ESC_QUOT)
83
+ else
84
+ io.putc(c)
85
+ end
86
+ end
87
+ io.putc(QUOT)
88
+
89
+ io.string
90
+ end
91
+
92
+ def encode_object(object, io = StringIO.new)
93
+ case object
94
+ when ::Hash then encode_hash(object, io)
95
+ when ::Array then encode_array(object, io)
96
+ when ::Set then encode_set(object, io)
97
+ when ::String then encode_string(object, io)
98
+ when ::Time then encode_timestamp(object, io)
99
+ when ::Numeric then encode_number(object, io)
100
+ when ::IPAddr then encode_inet(object, io)
101
+ when Uuid then encode_uuid(object, io)
102
+ when nil then io.print(NULL_STR)
103
+ when false then io.print(FALSE_STR)
104
+ when true then io.print(TRUE_STR)
105
+ else
106
+ raise "unsupported type: #{object.inspect}"
107
+ end
108
+
109
+ io.string
110
+ end
111
+ alias :encode :encode_object
112
+
113
+ def encode_timestamp(time, io = StringIO.new)
114
+ io.print(time.to_i)
115
+ io.string
116
+ end
117
+
118
+ def encode_number(number, io = StringIO.new)
119
+ io.print(number)
120
+ io.string
121
+ end
122
+
123
+ def encode_uuid(uuid, io = StringIO.new)
124
+ io.print(uuid)
125
+ io.string
126
+ end
127
+
128
+ def encode_inet(inet, io = StringIO.new)
129
+ io.putc(QUOT)
130
+ io.print(inet)
131
+ io.putc(QUOT)
132
+ io.string
133
+ end
134
+
135
+ def escape_name(name)
136
+ return name if name[LOWERCASE_REGEXP] == name
137
+ DBL_QUOT + name + DBL_QUOT
138
+ end
139
+
140
+ # @private
141
+ LOWERCASE_REGEXP = /[[:lower:]\_]*/
142
+ # @private
143
+ NULL_STR = 'null'.freeze
144
+ # @private
145
+ FALSE_STR = 'false'.freeze
146
+ # @private
147
+ TRUE_STR = 'true'.freeze
148
+ # @private
149
+ CRL_OPN = '{'.freeze
150
+ # @private
151
+ CRL_CLS = '}'.freeze
152
+ # @private
153
+ SQR_OPN = '['.freeze
154
+ # @private
155
+ SQR_CLS = ']'.freeze
156
+ # @private
157
+ COMMA = ', '.freeze
158
+ # @private
159
+ COLON = ' : '.freeze
160
+ # @private
161
+ QUOT = ?'.freeze
162
+ # @private
163
+ ESC_QUOT = "''".freeze
164
+ # @private
165
+ DBL_QUOT = ?".freeze
166
+ end
167
+ end
@@ -0,0 +1,104 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright 2013-2014 DataStax, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #++
18
+
19
+ module Cassandra
20
+ # Represents a UUID value.
21
+ #
22
+ # This is a very basic implementation of UUIDs and exists more or less just
23
+ # to encode and decode UUIDs from and to Cassandra.
24
+ #
25
+ # If you want to generate UUIDs see {Cassandra::TimeUuid::Generator}.
26
+ #
27
+ class Uuid
28
+ # Creates a new UUID either from a string (expected to be on the standard 8-4-4-4-12 form, or just 32 characters without hyphens), or from a 128 bit number.
29
+ #
30
+ # @param uuid [String] a 32 char uuid
31
+ #
32
+ # @raise [ArgumentError] if the string does not conform to the expected format
33
+ #
34
+ def initialize(uuid)
35
+ case uuid
36
+ when String
37
+ @n = from_s(uuid)
38
+ else
39
+ @n = uuid
40
+ end
41
+ end
42
+
43
+ # Returns a string representation of this UUID in the standard 8-4-4-4-12 form.
44
+ #
45
+ def to_s
46
+ @s ||= begin
47
+ s = RAW_FORMAT % @n
48
+ s.insert(20, HYPHEN)
49
+ s.insert(16, HYPHEN)
50
+ s.insert(12, HYPHEN)
51
+ s.insert( 8, HYPHEN)
52
+ s
53
+ end
54
+ end
55
+
56
+ def hash
57
+ @n.hash
58
+ end
59
+
60
+ # Returns the numerical representation of this UUID
61
+ #
62
+ # @return [Bignum] the 128 bit numerical representation
63
+ #
64
+ def value
65
+ @n
66
+ end
67
+ alias_method :to_i, :value
68
+
69
+ # @private
70
+ def eql?(other)
71
+ other.respond_to?(:value) && self.value == other.value
72
+ end
73
+ alias_method :==, :eql?
74
+
75
+ private
76
+
77
+ # @private
78
+ RAW_FORMAT = '%032x'.force_encoding(Encoding::ASCII).freeze
79
+ # @private
80
+ HYPHEN = '-'.force_encoding(Encoding::ASCII).freeze
81
+ # @private
82
+ EMPTY_STRING = ''.freeze
83
+
84
+ if RUBY_ENGINE == 'jruby'
85
+ # @private
86
+ HEX_RE = /^[A-Fa-f0-9]+$/
87
+ # See https://github.com/jruby/jruby/issues/1608
88
+ # @private
89
+ def from_s(str)
90
+ str = str.gsub(HYPHEN, EMPTY_STRING)
91
+ raise ArgumentError, "Expected 32 hexadecimal digits but got #{str.length}" unless str.length == 32
92
+ raise ArgumentError, "invalid value for Integer(): \"#{str}\"" unless str =~ HEX_RE
93
+ Integer(str, 16)
94
+ end
95
+ else
96
+ # @private
97
+ def from_s(str)
98
+ str = str.gsub(HYPHEN, EMPTY_STRING)
99
+ raise ArgumentError, "Expected 32 hexadecimal digits but got #{str.length}" unless str.length == 32
100
+ Integer(str, 16)
101
+ end
102
+ end
103
+ end
104
+ end