cassandra-driver 1.0.0.beta.3-java → 1.0.0-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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +51 -14
  3. data/lib/cassandra.rb +164 -78
  4. data/lib/cassandra/address_resolution.rb +36 -0
  5. data/lib/cassandra/address_resolution/policies.rb +2 -0
  6. data/lib/cassandra/address_resolution/policies/ec2_multi_region.rb +56 -0
  7. data/lib/cassandra/address_resolution/policies/none.rb +35 -0
  8. data/lib/cassandra/auth.rb +1 -1
  9. data/lib/cassandra/auth/providers/password.rb +1 -1
  10. data/lib/cassandra/cluster.rb +18 -5
  11. data/lib/cassandra/cluster/client.rb +175 -101
  12. data/lib/cassandra/{client/connection_manager.rb → cluster/connection_pool.rb} +5 -5
  13. data/lib/cassandra/cluster/connector.rb +142 -56
  14. data/lib/cassandra/cluster/control_connection.rb +385 -134
  15. data/lib/cassandra/{client/null_logger.rb → cluster/failed_connection.rb} +12 -14
  16. data/lib/cassandra/cluster/options.rb +13 -2
  17. data/lib/cassandra/cluster/registry.rb +19 -9
  18. data/lib/cassandra/column.rb +5 -0
  19. data/lib/cassandra/compression.rb +1 -1
  20. data/lib/cassandra/compression/compressors/lz4.rb +1 -1
  21. data/lib/cassandra/compression/compressors/snappy.rb +1 -1
  22. data/lib/cassandra/driver.rb +29 -21
  23. data/lib/cassandra/errors.rb +325 -35
  24. data/lib/cassandra/execution/options.rb +13 -6
  25. data/lib/cassandra/execution/trace.rb +4 -4
  26. data/lib/cassandra/future.rb +7 -3
  27. data/lib/cassandra/keyspace.rb +5 -0
  28. data/lib/cassandra/load_balancing/policies/dc_aware_round_robin.rb +13 -4
  29. data/lib/cassandra/load_balancing/policies/token_aware.rb +2 -4
  30. data/lib/cassandra/load_balancing/policies/white_list.rb +3 -6
  31. data/lib/cassandra/null_logger.rb +35 -0
  32. data/lib/cassandra/protocol.rb +0 -16
  33. data/lib/cassandra/protocol/cql_byte_buffer.rb +18 -18
  34. data/lib/cassandra/protocol/cql_protocol_handler.rb +78 -8
  35. data/lib/cassandra/protocol/frame_decoder.rb +2 -2
  36. data/lib/cassandra/protocol/frame_encoder.rb +1 -1
  37. data/lib/cassandra/protocol/requests/query_request.rb +1 -11
  38. data/lib/cassandra/protocol/response.rb +1 -1
  39. data/lib/cassandra/protocol/responses/detailed_error_response.rb +16 -1
  40. data/lib/cassandra/protocol/responses/error_response.rb +17 -0
  41. data/lib/cassandra/protocol/responses/event_response.rb +1 -1
  42. data/lib/cassandra/protocol/responses/raw_rows_result_response.rb +1 -1
  43. data/lib/cassandra/protocol/responses/result_response.rb +1 -1
  44. data/lib/cassandra/protocol/responses/rows_result_response.rb +1 -1
  45. data/lib/cassandra/protocol/type_converter.rb +4 -3
  46. data/lib/cassandra/reconnection.rb +1 -1
  47. data/lib/cassandra/result.rb +4 -6
  48. data/lib/cassandra/retry.rb +3 -5
  49. data/lib/cassandra/session.rb +14 -5
  50. data/lib/cassandra/statements/prepared.rb +5 -1
  51. data/lib/cassandra/table.rb +6 -1
  52. data/lib/cassandra/time_uuid.rb +21 -83
  53. data/lib/cassandra/util.rb +131 -1
  54. data/lib/cassandra/uuid.rb +6 -4
  55. data/lib/cassandra/uuid/generator.rb +207 -0
  56. data/lib/cassandra/version.rb +1 -1
  57. data/lib/cassandra_murmur3.jar +0 -0
  58. metadata +43 -49
  59. data/lib/cassandra/client.rb +0 -144
  60. data/lib/cassandra/client/batch.rb +0 -212
  61. data/lib/cassandra/client/client.rb +0 -591
  62. data/lib/cassandra/client/column_metadata.rb +0 -54
  63. data/lib/cassandra/client/connector.rb +0 -277
  64. data/lib/cassandra/client/execute_options_decoder.rb +0 -59
  65. data/lib/cassandra/client/peer_discovery.rb +0 -50
  66. data/lib/cassandra/client/prepared_statement.rb +0 -314
  67. data/lib/cassandra/client/query_result.rb +0 -230
  68. data/lib/cassandra/client/request_runner.rb +0 -71
  69. data/lib/cassandra/client/result_metadata.rb +0 -48
  70. data/lib/cassandra/client/void_result.rb +0 -78
