mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 13:28:25 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			350 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			350 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
// 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
 | 
						|
 | 
						|
	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
 | 
						|
 | 
						|
)
 | 
						|
 | 
						|
// 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}
 | 
						|
 | 
						|
// 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)
 | 
						|
)
 | 
						|
 | 
						|
// 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,
 | 
						|
}
 | 
						|
 | 
						|
// 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"
 | 
						|
 | 
						|
	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
 | 
						|
}
 |