Class: Dalli::Protocol::Base

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/dalli/protocol/base.rb

Overview

Base class for a single Memcached server, containing logic common to all protocols. Contains logic for managing connection state to the server and value handling.

Direct Known Subclasses

Meta

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attribs, client_options = {}) ⇒ Base

Returns a new instance of Base.



23
24
25
26
27
28
29
30
# File 'lib/dalli/protocol/base.rb', line 23

def initialize(attribs, client_options = {})
  hostname, port, socket_type, @weight, user_creds = ServerConfigParser.parse(attribs)
  warn_uri_credentials(user_creds)
  @options = client_options.merge(user_creds)
  @raw_mode = client_options[:raw]
  @value_marshaller = @raw_mode ? StringMarshaller.new(@options) : ValueMarshaller.new(@options)
  @connection_manager = ConnectionManager.new(hostname, port, socket_type, @options)
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



17
18
19
# File 'lib/dalli/protocol/base.rb', line 17

def options
  @options
end

#weightObject

Returns the value of attribute weight.



17
18
19
# File 'lib/dalli/protocol/base.rb', line 17

def weight
  @weight
end

Instance Method Details

#alive?Boolean

Boolean method used by clients of this class to determine if this particular memcached instance is available for use.

Returns:

  • (Boolean)


65
66
67
68
69
70
71
# File 'lib/dalli/protocol/base.rb', line 65

def alive?
  ensure_connected!
rescue Dalli::NetworkError
  # ensure_connected! raises a NetworkError if connection fails.  We
  # want to capture that error and convert it to a boolean value here.
  false
end

#lock!Object



73
# File 'lib/dalli/protocol/base.rb', line 73

def lock!; end

#pipeline_abortObject

Abort current pipelined get. Generally used to signal an external timeout during pipelined get. The underlying socket is disconnected, and the exception is swallowed.

Returns nothing.



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/dalli/protocol/base.rb', line 139

def pipeline_abort
  response_buffer.clear
  @connection_manager.abort_request!
  return true unless connected?

  # Closes the connection, which ensures that our connection
  # is in a clean state for future requests
  @connection_manager.error_on_request!('External timeout')
rescue NetworkError
  true
end

#pipeline_complete?Boolean

Did the last call to #pipeline_response_setup complete successfully?

Returns:

  • (Boolean)


152
153
154
# File 'lib/dalli/protocol/base.rb', line 152

def pipeline_complete?
  !response_buffer.in_progress?
end

#pipeline_next_responses(&block) ⇒ Object

Attempt to receive and parse as many key/value pairs as possible from this server. After #pipeline_response_setup, this should be invoked repeatedly whenever this server’s socket is readable until #pipeline_complete?.

When a block is given, yields (key, value, cas) for each response, avoiding intermediate Hash allocation. Returns nil. Without a block, returns a Hash of { key => [value, cas] }. rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/dalli/protocol/base.rb', line 99

def pipeline_next_responses(&block)
  reconnect_on_pipeline_complete!
  values = nil

  response_buffer.read

  status, cas, key, value = response_buffer.process_single_getk_response
  # status is not nil only if we have a full response to parse
  # in the buffer
  until status.nil?
    # If the status is ok and key is nil, then this is the response
    # to the noop at the end of the pipeline
    finish_pipeline && break if status && key.nil?

    # If the status is ok and the key is not nil, then this is a
    # getkq response with a value that we want to set in the response hash
    unless key.nil?
      if block
        yield key, value, cas
      else
        values ||= {}
        values[key] = [value, cas]
      end
    end

    # Get the next response from the buffer
    status, cas, key, value = response_buffer.process_single_getk_response
  end

  values || {}
rescue SystemCallError, *TIMEOUT_ERRORS, *SSL_ERRORS, EOFError => e
  @connection_manager.error_on_request!(e)
end

#pipeline_response_setupObject

Start reading key/value pairs from this connection. This is usually called after a series of GETKQ commands. A NOOP is sent, and the server begins flushing responses for kv pairs that were found.

Returns nothing.



82
83
84
85
86
87
88
# File 'lib/dalli/protocol/base.rb', line 82

def pipeline_response_setup
  verify_pipelined_state(:getkq)
  write_noop
  # Use ensure_ready instead of reset to preserve any data already buffered
  # during interleaved pipelined get draining
  response_buffer.ensure_ready
end

#quiet?Boolean Also known as: multi?

Returns:

  • (Boolean)


156
157
158
# File 'lib/dalli/protocol/base.rb', line 156

def quiet?
  Thread.current[::Dalli::QUIET]
end

#raw_mode?Boolean

Returns true if client is in raw mode (no serialization/compression). In raw mode, we can skip requesting bitflags from the server.

Returns:

  • (Boolean)


34
35
36
# File 'lib/dalli/protocol/base.rb', line 34

def raw_mode?
  @raw_mode
end

#request(opkey, *args) ⇒ Object

Chokepoint method for error handling and ensuring liveness



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/dalli/protocol/base.rb', line 39

def request(opkey, *args)
  verify_state(opkey)

  begin
    @connection_manager.start_request!
    response = send(opkey, *args)

    # pipelined_get/pipelined_get_interleaved emit query but don't read the response(s)
    @connection_manager.finish_request! unless %i[pipelined_get pipelined_get_interleaved].include?(opkey)

    response
  rescue Dalli::MarshalError => e
    log_marshal_err(args.first, e)
    raise
  rescue Dalli::DalliError
    raise
  rescue StandardError => e
    log_unexpected_err(e)
    close
    raise
  end
end

#unlock!Object



75
# File 'lib/dalli/protocol/base.rb', line 75

def unlock!; end