@@ -47,7 +47,7 @@ module Cassandra
47
47
 
48
48
  def actual_decode(buffer, fields, size)
49
49
  if (fields >> 24) & 0x80 == 0
50
- raise UnsupportedFrameTypeError, 'Request frames are not supported'
50
+ raise Errors::DecodingError, 'Request frames are not supported'
51
51
  end
52
52
  protocol_version = (fields >> 24) & 0x7f
53
53
  compression = (fields >> 16) & 0x01
@@ -78,7 +78,7 @@ module Cassandra
78
78
  compressed_body = buffer.read(size)
79
79
  CqlByteBuffer.new(@compressor.decompress(compressed_body))
80
80
  else
81
- raise UnexpectedCompressionError, 'Compressed frame received, but no compressor configured'
81
+ raise Errors::DecodingError, 'Compressed frame received, but no compressor configured'
82
82
  end
83
83
  end
84
84
 
@@ -26,7 +26,7 @@ module Cassandra
26
26
  end
27
27
 
28
28
  def encode_frame(request, stream_id=0, buffer=nil)
29
- raise InvalidStreamIdError, 'The stream ID must be between 0 and 127' unless 0 <= stream_id && stream_id < 128
29
+ raise EncodingError, 'The stream ID must be between 0 and 127' unless 0 <= stream_id && stream_id < 128
30
30
  buffer ||= CqlByteBuffer.new
31
31
  flags = request.trace? ? 2 : 0
32
32
  body = request.write(@protocol_version, CqlByteBuffer.new)
@@ -39,11 +39,7 @@ module Cassandra
39
39
  end
40
40
 
41
41
  def write(protocol_version, buffer)
42
- if protocol_version > 1
43
- buffer.append_long_string(@cql)
44
- else
45
- buffer.append_long_string(serialized_cql)
46
- end
42
+ buffer.append_long_string(@cql)
47
43
  buffer.append_consistency(@consistency)
48
44
  if protocol_version > 1
49
45
  flags = 0
@@ -108,12 +104,6 @@ module Cassandra
108
104
 
109
105
  private
110
106
 
111
- def serialized_cql
112
- return @cql if @values.nil? || @values.empty?
113
- i = -1
114
- @cql.gsub('?') { Util.encode(@values[i += 1]) }
115
- end
116
-
117
107
  def self.guess_type(value)
118
108
  type = TYPE_GUESSES[value.class]
119
109
  if type == :map
@@ -24,7 +24,7 @@ module Cassandra
24
24
  if response_class
25
25
  response_class.decode(protocol_version, buffer, length, trace_id)
26
26
  else
27
- raise UnsupportedOperationError, "The operation #{opcode} is not supported"
27
+ raise Errors::DecodingError, "Unsupported opcode #{opcode.inspect}"
28
28
  end
29
29
  end
30
30
 
