Documentation
¶
Overview ¶
Package protocol implements the text and binary wire protocols used by the celeris native Memcached driver.
Text protocol ¶
The text protocol is line-oriented ASCII. Storage commands carry a data block on the following line; retrieval commands return zero or more VALUE lines (each with an optional CAS), then the END sentinel. Responses are streamed via TextReader; the reader parses one logical reply at a time and returns ErrIncomplete when more bytes are needed.
Binary protocol ¶
See [binary.go]. Length-prefixed 24-byte header + optional extras/key/value body. Drivers choose text or binary at dial time.
Allocation discipline ¶
Both TextWriter and BinaryWriter expose a caller-supplied byte buffer via Reset — no per-call heap allocation in the steady state. The reader side feeds into an append-only internal buffer; VALUE payloads are sliced into the buffer and valid until the next Feed/Compact cycle.
Index ¶
- Constants
- Variables
- type BinaryHeader
- type BinaryPacket
- type BinaryReader
- type BinaryWriter
- func (w *BinaryWriter) AppendArith(opcode byte, key string, delta, initial uint64, exptime uint32, opaque uint32) []byte
- func (w *BinaryWriter) AppendConcat(opcode byte, key string, value []byte, cas uint64, opaque uint32) []byte
- func (w *BinaryWriter) AppendDelete(key string, cas uint64, opaque uint32) []byte
- func (w *BinaryWriter) AppendFlush(exptime uint32, opaque uint32) []byte
- func (w *BinaryWriter) AppendGAT(opcode byte, key string, exptime uint32, opaque uint32) []byte
- func (w *BinaryWriter) AppendGet(opcode byte, key string, opaque uint32) []byte
- func (w *BinaryWriter) AppendRequest(opcode byte, extras, key, value []byte, cas uint64, opaque uint32) []byte
- func (w *BinaryWriter) AppendSimple(opcode byte, opaque uint32) []byte
- func (w *BinaryWriter) AppendStats(arg string, opaque uint32) []byte
- func (w *BinaryWriter) AppendStorage(opcode byte, key string, value []byte, flags uint32, exptime uint32, ...) []byte
- func (w *BinaryWriter) AppendTouch(key string, exptime uint32, opaque uint32) []byte
- func (w *BinaryWriter) Bytes() []byte
- func (w *BinaryWriter) Reset()
- type Kind
- type TextReader
- type TextReply
- type TextWriter
- func (w *TextWriter) AppendArith(cmd, key string, delta uint64) []byte
- func (w *TextWriter) AppendDelete(key string) []byte
- func (w *TextWriter) AppendFlushAll(delay int64) []byte
- func (w *TextWriter) AppendRetrieval(cmd string, keys ...string) []byte
- func (w *TextWriter) AppendRetrievalTouch(cmd string, exptime int64, keys ...string) []byte
- func (w *TextWriter) AppendSimple(cmd string) []byte
- func (w *TextWriter) AppendStats(arg string) []byte
- func (w *TextWriter) AppendStorage(cmd, key string, flags uint32, exptime int64, data []byte, casID uint64, ...) []byte
- func (w *TextWriter) AppendTouch(key string, exptime int64) []byte
- func (w *TextWriter) Bytes() []byte
- func (w *TextWriter) Reset()
Constants ¶
const ( // BinHeaderLen is the fixed 24-byte binary-protocol header size. BinHeaderLen = 24 // MagicRequest marks a request packet (client → server). MagicRequest byte = 0x80 // MagicResponse marks a response packet (server → client). MagicResponse byte = 0x81 )
Binary-protocol constants. See https://github.com/memcached/memcached/wiki/BinaryProtocolRevamped.
const ( // OpGet retrieves a value (no extras on request). OpGet byte = 0x00 // OpSet stores a value (4-byte flags + 4-byte exptime extras on request). OpSet byte = 0x01 // OpAdd stores a value only if the key does not exist. OpAdd byte = 0x02 // OpReplace stores a value only if the key already exists. OpReplace byte = 0x03 // OpDelete removes a key. OpDelete byte = 0x04 // OpIncrement atomically adds to a counter. OpIncrement byte = 0x05 // OpDecrement atomically subtracts from a counter. OpDecrement byte = 0x06 // OpQuit closes the connection. OpQuit byte = 0x07 // OpFlush wipes all data (optional 4-byte expiration extras). OpFlush byte = 0x08 // OpGetQ is the quiet variant of GET (no reply on miss). OpGetQ byte = 0x09 // OpNoop is a no-op that forces a reply (used to terminate multi-get // pipelines made of OpGetQ packets). OpNoop byte = 0x0a // OpVersion returns the server version string as the value body. OpVersion byte = 0x0b // OpGetK is like OpGet but includes the key in the response body. OpGetK byte = 0x0c // OpGetKQ is the quiet variant of OpGetK. OpGetKQ byte = 0x0d // OpAppend appends to an existing value. OpAppend byte = 0x0e // OpPrepend prepends to an existing value. OpPrepend byte = 0x0f // OpStat requests server statistics (multi-reply terminated by a zero- // length key response). OpStat byte = 0x10 // OpTouch updates the expiration of a key without fetching the value. OpTouch byte = 0x1c // OpGAT gets a value and updates its expiration. OpGAT byte = 0x1d // OpGATQ is the quiet variant of OpGAT. OpGATQ byte = 0x1e )
Binary opcodes. Only the subset actually used by the driver is enumerated; the parser/encoder is still generic over the full 1-byte opcode range.
const ( // StatusOK indicates a successful reply. StatusOK uint16 = 0x0000 // StatusKeyNotFound indicates the key does not exist. StatusKeyNotFound uint16 = 0x0001 // StatusKeyExists indicates the key already exists or CAS mismatch. StatusKeyExists uint16 = 0x0002 // StatusValueTooLarge indicates the value exceeded the server's limit. StatusValueTooLarge uint16 = 0x0003 // StatusInvalidArgs indicates malformed request. StatusInvalidArgs uint16 = 0x0004 // StatusItemNotStored indicates add/replace preconditions failed. StatusItemNotStored uint16 = 0x0005 // StatusNonNumeric indicates incr/decr on a non-numeric value. StatusNonNumeric uint16 = 0x0006 // StatusUnknownCommand indicates an unknown opcode. StatusUnknownCommand uint16 = 0x0081 // StatusOutOfMemory indicates server-side OOM. StatusOutOfMemory uint16 = 0x0082 )
Binary status codes.
const MaxValueLen = 128 * 1024 * 1024
MaxValueLen caps the advertised length of a single VALUE data block. 128 MiB is above memcached's default 1 MiB per-item limit with plenty of headroom for servers raised via -I.
Variables ¶
var ErrIncomplete = errors.New("celeris-memcached-protocol: incomplete frame")
ErrIncomplete indicates the buffered input does not yet contain a complete reply. The reader's cursor is not advanced and the caller should feed more bytes and retry.
var ErrProtocol = errors.New("celeris-memcached-protocol: protocol error")
ErrProtocol is returned when server input cannot be parsed against either dialect (corrupted stream, unknown reply line, bad length header, ...).
Functions ¶
This section is empty.
Types ¶
type BinaryHeader ¶
type BinaryHeader struct {
Magic byte
Opcode byte
KeyLen uint16
ExtrasLen uint8
DataType uint8
VBucketOrSt uint16 // vbucket (request) or status (response)
BodyLen uint32
Opaque uint32
CAS uint64
}
BinaryHeader is the fixed 24-byte packet header. Magic + opcode + lengths + status/vbucket + opaque + CAS.
type BinaryPacket ¶
type BinaryPacket struct {
Header BinaryHeader
Extras []byte
Key []byte
Value []byte
}
BinaryPacket is one decoded binary-protocol packet. Extras/Key/Value slices alias the reader's internal buffer; copy before retaining past the next Feed/Compact cycle.
func (*BinaryPacket) Status ¶
func (p *BinaryPacket) Status() uint16
Status returns the response status (response packets only).
type BinaryReader ¶
type BinaryReader struct {
// contains filtered or unexported fields
}
BinaryReader streams binary-protocol packets.
func NewBinaryReader ¶
func NewBinaryReader() *BinaryReader
NewBinaryReader returns a ready-to-use BinaryReader.
func (*BinaryReader) Compact ¶
func (r *BinaryReader) Compact()
Compact discards already-parsed bytes.
func (*BinaryReader) Feed ¶
func (r *BinaryReader) Feed(data []byte)
Feed appends data to the internal buffer.
func (*BinaryReader) Next ¶
func (r *BinaryReader) Next() (BinaryPacket, error)
Next parses one complete packet. Returns ErrIncomplete if more bytes are needed; the read cursor is restored in that case.
func (*BinaryReader) Reset ¶
func (r *BinaryReader) Reset()
Reset clears internal state while retaining the buffer for reuse.
type BinaryWriter ¶
type BinaryWriter struct {
// contains filtered or unexported fields
}
BinaryWriter builds binary-protocol requests into a reusable byte buffer.
func NewBinaryWriter ¶
func NewBinaryWriter() *BinaryWriter
NewBinaryWriter returns a BinaryWriter with a small pre-allocated buffer.
func (*BinaryWriter) AppendArith ¶
func (w *BinaryWriter) AppendArith(opcode byte, key string, delta, initial uint64, exptime uint32, opaque uint32) []byte
AppendArith encodes an INCREMENT / DECREMENT packet. Extras are delta(8) + initial(8) + exptime(4) = 20 bytes, big-endian.
func (*BinaryWriter) AppendConcat ¶
func (w *BinaryWriter) AppendConcat(opcode byte, key string, value []byte, cas uint64, opaque uint32) []byte
AppendConcat encodes append/prepend which have no extras.
func (*BinaryWriter) AppendDelete ¶
func (w *BinaryWriter) AppendDelete(key string, cas uint64, opaque uint32) []byte
AppendDelete encodes a DELETE with no extras.
func (*BinaryWriter) AppendFlush ¶
func (w *BinaryWriter) AppendFlush(exptime uint32, opaque uint32) []byte
AppendFlush encodes a FLUSH packet with an optional exptime extra.
func (*BinaryWriter) AppendGAT ¶
AppendGAT encodes a Get-And-Touch (or GATQ) packet. Extras carry exptime(4).
func (*BinaryWriter) AppendGet ¶
func (w *BinaryWriter) AppendGet(opcode byte, key string, opaque uint32) []byte
AppendGet encodes a simple GET (or GetK) with no extras.
func (*BinaryWriter) AppendRequest ¶
func (w *BinaryWriter) AppendRequest(opcode byte, extras, key, value []byte, cas uint64, opaque uint32) []byte
AppendRequest encodes a request packet with the given opcode, extras, key, value, cas, and opaque. The buffer is appended to — call BinaryWriter.Reset to start a fresh packet.
func (*BinaryWriter) AppendSimple ¶
func (w *BinaryWriter) AppendSimple(opcode byte, opaque uint32) []byte
AppendSimple encodes a packet with no extras/key/value (e.g. version, noop, quit, stats-without-arg).
func (*BinaryWriter) AppendStats ¶
func (w *BinaryWriter) AppendStats(arg string, opaque uint32) []byte
AppendStats encodes STATS with an optional sub-statistic key.
func (*BinaryWriter) AppendStorage ¶
func (w *BinaryWriter) AppendStorage(opcode byte, key string, value []byte, flags uint32, exptime uint32, cas uint64, opaque uint32) []byte
AppendStorage encodes a storage-class request (set/add/replace). The 8-byte extras carry flags (4) + exptime (4), big-endian.
func (*BinaryWriter) AppendTouch ¶
func (w *BinaryWriter) AppendTouch(key string, exptime uint32, opaque uint32) []byte
AppendTouch encodes a TOUCH packet. Extras carry exptime(4).
func (*BinaryWriter) Bytes ¶
func (w *BinaryWriter) Bytes() []byte
Bytes returns the serialized buffer.
func (*BinaryWriter) Reset ¶
func (w *BinaryWriter) Reset()
Reset empties the internal buffer without freeing it.
type Kind ¶
type Kind uint8
Kind tags the flavor of a parsed text-protocol reply.
const ( // KindStored corresponds to "STORED\r\n". KindStored Kind = iota // KindNotStored corresponds to "NOT_STORED\r\n". KindNotStored // KindExists corresponds to "EXISTS\r\n" (CAS mismatch). KindExists // KindNotFound corresponds to "NOT_FOUND\r\n". KindNotFound // KindDeleted corresponds to "DELETED\r\n". KindDeleted // KindTouched corresponds to "TOUCHED\r\n". KindTouched // KindOK corresponds to "OK\r\n". KindOK // KindEnd corresponds to "END\r\n" and terminates a get/gets/stats reply. KindEnd // KindValue is a "VALUE <key> <flags> <bytes> [<cas>]\r\n<data>\r\n" block. KindValue // KindStat is a "STAT <name> <value>\r\n" line within a stats reply. KindStat // KindNumber is a decimal integer reply from incr/decr. KindNumber // KindVersion is a "VERSION <version>\r\n" reply. KindVersion // KindError is a generic "ERROR\r\n" reply (unknown command). KindError // KindClientError is a "CLIENT_ERROR <msg>\r\n" reply (malformed input). KindClientError // KindServerError is a "SERVER_ERROR <msg>\r\n" reply (server-side fault). KindServerError )
type TextReader ¶
type TextReader struct {
// contains filtered or unexported fields
}
TextReader streams text-protocol replies. The zero value is not usable; call NewTextReader.
func NewTextReader ¶
func NewTextReader() *TextReader
NewTextReader returns a ready-to-use TextReader.
func (*TextReader) Compact ¶
func (r *TextReader) Compact()
Compact discards already-parsed bytes. Aliased slices from previously returned replies become invalid after Compact.
func (*TextReader) Feed ¶
func (r *TextReader) Feed(data []byte)
Feed appends data to the internal buffer.
func (*TextReader) Next ¶
func (r *TextReader) Next() (TextReply, error)
Next parses one complete text-protocol reply. Returns ErrIncomplete if more bytes are needed; the read cursor is restored in that case.
func (*TextReader) Reset ¶
func (r *TextReader) Reset()
Reset clears internal state while retaining the buffer for reuse.
type TextReply ¶
type TextReply struct {
Kind Kind
Key []byte
Flags uint32
// CAS is the compare-and-swap token for VALUE blocks returned by gets/gats
// replies. Zero when the server did not advertise one.
CAS uint64
Int uint64
Data []byte
}
TextReply is one decoded text-protocol reply line (or VALUE block).
Depending on Kind, different fields are populated:
- KindValue: Key, Flags, CAS, Data.
- KindStat: Key (name), Data (value).
- KindNumber: Int.
- KindVersion: Data (version string).
- KindError / KindClientError / KindServerError: Data (message, may be empty).
- Scalars (Stored, Deleted, Touched, OK, End, ...): no extra fields.
type TextWriter ¶
type TextWriter struct {
// contains filtered or unexported fields
}
TextWriter builds text-protocol requests into a reusable byte buffer. The internal buffer is reset on every TextWriter.Reset call; callers that batch multiple commands should call Reset at the start of a batch and then use the Append* methods.
func NewTextWriter ¶
func NewTextWriter() *TextWriter
NewTextWriter returns a TextWriter with a small pre-allocated buffer.
func (*TextWriter) AppendArith ¶
func (w *TextWriter) AppendArith(cmd, key string, delta uint64) []byte
AppendArith encodes "incr <key> <delta>\r\n" or "decr <key> <delta>\r\n".
func (*TextWriter) AppendDelete ¶
func (w *TextWriter) AppendDelete(key string) []byte
AppendDelete encodes "delete <key>\r\n".
func (*TextWriter) AppendFlushAll ¶
func (w *TextWriter) AppendFlushAll(delay int64) []byte
AppendFlushAll encodes "flush_all[ <delay>]\r\n". Pass a negative delay to omit the argument.
func (*TextWriter) AppendRetrieval ¶
func (w *TextWriter) AppendRetrieval(cmd string, keys ...string) []byte
AppendRetrieval encodes "<cmd> <key1> <key2> ...\r\n". cmd is one of get / gets. gat/gats carry a leading exptime — see [AppendRetrievalTouch].
func (*TextWriter) AppendRetrievalTouch ¶
func (w *TextWriter) AppendRetrievalTouch(cmd string, exptime int64, keys ...string) []byte
AppendRetrievalTouch encodes "<cmd> <exptime> <key1> <key2> ...\r\n". cmd is one of gat / gats.
func (*TextWriter) AppendSimple ¶
func (w *TextWriter) AppendSimple(cmd string) []byte
AppendSimple encodes a single-word command like "version\r\n", "stats\r\n", or "quit\r\n".
func (*TextWriter) AppendStats ¶
func (w *TextWriter) AppendStats(arg string) []byte
AppendStats encodes "stats[ <arg>]\r\n".
func (*TextWriter) AppendStorage ¶
func (w *TextWriter) AppendStorage(cmd, key string, flags uint32, exptime int64, data []byte, casID uint64, noreply bool) []byte
AppendStorage encodes "<cmd> <key> <flags> <exptime> <bytes>[ <cas>][ noreply]\r\n<data>\r\n". cmd is one of: set, add, replace, append, prepend, cas. For cas commands, casID must be non-zero.
func (*TextWriter) AppendTouch ¶
func (w *TextWriter) AppendTouch(key string, exptime int64) []byte
AppendTouch encodes "touch <key> <exptime>\r\n".
func (*TextWriter) Reset ¶
func (w *TextWriter) Reset()
Reset empties the internal buffer without freeing it.