Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
364 lines
12 KiB
364 lines
12 KiB
// Package gomemcached is binary protocol packet formats and constants. |
|
package gomemcached |
|
|
|
import ( |
|
"fmt" |
|
) |
|
|
|
const ( |
|
REQ_MAGIC = 0x80 |
|
RES_MAGIC = 0x81 |
|
FLEX_MAGIC = 0x08 |
|
FLEX_RES_MAGIC = 0x18 |
|
) |
|
|
|
// CommandCode for memcached packets. |
|
type CommandCode uint8 |
|
|
|
const ( |
|
GET = CommandCode(0x00) |
|
SET = CommandCode(0x01) |
|
ADD = CommandCode(0x02) |
|
REPLACE = CommandCode(0x03) |
|
DELETE = CommandCode(0x04) |
|
INCREMENT = CommandCode(0x05) |
|
DECREMENT = CommandCode(0x06) |
|
QUIT = CommandCode(0x07) |
|
FLUSH = CommandCode(0x08) |
|
GETQ = CommandCode(0x09) |
|
NOOP = CommandCode(0x0a) |
|
VERSION = CommandCode(0x0b) |
|
GETK = CommandCode(0x0c) |
|
GETKQ = CommandCode(0x0d) |
|
APPEND = CommandCode(0x0e) |
|
PREPEND = CommandCode(0x0f) |
|
STAT = CommandCode(0x10) |
|
SETQ = CommandCode(0x11) |
|
ADDQ = CommandCode(0x12) |
|
REPLACEQ = CommandCode(0x13) |
|
DELETEQ = CommandCode(0x14) |
|
INCREMENTQ = CommandCode(0x15) |
|
DECREMENTQ = CommandCode(0x16) |
|
QUITQ = CommandCode(0x17) |
|
FLUSHQ = CommandCode(0x18) |
|
APPENDQ = CommandCode(0x19) |
|
AUDIT = CommandCode(0x27) |
|
PREPENDQ = CommandCode(0x1a) |
|
GAT = CommandCode(0x1d) |
|
HELLO = CommandCode(0x1f) |
|
RGET = CommandCode(0x30) |
|
RSET = CommandCode(0x31) |
|
RSETQ = CommandCode(0x32) |
|
RAPPEND = CommandCode(0x33) |
|
RAPPENDQ = CommandCode(0x34) |
|
RPREPEND = CommandCode(0x35) |
|
RPREPENDQ = CommandCode(0x36) |
|
RDELETE = CommandCode(0x37) |
|
RDELETEQ = CommandCode(0x38) |
|
RINCR = CommandCode(0x39) |
|
RINCRQ = CommandCode(0x3a) |
|
RDECR = CommandCode(0x3b) |
|
RDECRQ = CommandCode(0x3c) |
|
|
|
SASL_LIST_MECHS = CommandCode(0x20) |
|
SASL_AUTH = CommandCode(0x21) |
|
SASL_STEP = CommandCode(0x22) |
|
|
|
SET_VBUCKET = CommandCode(0x3d) |
|
|
|
TAP_CONNECT = CommandCode(0x40) // Client-sent request to initiate Tap feed |
|
TAP_MUTATION = CommandCode(0x41) // Notification of a SET/ADD/REPLACE/etc. on the server |
|
TAP_DELETE = CommandCode(0x42) // Notification of a DELETE on the server |
|
TAP_FLUSH = CommandCode(0x43) // Replicates a flush_all command |
|
TAP_OPAQUE = CommandCode(0x44) // Opaque control data from the engine |
|
TAP_VBUCKET_SET = CommandCode(0x45) // Sets state of vbucket in receiver (used in takeover) |
|
TAP_CHECKPOINT_START = CommandCode(0x46) // Notifies start of new checkpoint |
|
TAP_CHECKPOINT_END = CommandCode(0x47) // Notifies end of checkpoint |
|
GET_ALL_VB_SEQNOS = CommandCode(0x48) // Get current high sequence numbers from all vbuckets located on the server |
|
|
|
UPR_OPEN = CommandCode(0x50) // Open a UPR connection with a name |
|
UPR_ADDSTREAM = CommandCode(0x51) // Sent by ebucketMigrator to UPR Consumer |
|
UPR_CLOSESTREAM = CommandCode(0x52) // Sent by eBucketMigrator to UPR Consumer |
|
UPR_FAILOVERLOG = CommandCode(0x54) // Request failover logs |
|
UPR_STREAMREQ = CommandCode(0x53) // Stream request from consumer to producer |
|
UPR_STREAMEND = CommandCode(0x55) // Sent by producer when it has no more messages to stream |
|
UPR_SNAPSHOT = CommandCode(0x56) // Start of a new snapshot |
|
UPR_MUTATION = CommandCode(0x57) // Key mutation |
|
UPR_DELETION = CommandCode(0x58) // Key deletion |
|
UPR_EXPIRATION = CommandCode(0x59) // Key expiration |
|
UPR_FLUSH = CommandCode(0x5a) // Delete all the data for a vbucket |
|
UPR_NOOP = CommandCode(0x5c) // UPR NOOP |
|
UPR_BUFFERACK = CommandCode(0x5d) // UPR Buffer Acknowledgement |
|
UPR_CONTROL = CommandCode(0x5e) // Set flow control params |
|
|
|
SELECT_BUCKET = CommandCode(0x89) // Select bucket |
|
|
|
OBSERVE_SEQNO = CommandCode(0x91) // Sequence Number based Observe |
|
OBSERVE = CommandCode(0x92) |
|
|
|
GET_META = CommandCode(0xA0) // Get meta. returns with expiry, flags, cas etc |
|
GET_COLLECTIONS_MANIFEST = CommandCode(0xba) // Get entire collections manifest. |
|
COLLECTIONS_GET_CID = CommandCode(0xbb) // Get collection id. |
|
SUBDOC_GET = CommandCode(0xc5) // Get subdoc. Returns with xattrs |
|
SUBDOC_MULTI_LOOKUP = CommandCode(0xd0) // Multi lookup. Doc xattrs and meta. |
|
|
|
DCP_SYSTEM_EVENT = CommandCode(0x5f) // A system event has occurred |
|
DCP_SEQNO_ADV = CommandCode(0x64) // Sent when the vb seqno has advanced due to an unsubscribed event |
|
DCP_OSO_SNAPSHOT = CommandCode(0x65) // Marks the begin and end of out-of-sequence-number stream |
|
) |
|
|
|
// command codes that are counted toward DCP control buffer |
|
// when DCP clients receive DCP messages with these command codes, they need to provide acknowledgement |
|
var BufferedCommandCodeMap = map[CommandCode]bool{ |
|
SET_VBUCKET: true, |
|
UPR_STREAMEND: true, |
|
UPR_SNAPSHOT: true, |
|
UPR_MUTATION: true, |
|
UPR_DELETION: true, |
|
UPR_EXPIRATION: true, |
|
DCP_SYSTEM_EVENT: true, |
|
DCP_SEQNO_ADV: true, |
|
DCP_OSO_SNAPSHOT: true, |
|
} |
|
|
|
// Status field for memcached response. |
|
type Status uint16 |
|
|
|
// Matches with protocol_binary.h as source of truth |
|
const ( |
|
SUCCESS = Status(0x00) |
|
KEY_ENOENT = Status(0x01) |
|
KEY_EEXISTS = Status(0x02) |
|
E2BIG = Status(0x03) |
|
EINVAL = Status(0x04) |
|
NOT_STORED = Status(0x05) |
|
DELTA_BADVAL = Status(0x06) |
|
NOT_MY_VBUCKET = Status(0x07) |
|
NO_BUCKET = Status(0x08) |
|
LOCKED = Status(0x09) |
|
AUTH_STALE = Status(0x1f) |
|
AUTH_ERROR = Status(0x20) |
|
AUTH_CONTINUE = Status(0x21) |
|
ERANGE = Status(0x22) |
|
ROLLBACK = Status(0x23) |
|
EACCESS = Status(0x24) |
|
NOT_INITIALIZED = Status(0x25) |
|
UNKNOWN_COMMAND = Status(0x81) |
|
ENOMEM = Status(0x82) |
|
NOT_SUPPORTED = Status(0x83) |
|
EINTERNAL = Status(0x84) |
|
EBUSY = Status(0x85) |
|
TMPFAIL = Status(0x86) |
|
UNKNOWN_COLLECTION = Status(0x88) |
|
|
|
SYNC_WRITE_IN_PROGRESS = Status(0xa2) |
|
SYNC_WRITE_AMBIGUOUS = Status(0xa3) |
|
|
|
// SUBDOC |
|
SUBDOC_PATH_NOT_FOUND = Status(0xc0) |
|
SUBDOC_BAD_MULTI = Status(0xcc) |
|
SUBDOC_MULTI_PATH_FAILURE_DELETED = Status(0xd3) |
|
|
|
// Not a Memcached status |
|
UNKNOWN_STATUS = Status(0xffff) |
|
) |
|
|
|
// for log redaction |
|
const ( |
|
UdTagBegin = "<ud>" |
|
UdTagEnd = "</ud>" |
|
) |
|
|
|
var isFatal = map[Status]bool{ |
|
DELTA_BADVAL: true, |
|
NO_BUCKET: true, |
|
AUTH_STALE: true, |
|
AUTH_ERROR: true, |
|
ERANGE: true, |
|
ROLLBACK: true, |
|
EACCESS: true, |
|
ENOMEM: true, |
|
NOT_SUPPORTED: true, |
|
|
|
// consider statuses coming from outside couchbase (eg OS errors) as fatal for the connection |
|
// as there might be unread data left over on the wire |
|
UNKNOWN_STATUS: true, |
|
} |
|
|
|
// the producer/consumer bit in dcp flags |
|
var DCP_PRODUCER uint32 = 0x01 |
|
|
|
// the include XATTRS bit in dcp flags |
|
var DCP_OPEN_INCLUDE_XATTRS uint32 = 0x04 |
|
|
|
// the include deletion time bit in dcp flags |
|
var DCP_OPEN_INCLUDE_DELETE_TIMES uint32 = 0x20 |
|
|
|
// Datatype to Include XATTRS in SUBDOC GET |
|
var SUBDOC_FLAG_XATTR uint8 = 0x04 |
|
|
|
// MCItem is an internal representation of an item. |
|
type MCItem struct { |
|
Cas uint64 |
|
Flags, Expiration uint32 |
|
Data []byte |
|
} |
|
|
|
// Number of bytes in a binary protocol header. |
|
const HDR_LEN = 24 |
|
|
|
// Mapping of CommandCode -> name of command (not exhaustive) |
|
var CommandNames map[CommandCode]string |
|
|
|
// StatusNames human readable names for memcached response. |
|
var StatusNames map[Status]string |
|
|
|
func init() { |
|
CommandNames = make(map[CommandCode]string) |
|
CommandNames[GET] = "GET" |
|
CommandNames[SET] = "SET" |
|
CommandNames[ADD] = "ADD" |
|
CommandNames[REPLACE] = "REPLACE" |
|
CommandNames[DELETE] = "DELETE" |
|
CommandNames[INCREMENT] = "INCREMENT" |
|
CommandNames[DECREMENT] = "DECREMENT" |
|
CommandNames[QUIT] = "QUIT" |
|
CommandNames[FLUSH] = "FLUSH" |
|
CommandNames[GETQ] = "GETQ" |
|
CommandNames[NOOP] = "NOOP" |
|
CommandNames[VERSION] = "VERSION" |
|
CommandNames[GETK] = "GETK" |
|
CommandNames[GETKQ] = "GETKQ" |
|
CommandNames[APPEND] = "APPEND" |
|
CommandNames[PREPEND] = "PREPEND" |
|
CommandNames[STAT] = "STAT" |
|
CommandNames[SETQ] = "SETQ" |
|
CommandNames[ADDQ] = "ADDQ" |
|
CommandNames[REPLACEQ] = "REPLACEQ" |
|
CommandNames[DELETEQ] = "DELETEQ" |
|
CommandNames[INCREMENTQ] = "INCREMENTQ" |
|
CommandNames[DECREMENTQ] = "DECREMENTQ" |
|
CommandNames[QUITQ] = "QUITQ" |
|
CommandNames[FLUSHQ] = "FLUSHQ" |
|
CommandNames[APPENDQ] = "APPENDQ" |
|
CommandNames[PREPENDQ] = "PREPENDQ" |
|
CommandNames[RGET] = "RGET" |
|
CommandNames[RSET] = "RSET" |
|
CommandNames[RSETQ] = "RSETQ" |
|
CommandNames[RAPPEND] = "RAPPEND" |
|
CommandNames[RAPPENDQ] = "RAPPENDQ" |
|
CommandNames[RPREPEND] = "RPREPEND" |
|
CommandNames[RPREPENDQ] = "RPREPENDQ" |
|
CommandNames[RDELETE] = "RDELETE" |
|
CommandNames[RDELETEQ] = "RDELETEQ" |
|
CommandNames[RINCR] = "RINCR" |
|
CommandNames[RINCRQ] = "RINCRQ" |
|
CommandNames[RDECR] = "RDECR" |
|
CommandNames[RDECRQ] = "RDECRQ" |
|
|
|
CommandNames[SASL_LIST_MECHS] = "SASL_LIST_MECHS" |
|
CommandNames[SASL_AUTH] = "SASL_AUTH" |
|
CommandNames[SASL_STEP] = "SASL_STEP" |
|
|
|
CommandNames[TAP_CONNECT] = "TAP_CONNECT" |
|
CommandNames[TAP_MUTATION] = "TAP_MUTATION" |
|
CommandNames[TAP_DELETE] = "TAP_DELETE" |
|
CommandNames[TAP_FLUSH] = "TAP_FLUSH" |
|
CommandNames[TAP_OPAQUE] = "TAP_OPAQUE" |
|
CommandNames[TAP_VBUCKET_SET] = "TAP_VBUCKET_SET" |
|
CommandNames[TAP_CHECKPOINT_START] = "TAP_CHECKPOINT_START" |
|
CommandNames[TAP_CHECKPOINT_END] = "TAP_CHECKPOINT_END" |
|
|
|
CommandNames[UPR_OPEN] = "UPR_OPEN" |
|
CommandNames[UPR_ADDSTREAM] = "UPR_ADDSTREAM" |
|
CommandNames[UPR_CLOSESTREAM] = "UPR_CLOSESTREAM" |
|
CommandNames[UPR_FAILOVERLOG] = "UPR_FAILOVERLOG" |
|
CommandNames[UPR_STREAMREQ] = "UPR_STREAMREQ" |
|
CommandNames[UPR_STREAMEND] = "UPR_STREAMEND" |
|
CommandNames[UPR_SNAPSHOT] = "UPR_SNAPSHOT" |
|
CommandNames[UPR_MUTATION] = "UPR_MUTATION" |
|
CommandNames[UPR_DELETION] = "UPR_DELETION" |
|
CommandNames[UPR_EXPIRATION] = "UPR_EXPIRATION" |
|
CommandNames[UPR_FLUSH] = "UPR_FLUSH" |
|
CommandNames[UPR_NOOP] = "UPR_NOOP" |
|
CommandNames[UPR_BUFFERACK] = "UPR_BUFFERACK" |
|
CommandNames[UPR_CONTROL] = "UPR_CONTROL" |
|
CommandNames[SUBDOC_GET] = "SUBDOC_GET" |
|
CommandNames[SUBDOC_MULTI_LOOKUP] = "SUBDOC_MULTI_LOOKUP" |
|
CommandNames[GET_COLLECTIONS_MANIFEST] = "GET_COLLECTIONS_MANIFEST" |
|
CommandNames[COLLECTIONS_GET_CID] = "COLLECTIONS_GET_CID" |
|
CommandNames[DCP_SYSTEM_EVENT] = "DCP_SYSTEM_EVENT" |
|
CommandNames[DCP_SEQNO_ADV] = "DCP_SEQNO_ADV" |
|
|
|
StatusNames = make(map[Status]string) |
|
StatusNames[SUCCESS] = "SUCCESS" |
|
StatusNames[KEY_ENOENT] = "KEY_ENOENT" |
|
StatusNames[KEY_EEXISTS] = "KEY_EEXISTS" |
|
StatusNames[E2BIG] = "E2BIG" |
|
StatusNames[EINVAL] = "EINVAL" |
|
StatusNames[NOT_STORED] = "NOT_STORED" |
|
StatusNames[DELTA_BADVAL] = "DELTA_BADVAL" |
|
StatusNames[NOT_MY_VBUCKET] = "NOT_MY_VBUCKET" |
|
StatusNames[NO_BUCKET] = "NO_BUCKET" |
|
StatusNames[AUTH_STALE] = "AUTH_STALE" |
|
StatusNames[AUTH_ERROR] = "AUTH_ERROR" |
|
StatusNames[AUTH_CONTINUE] = "AUTH_CONTINUE" |
|
StatusNames[ERANGE] = "ERANGE" |
|
StatusNames[ROLLBACK] = "ROLLBACK" |
|
StatusNames[EACCESS] = "EACCESS" |
|
StatusNames[NOT_INITIALIZED] = "NOT_INITIALIZED" |
|
StatusNames[UNKNOWN_COMMAND] = "UNKNOWN_COMMAND" |
|
StatusNames[ENOMEM] = "ENOMEM" |
|
StatusNames[NOT_SUPPORTED] = "NOT_SUPPORTED" |
|
StatusNames[EINTERNAL] = "EINTERNAL" |
|
StatusNames[EBUSY] = "EBUSY" |
|
StatusNames[TMPFAIL] = "TMPFAIL" |
|
StatusNames[UNKNOWN_COLLECTION] = "UNKNOWN_COLLECTION" |
|
StatusNames[SUBDOC_PATH_NOT_FOUND] = "SUBDOC_PATH_NOT_FOUND" |
|
StatusNames[SUBDOC_BAD_MULTI] = "SUBDOC_BAD_MULTI" |
|
|
|
} |
|
|
|
// String an op code. |
|
func (o CommandCode) String() (rv string) { |
|
rv = CommandNames[o] |
|
if rv == "" { |
|
rv = fmt.Sprintf("0x%02x", int(o)) |
|
} |
|
return rv |
|
} |
|
|
|
// String an op code. |
|
func (s Status) String() (rv string) { |
|
rv = StatusNames[s] |
|
if rv == "" { |
|
rv = fmt.Sprintf("0x%02x", int(s)) |
|
} |
|
return rv |
|
} |
|
|
|
// IsQuiet will return true if a command is a "quiet" command. |
|
func (o CommandCode) IsQuiet() bool { |
|
switch o { |
|
case GETQ, |
|
GETKQ, |
|
SETQ, |
|
ADDQ, |
|
REPLACEQ, |
|
DELETEQ, |
|
INCREMENTQ, |
|
DECREMENTQ, |
|
QUITQ, |
|
FLUSHQ, |
|
APPENDQ, |
|
PREPENDQ, |
|
RSETQ, |
|
RAPPENDQ, |
|
RPREPENDQ, |
|
RDELETEQ, |
|
RINCRQ, |
|
RDECRQ: |
|
return true |
|
} |
|
return false |
|
}
|
|
|