@@ -37,7 +37,10 @@ module Cassandra
37
37
  details[:cl] = buffer.read_consistency
38
38
  details[:received] = buffer.read_int
39
39
  details[:blockfor] = buffer.read_int
40
- details[:write_type] = buffer.read_string
40
+ write_type = buffer.read_string
41
+ write_type.downcase!
42
+
43
+ details[:write_type] = write_type.to_sym
41
44
  when 0x1200 # read_timeout
42
45
  details[:cl] = buffer.read_consistency
43
46
  details[:received] = buffer.read_int
@@ -52,6 +55,18 @@ module Cassandra
52
55
  new(code, message, details)
53
56
  end
54
57
 
58
+ def to_error(statement = nil)
59
+ case code
60
+ when 0x1000 then Errors::UnavailableError.new(@message, statement, @details[:cl], @details[:required], @details[:alive])
61
+ when 0x1100 then Errors::WriteTimeoutError.new(@message, statement, @details[:write_type], @details[:cl], @details[:blockfor], @details[:received])
62
+ when 0x1200 then Errors::ReadTimeoutError.new(@message, statement, @details[:data_present], @details[:cl], @details[:blockfor], @details[:received])
63
+ when 0x2400 then Errors::AlreadyExistsError.new(@message, statement, @details[:ks], @details[:table])
64
+ when 0x2500 then Errors::UnpreparedError.new(@message, statement, @details[:id])
65
+ else
66
+ super
67
+ end
68
+ end
69
+
55
70
  def to_s
56
71
  "#{super} #{@details}"
57
72
  end
