Class: EM::Tycoon::Protocol::Message
- Inherits:
-
Object
- Object
- EM::Tycoon::Protocol::Message
- Defined in:
- lib/em/tycoon/protocol/message.rb
Overview
Represents a Kyoto Tycoon binary protocol message See KT docs : fallabs.com/kyototycoon/spex.html#protocol
Direct Known Subclasses
Binary::ErrorMessage, Binary::GetMessage, Binary::PlayScriptMessage, Binary::RemoveMessage, Binary::SetMessage
Constant Summary collapse
- MAGIC =
{:set => 0xB8, :get => 0xBA, :remove => 0xB9, :play_script => 0xB4, :replication => 0xB1, :error => 0xBF}
- MSG_TYPES =
MAGIC.invert
- FLAGS =
{:no_reply => 0x01}
- DEFAULT_OPTS =
{ :no_reply => false }
- NO_EXPIRATION_TIME =
0x7FFFFFFFFFFFFFFF
- PARSE_PHASES =
[:magic,:item_count]
- NO_XT_HEX =
"7#{'F'*15}"
- KV_PACK_FMT =
"nNNH*a*a*"
Instance Attribute Summary collapse
-
#buffer ⇒ Object
readonly
Returns the value of attribute buffer.
-
#bytes_expected ⇒ Object
readonly
Returns the value of attribute bytes_expected.
-
#data ⇒ Object
readonly
The data payload of the KT message, which can either be empty, contain a hash of KV pairs, or a list of keys.
-
#item_count ⇒ Object
readonly
Number of items/KV pairs contained in KT message.
-
#keysize ⇒ Object
readonly
Total size, in bytes, of all key data contained in KT message.
-
#magic ⇒ Object
readonly
“Magic” number header from KT message, indicating message type.
-
#parse_phase ⇒ Object
readonly
Returns the value of attribute parse_phase.
-
#parsed ⇒ Object
readonly
Returns the value of attribute parsed.
-
#type ⇒ Object
The human-readable symbol version of the KT message type, as defined in the keys of Message::MAGIC.
-
#valuesize ⇒ Object
readonly
Total size, in bytes, of all value data contained in KT message.
Class Method Summary collapse
- .check_msg_type(type) ⇒ Object
- .generate(type, data, opts = {}) ⇒ Object
- .message_for(data) ⇒ Object
- .msg_type_for(data) ⇒ Object
Instance Method Summary collapse
- #[](key) ⇒ Object
-
#initialize(type, data = nil) ⇒ Message
constructor
Create a new KT message object to parse a response from KT or to serialize one to send, type indicates the message type being created, as defined by the keys of Message::MAGIC (e.g. :set, :get, etc.), and the optional data parameter can be used to specify the initial contents of the message, specific to the message type.
-
#parse(data) ⇒ Object
Parse an arbitrary blob of data, possibly containing an entire message, possibly part of it, possibly more than 1 returns the number of bytes from the buffer that were actually parsed and updates the #bytes_expected property accordingly.
-
#parse_chunk(data) ⇒ Object
Parse a Kyoto Tycoon binary protocol message part into this Message instance, returning the number of bytes parsed.
- #parsed? ⇒ Boolean
Constructor Details
#initialize(type, data = nil) ⇒ Message
Create a new KT message object to parse a response from KT or to serialize one to send, type indicates the message type being created, as defined by the keys of Message::MAGIC (e.g. :set, :get, etc.), and the optional data parameter can be used to specify the initial contents of the message, specific to the message type
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/em/tycoon/protocol/message.rb', line 43 def initialize(type,data=nil) self.class.check_msg_type(type) self.type = type @data = data @bytes_per_record = 0 @bytes_expected = 5 @keysize = @valuesize = 0 @parsed = false @buffer = String.new @parse_phase = PARSE_PHASES.first end |
Instance Attribute Details
#buffer ⇒ Object (readonly)
Returns the value of attribute buffer.
24 25 26 |
# File 'lib/em/tycoon/protocol/message.rb', line 24 def buffer @buffer end |
#bytes_expected ⇒ Object (readonly)
Returns the value of attribute bytes_expected.
24 25 26 |
# File 'lib/em/tycoon/protocol/message.rb', line 24 def bytes_expected @bytes_expected end |
#data ⇒ Object (readonly)
The data payload of the KT message, which can either be empty, contain a hash of KV pairs, or a list of keys
37 38 39 |
# File 'lib/em/tycoon/protocol/message.rb', line 37 def data @data end |
#item_count ⇒ Object (readonly)
Number of items/KV pairs contained in KT message
30 31 32 |
# File 'lib/em/tycoon/protocol/message.rb', line 30 def item_count @item_count end |
#keysize ⇒ Object (readonly)
Total size, in bytes, of all key data contained in KT message
32 33 34 |
# File 'lib/em/tycoon/protocol/message.rb', line 32 def keysize @keysize end |
#magic ⇒ Object (readonly)
“Magic” number header from KT message, indicating message type
28 29 30 |
# File 'lib/em/tycoon/protocol/message.rb', line 28 def magic @magic end |
#parse_phase ⇒ Object (readonly)
Returns the value of attribute parse_phase.
24 25 26 |
# File 'lib/em/tycoon/protocol/message.rb', line 24 def parse_phase @parse_phase end |
#parsed ⇒ Object (readonly)
Returns the value of attribute parsed.
24 25 26 |
# File 'lib/em/tycoon/protocol/message.rb', line 24 def parsed @parsed end |
#type ⇒ Object
The human-readable symbol version of the KT message type, as defined in the keys of Message::MAGIC
26 27 28 |
# File 'lib/em/tycoon/protocol/message.rb', line 26 def type @type end |
#valuesize ⇒ Object (readonly)
Total size, in bytes, of all value data contained in KT message
34 35 36 |
# File 'lib/em/tycoon/protocol/message.rb', line 34 def valuesize @valuesize end |
Class Method Details
.check_msg_type(type) ⇒ Object
135 136 137 |
# File 'lib/em/tycoon/protocol/message.rb', line 135 def check_msg_type(type) raise ArgumentError.new("Unknown message type #{type.inspect}") unless MAGIC.has_key?(type.downcase.to_sym) end |
.generate(type, data, opts = {}) ⇒ Object
128 129 130 131 132 133 |
# File 'lib/em/tycoon/protocol/message.rb', line 128 def generate(type, data, opts={}) check_msg_type(type) opts=DEFAULT_OPTS.merge(opts) classname = type.to_s.gsub(/^[a-z]|_[a-z]/) {|c| c.upcase}.gsub('_','') + "Message" Binary.const_get(classname).generate(data,opts) end |
.message_for(data) ⇒ Object
116 117 118 119 120 121 |
# File 'lib/em/tycoon/protocol/message.rb', line 116 def (data) msgtype = msg_type_for(data) raise ArgumentError.new("Unknown magic byte 0x#{('%02X' % data[0])}") unless msgtype classname = msgtype.to_s.gsub(/^[a-z]|_[a-z]/) {|c| c.upcase}.gsub('_','') + "Message" Binary.const_get(classname).new(data) end |
.msg_type_for(data) ⇒ Object
123 124 125 126 |
# File 'lib/em/tycoon/protocol/message.rb', line 123 def msg_type_for(data) magic = data.unpack("C").first MSG_TYPES[magic] end |
Instance Method Details
#[](key) ⇒ Object
109 110 111 |
# File 'lib/em/tycoon/protocol/message.rb', line 109 def [](key) @data[key] end |
#parse(data) ⇒ Object
Parse an arbitrary blob of data, possibly containing an entire message, possibly part of it, possibly more than 1 returns the number of bytes from the buffer that were actually parsed and updates the #bytes_expected property accordingly
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/em/tycoon/protocol/message.rb', line 65 def parse(data) return 0 unless data && data.bytesize > 0 if data.bytesize < @bytes_expected @buffer << data @bytes_expected -= data.bytesize return data.bytesize else @buffer << data[0..@bytes_expected] bytes_parsed = parse_chunk(@buffer) return 0 if bytes_parsed == 0 # This is an error @bytes_expected -= bytes_parsed @buffer = String.new if @bytes_expected == 0 @parsed = true elsif (data.bytesize-bytes_parsed) > 0 bytes_parsed += parse(data[bytes_parsed..-1]) end return bytes_parsed end end |
#parse_chunk(data) ⇒ Object
Parse a Kyoto Tycoon binary protocol message part into this Message instance, returning the number of bytes parsed. Default implementation supports standard magic+hits or just magic (in case of error message) messages
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/em/tycoon/protocol/message.rb', line 89 def parse_chunk(data) return 0 if data.nil? return 0 unless data.bytesize == @bytes_expected bytes_parsed = 0 if @bytes_expected > 1 @magic,@item_count = data.unpack("CN") bytes_parsed = 5 else @magic = data.unpack("C").first bytes_parsed = 1 end @data = @item_count @parse_phase = :item_count return bytes_parsed end |
#parsed? ⇒ Boolean
105 106 107 |
# File 'lib/em/tycoon/protocol/message.rb', line 105 def parsed? @parsed end |