@@ -42,6 +42,23 @@ module Cassandra
42
42
  %(ERROR 0x#{hex_code} "#@message")
43
43
  end
44
44
 
45
+ def to_error(statement = nil)
46
+ case @code
47
+ when 0x0000 then Errors::ServerError.new(@message)
48
+ when 0x000A then Errors::ProtocolError.new(@message)
49
+ when 0x0100 then Errors::AuthenticationError.new(@message)
50
+ when 0x1001 then Errors::OverloadedError.new(@message, statement)
51
+ when 0x1002 then Errors::IsBootstrappingError.new(@message, statement)
52
+ when 0x1003 then Errors::TruncateError.new(@message, statement)
53
+ when 0x2000 then Errors::SyntaxError.new(@message, statement)
54
+ when 0x2100 then Errors::UnauthorizedError.new(@message, statement)
55
+ when 0x2200 then Errors::InvalidError.new(@message, statement)
56
+ when 0x2300 then Errors::ConfigurationError.new(@message, statement)
57
+ else
58
+ Errors::ServerError.new(@message)
59
+ end
60
+ end
61
+
45
62
  private
46
63
 
47
64
  RESPONSE_TYPES[0x00] = self
@@ -22,7 +22,7 @@ module Cassandra
22
22
  def self.decode(protocol_version, buffer, length, trace_id=nil)
23
23
  type = buffer.read_string
24
24
  impl = EVENT_TYPES[type]
25
- raise UnsupportedEventTypeError, %(Unsupported event type: "#{type}") unless impl
25
+ raise Errors::DecodingError, %(Unsupported event type: "#{type}") unless impl
26
26
  new_length = length - 4 - type.bytesize
27
27
  impl.decode(protocol_version, buffer, new_length, trace_id)
28
28
  end
@@ -31,7 +31,7 @@ module Cassandra
31
31
  end
32
32
 
33
33
  def rows
34
- raise UnmaterializedRowsError, 'Not materialized!' unless @rows
34
+ raise Errors::DecodingError, 'Not materialized!' unless @rows
35
35
  @rows
36
36
  end
37
37
 
@@ -28,7 +28,7 @@ module Cassandra
28
28
  def self.decode(protocol_version, buffer, length, trace_id=nil)
29
29
  kind = buffer.read_int
30
30
  impl = RESULT_TYPES[kind]
31
- raise UnsupportedResultKindError, %(Unsupported result kind: #{kind}) unless impl
31
+ raise Errors::DecodingError, %(Unsupported result kind: #{kind}) unless impl
32
32
  impl.decode(protocol_version, buffer, length - 4, trace_id)
33
33
  end
34
34
 
@@ -87,7 +87,7 @@ module Cassandra
87
87
  sub_type = read_column_type(buffer)
88
88
  [:set, sub_type]
89
89
  else
90
- raise UnsupportedColumnTypeError, %(Unsupported column type: #{id})
90
+ raise Errors::DecodingError, %(Unsupported column type: #{id})
91
91
  end
92
92
  end
93
93
  type
@@ -46,7 +46,7 @@ module Cassandra
46
46
  case type
47
47
  when Array
48
48
  unless value.nil? || value.is_a?(Enumerable)
49
- raise InvalidValueError, 'Value for collection must be enumerable'
49
+ raise EncodingError, 'Value for collection must be enumerable'
50
50
  end
51
51
  case type.first
52
52
  when :list, :set
@@ -75,12 +75,12 @@ module Cassandra
75
75
  nil_to_bytes(buffer, size_bytes)
76
76
  end
77
77
  else
78
- raise UnsupportedColumnTypeError, %(Unsupported column collection type: #{type.first})
78
+ raise EncodingError, %(Unsupported column collection type: #{type.first})
79
79
  end
80
80
  else
81
81
  converter = @to_bytes_converters[type]
82
82
  unless converter
83
- raise UnsupportedColumnTypeError, %(Unsupported column type: #{type})
83
+ raise EncodingError, %(Unsupported column type: #{type})
84
84
  end
85
85
  converter.call(buffer, value, size_bytes)
86
86
  end
@@ -140,6 +140,7 @@ module Cassandra
140
140
  size = buffer.read_signed_int
141
141
  return nil if size & 0x80000000 == 0x80000000
142
142
  end
143
+ return nil if size.zero?
143
144
  size
144
145
  end
145
146
 
@@ -30,7 +30,7 @@ module Cassandra
30
30
 
31
31
  # A reconnection policy
32
32
  # @abstract Actual reconnection policies supplied as `:reconnection_policy`
33
- # option to {Cassandra.connect} don't need to inherit this class, only
33
+ # option to {Cassandra.cluster} don't need to inherit this class, only
34
34
  # implement its methods. This class exists for documentation purposes
35
35
  # only.
36
36
  class Policy
@@ -180,10 +180,9 @@ module Cassandra
180
180
  # Returns true when there are no more pages to load.
181
181
  #
182
182
  # This is only relevant when you have requested paging of the results with
183
- # the `:page_size` option to {Cassandra::Client::Client#execute} or
184
- # {Cassandra::Client::PreparedStatement#execute}.
183
+ # the `:page_size` option to {Cassandra::Session#execute}.
185
184
  #
186
- # @see Cassandra::Client::Client#execute
185
+ # @see Cassandra::Session#execute
187
186
  def last_page?
188
187
  true
189
188
  end
@@ -191,10 +190,9 @@ module Cassandra
191
190
  # Returns the next page or nil when there is no next page.
192
191
  #
193
192
  # This is only relevant when you have requested paging of the results with
194
- # the `:page_size` option to {Cassandra::Client::Client#execute} or
195
- # {Cassandra::Client::PreparedStatement#execute}.
193
+ # the `:page_size` option to {Cassandra::Session#execute_async}.
196
194
  #
197
- # @see Cassandra::Client::Client#execute
195
+ # @see Cassandra::Session#execute_async
198
196
  def next_page_async(options = nil)
199
197
  @futures.value(nil)
200
198
  end
@@ -19,7 +19,7 @@
19
19
  module Cassandra
20
20
  module Retry
21
21
  # @abstract Actual retry policies supplied as `:retry_policy` option to
22
- # {Cassandra.connect} don't need to inherit this class, only implement
22
+ # {Cassandra.cluster} don't need to inherit this class, only implement
23
23
  # its methods. This class exists for documentation purposes only.
24
24
  module Policy
25
25
  # Decides wether to retry a read and at what consistency level.
@@ -51,8 +51,7 @@ module Cassandra
51
51
  # @param statement [Cassandra::Statement] the original statement that timed out
52
52
  # @param consistency [Symbol] the original consistency level for the
53
53
  # request, one of {Cassandra::CONSISTENCIES}
54
- # @param type [Symbol] One of `:simple`, `:batch`, `:unlogged_batch`,
55
- # `:counter` or `:batch_log`
54
+ # @param type [Symbol] One of {Cassandra::WRITE_TYPES}
56
55
  # @param required [Integer] the number of acks required to achieve
57
56
  # requested consistency level
58
57
  # @param received [Integer] the number of acks received by the time the
@@ -75,8 +74,7 @@ module Cassandra
75
74
  # request, one of {Cassandra::CONSISTENCIES}
76
75
  # @param required [Integer] the number of replicas required to achieve
77
76
  # requested consistency level
78
- # @param alive [Integer] the number of replicas received by the time the
79
- # query timed out
77
+ # @param alive [Integer] the number of replicas available for the request
80
78
  # @param retries [Integer] the number of retries already performed
81
79
  #
82
80
  # @return [Cassandra::Policies::Retry::Decision] a retry decision
@@ -54,14 +54,20 @@ module Cassandra
54
54
  # relevant for conditional updates and specifies a serial consistency to
55
55
  # be used, one of {Cassandra::SERIAL_CONSISTENCIES}
56
56
  #
57
- # @see Cassandra.connect for description of options that can be specified
58
- # on the cluster-level as well as default values chosen.
57
+ # @see Cassandra.cluster Options that can be specified on the cluster-level
58
+ # and their default values.
59
59
  #
60
60
  # @note Last argument will be treated as `options` if it is a {Hash}.
61
61
  # Therefore, make sure to pass empty `options` when executing a statement
62
62
  # with the last parameter required to be a map datatype.
63
63
  #
64
+ # @note Positional arguments are only supported on Apache Cassandra 2.0 and
65
+ # above.
66
+ #
64
67
  # @return [Cassandra::Future<Cassandra::Result>]
68
+ #
69
+ # @see Cassandra::Session#execute A list of errors this future can be
70
+ # resolved with
65
71
  def execute_async(statement, *args)
66
72
  if args.last.is_a?(::Hash)
67
73
  options = @options.override(args.pop)
@@ -91,8 +97,11 @@ module Cassandra
91
97
  # @see Cassandra::Future#get
92
98
  #
93
99
  # @return [Cassandra::Result] query result
94
- # @raise [Cassandra::Errors::NoHostsAvailable] if none of the hosts can be reached
95
- # @raise [Cassandra::Errors::QueryError] if Cassandra returns an error response
100
+ # @raise [Cassandra::Errors::NoHostsAvailable] if all hosts fail
101
+ # @raise [Cassandra::Errors::ExecutionError] if Cassandra fails to execute
102
+ # @raise [Cassandra::Errors::ValidationError] if Cassandra fails to validate
103
+ # @raise [Cassandra::Errors::TimeoutError] if request has not completed
104
+ # within the `:timeout` given
96
105
  def execute(*args)
97
106
  execute_async(*args).get
98
107
  end
@@ -131,7 +140,7 @@ module Cassandra
131
140
  #
132
141
  # @return [Cassandra::Statements::Prepared] prepared statement
133
142
  # @raise [Cassandra::Errors::NoHostsAvailable] if none of the hosts can be reached
134
- # @raise [Cassandra::Errors::QueryError] if Cassandra returns an error response
143
+ # @raise [Cassandra::Errors::ExecutionError] if Cassandra returns an error response
135
144
  def prepare(*args)
136
145
  prepare_async(*args).get
137
146
  end
@@ -50,7 +50,11 @@ module Cassandra
50
50
  # original cql passed to {Cassandra::Session#prepare}
51
51
  # @return [Cassandra::Statements::Bound] bound statement
52
52
  def bind(*args)
53
- raise ::ArgumentError, "expecting exactly #{@params_metadata.size} bind parameters, #{args.size} given" if args.size != @params_metadata.size
53
+ Util.assert_equal(@params_metadata.size, args.size) { "expecting exactly #{@params_metadata.size} bind parameters, #{args.size} given" }
54
+
55
+ @params_metadata.each_with_index do |metadata, i|
56
+ Util.assert_type(metadata[3], args[i]) { "argument for #{metadata[2].inspect} must be #{metadata[3].inspect}, #{args[i]} given" }
57
+ end
54
58
 
55
59
  return Bound.new(@cql, @params_metadata, @result_metadata, args) if @params_metadata.empty?
56
60
 
@@ -231,6 +231,11 @@ module Cassandra
231
231
  cql << ';'
232
232
  end
233
233
 
234
+ # @return [String] a CLI-friendly table representation
235
+ def inspect
236
+ "#<#{self.class.name}:0x#{self.object_id.to_s(16)} @keyspace=#{@keyspace} @name=#{@name}>"
237
+ end
238
+
234
239
  # @return [Boolean] whether this table is equal to the other
235
240
  def eql?(other)
236
241
  other.is_a?(Table) &&
@@ -247,7 +252,7 @@ module Cassandra
247
252
  # @private
248
253
  def create_partition_key(values)
249
254
  partition_key = @partition_key
250
- return nil unless partition_key.size == values.size
255
+ return nil if partition_key.size > values.size
251
256
 
252
257
  if partition_key.one?
253
258
  column = partition_key.first
@@ -19,6 +19,7 @@
19
19
  module Cassandra
20
20
  # A variant of UUID which can extract its time component.
21
21
  #
22
+ # You can use {Cassandra::Uuid::Generator} to generate {Cassandra::TimeUuid}s
22
23
  class TimeUuid < Uuid
23
24
  include Comparable
24
25
 
@@ -29,18 +30,37 @@ module Cassandra
29
30
  t = time_bits - GREGORIAN_OFFSET
30
31
  seconds = t/10_000_000
31
32
  microseconds = (t - seconds * 10_000_000)/10.0
33
+
32
34
  Time.at(seconds, microseconds).utc
33
35
  end
34
36
 
37
+ # Returns the date component from this UUID as Date.
38
+ #
39
+ # This just sugar around {#to_time}
40
+ #
41
+ # @return [Date]
42
+ def to_date
43
+ to_time.to_date
44
+ end
45
+
46
+ # Compares this timeuuid with another timeuuid
47
+ #
48
+ # @param other [Cassandra::TimeUuid] another timeuuid to compare
49
+ # @see Comparable
50
+ #
51
+ # @return [nil] when other is not a {Cassandra::Uuid}
52
+ # @return [Integer] `-1` when less than `other`, `0` when equal to `other`
53
+ # and `1` when greater than `other`
35
54
  def <=>(other)
36
55
  return nil unless other.kind_of?(Cassandra::Uuid)
37
56
  c = self.value <=> other.value
38
- return c if c == 0
57
+ return c if c == 0 || !other.is_a?(Cassandra::TimeUuid)
39
58
  self.time_bits <=> other.time_bits
40
59
  end
41
60
 
42
61
  protected
43
62
 
63
+ # @private
44
64
  def time_bits
45
65
  n = (value >> 64)
46
66
  t = 0
@@ -54,88 +74,6 @@ module Cassandra
54
74
 
55
75
  # @private
56
76
  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
77
  # @private
140
78
  GREGORIAN_OFFSET = 122192928000000000
141
79
  end