Documentation
¶
Overview ¶
Package protocol defines the FrogoDB binary wire protocol. Shared between server and client.
Index ¶
- Constants
- Variables
- func AcquireOperations() *[]Operation
- func AcquireResponseBuf() *[]byte
- func EncodeScanResponse(nextCursor uint32, records []ScanRecord) []byte
- func ExpAnd(exprs ...[]byte) []byte
- func ExpAndChecked(exprs ...[]byte) ([]byte, error)
- func ExpEqual(left, right []byte) []byte
- func ExpFloatBin(name string) []byte
- func ExpFloatBinChecked(name string) ([]byte, error)
- func ExpFloatVal(v float64) []byte
- func ExpGreater(left, right []byte) []byte
- func ExpGreaterOrEqual(left, right []byte) []byte
- func ExpIntBin(name string) []byte
- func ExpIntBinChecked(name string) ([]byte, error)
- func ExpIntVal(v int64) []byte
- func ExpLess(left, right []byte) []byte
- func ExpLessOrEqual(left, right []byte) []byte
- func ExpNot(expr []byte) []byte
- func ExpNotEqual(left, right []byte) []byte
- func ExpOr(exprs ...[]byte) []byte
- func ExpOrChecked(exprs ...[]byte) ([]byte, error)
- func ExpStringBin(name string) []byte
- func ExpStringBinChecked(name string) ([]byte, error)
- func ExpStringVal(v string) []byte
- func ExpStringValChecked(v string) ([]byte, error)
- func HasPrimaryOnly(opCode uint8, flags uint16) bool
- func IsValidationError(err error) bool
- func MarshalBatchGetResults(results []BatchGetResult) []byte
- func ReleaseOperations(ops *[]Operation)
- func ReleaseRequest(req *Request)
- func ReleaseResponse(resp *Response)
- func ReleaseResponseBuf(b *[]byte)
- type BatchGetResult
- type BatchRecord
- type Field
- type Header
- type Operation
- type Request
- func (r *Request) Marshal() []byte
- func (r *Request) MarshalChecked() ([]byte, error)
- func (r *Request) MarshalInto(buf []byte) int
- func (r *Request) MarshalIntoChecked(buf []byte) (int, error)
- func (r *Request) MarshalPayload() []byte
- func (r *Request) MarshalPayloadChecked() ([]byte, error)
- func (r *Request) MarshalSize() int
- func (r *Request) Reset()
- func (r *Request) Unmarshal(buf []byte) error
- func (r *Request) UnmarshalPayload(buf []byte) error
- func (r *Request) Validate() error
- type Response
- func (r *Response) Marshal() []byte
- func (r *Response) MarshalInto(buf []byte) int
- func (r *Response) MarshalPayload() []byte
- func (r *Response) MarshalPayloadInto(buf []byte) []byte
- func (r *Response) MarshalSize() int
- func (r *Response) Reset()
- func (r *Response) Unmarshal(buf []byte) error
- func (r *Response) UnmarshalPayload(buf []byte) error
- type ResponseBin
- type ScanRecord
Constants ¶
const ( ProtoVersionLegacy uint8 = 0x01 // synchronous request-response mode ProtoVersionMultiplexed uint8 = 0x02 // multiplexed concurrent requests )
Connection-level protocol version bytes sent as the first byte on a new connection for version negotiation (T17.8). The server reads this byte to select the connection handler. Old clients that do not send a version byte start with the Magic byte 'F' (0x46), which the server detects and falls back to legacy mode with RequestID-based auto-detection.
const ( OpPing uint8 = 0x01 OpPut uint8 = 0x02 OpGet uint8 = 0x03 OpDelete uint8 = 0x04 OpOperate uint8 = 0x05 OpBatch uint8 = 0x06 OpScan uint8 = 0x07 // scan namespace/set records with limit + cursor OpCount uint8 = 0x08 // return approximate record count for namespace/set OpGetMap uint8 = 0x10 OpBatchGet uint8 = 0x20 // native batch GET with thresholded server-side shard execution (T16.6) OpBatchPut uint8 = 0x21 // native batch PUT with server-side shard fan-out (T16.7) OpBatchOperate uint8 = 0x22 // native batch OPERATE with server-side shard fan-out (T16.7) OpBatchDelete uint8 = 0x23 // native batch DELETE with server-side shard fan-out (T19.3) OpLSHDedup uint8 = 0xA0 // LSH string deduplication (server-side) OpLSHVector uint8 = 0xA1 // LSH vector behavioural ID (server-side) )
OpCodes for client requests.
const ( OpPingResp uint8 = 0x81 OpPutResp uint8 = 0x82 OpGetResp uint8 = 0x83 OpDeleteResp uint8 = 0x84 OpOperateResp uint8 = 0x85 OpBatchResp uint8 = 0x86 OpScanResp uint8 = 0x87 OpCountResp uint8 = 0x88 OpGetMapResp uint8 = 0x90 OpBatchGetResp uint8 = 0xA0 // 0x20 | 0x80 OpBatchPutResp uint8 = 0xA1 // 0x21 | 0x80 OpBatchOperateResp uint8 = 0xA2 // 0x22 | 0x80 OpBatchDeleteResp uint8 = 0xA3 // 0x23 | 0x80 )
OpCodes for server responses (request OpCode | 0x80).
const ( FlagSendKey uint16 = 1 << 0 FlagCreateOnly uint16 = 1 << 1 FlagReplace uint16 = 1 << 2 FlagRespondAllOps uint16 = 1 << 3 )
Protocol flags (bitmask in Header.Flags).
const ( FlagReadMaster uint16 = 0 << 4 // default: read from partition master FlagReadMasterOrReplica uint16 = 1 << 4 // read from master or replica (whichever is local) FlagReadReplicaOnly uint16 = 2 << 4 // read from replica only )
Read policy flags (2-bit field in bits 4-5 of Header.Flags). Use ReadPolicyMask to extract.
const ( FieldNamespace uint8 = 0x01 FieldSet uint8 = 0x02 FieldKey uint8 = 0x03 FieldDigest uint8 = 0x04 FieldFilter uint8 = 0x05 // serialized filter expression tree FieldGroup uint8 = 0x06 // LSH group name )
Field types in the payload.
const ( OpTypeRead uint8 = 0x01 OpTypeWrite uint8 = 0x02 OpTypeIncr uint8 = 0x05 OpTypeAppend uint8 = 0x09 OpTypePrepend uint8 = 0x0A )
Operation types within OPERATE requests.
const ( ParticleTypeInteger uint8 = 0x01 ParticleTypeFloat uint8 = 0x02 ParticleTypeString uint8 = 0x03 ParticleTypeBlob uint8 = 0x04 )
Particle types stored in Operation.ParticleType and ResponseBin.ParticleType.
const ( RequestPayloadHeaderSize = 8 // NumFields(2) + NumOps(2) + TTL(4) ResponsePayloadHeaderSize = 4 // ResultCode(1) + NumBins(2) + Reserved(1) FieldHeaderSize = 5 // Type(1) + Len(4) OperationHeaderSize = 8 // OpType(1) + BinNameLen(1) + ParticleType(1) + Flags(1) + DataLen(4) ResponseBinHeaderSize = 6 // BinNameLen(1) + ParticleType(1) + DataLen(4) MaxPayloadSize = 128 << 20 // 128 MB )
Payload size constants.
const ( ResultOK uint8 = 0x00 ResultKeyNotFound uint8 = 0x02 ResultKeyExists uint8 = 0x05 ResultGenerationError uint8 = 0x06 ResultOverloaded uint8 = 0x18 // server backpressure: too many in-flight requests (T17.6) ResultFilteredOut uint8 = 0x1A // record exists but excluded by filter expression ResultInDoubt uint8 = 0x28 ResultServerError uint8 = 0x50 )
Result codes returned in server responses.
const FlagCommitMaster uint16 = 1 << 8
FlagCommitMaster is the commit policy flag (bit 8 of Header.Flags). Return after local write, replicate async.
const FlagPreserveTTL uint16 = 1 << 11
FlagPreserveTTL requests that PUT and BatchPut preserve the existing record TTL when a record already exists. When absent, the TTL field keeps the legacy meaning: TTL > 0 sets a new TTL, TTL == 0 clears expiration.
const FlagPrimaryOnly uint16 = 1 << 9
FlagPrimaryOnly limits local scan/count execution to partitions where the serving node is master. Only OpScan and OpCount honor it.
const FlagWriteMerge uint16 = 1 << 10
FlagWriteMerge requests merge/update semantics for PUT and BatchPut. When absent, writes use the legacy full-record replace path.
const HeaderSize = 20
HeaderSize is the fixed size of the wire protocol header in bytes.
const ( // OpFlagCreateOnly skips a Write operation if the bin already has a value. // Used for FirstSeen semantics: write only if the bin does not exist. OpFlagCreateOnly uint8 = 0x10 )
Per-operation flags (bitmask in Operation.Flags).
const ReadPolicyMask uint16 = 0x30
ReadPolicyMask extracts the read policy from Header.Flags (bits 4-5).
const VersionV1 uint8 = 0x01
VersionV1 is the current protocol version.
Variables ¶
var ErrInvalidRequest = errors.New("invalid protocol request")
ErrInvalidRequest identifies caller-supplied request data that cannot be represented by the FrogoDB wire format.
var Magic = [2]byte{'F', 'D'}
Magic bytes identifying a FrogoDB protocol frame.
var ResponseBufPool = sync.Pool{ New: func() any { b := make([]byte, 0, initialResponseBufferCap) return &b }, }
ResponseBufPool provides reusable byte buffers for response payload marshalling. Each buffer starts at 4KB capacity, sufficient for most single-record responses. Callers must return buffers via ReleaseResponseBuf after use.
Functions ¶
func AcquireOperations ¶
func AcquireOperations() *[]Operation
AcquireOperations returns a pooled Operation slice for temporary use. Caller must call ReleaseOperations after use.
func AcquireResponseBuf ¶
func AcquireResponseBuf() *[]byte
AcquireResponseBuf returns a pooled byte buffer for response marshalling.
func EncodeScanResponse ¶
func EncodeScanResponse(nextCursor uint32, records []ScanRecord) []byte
EncodeScanResponse encodes scan records and a continuation cursor into a blob.
Wire format: [NextCursor:4B][NumRecords:2B][Records...] Record: [Generation:4B][NumBins:2B][Bins...] Bins use the standard ResponseBin wire format.
func ExpAndChecked ¶ added in v1.2.0
ExpAndChecked creates a logical AND of all sub-expressions.
func ExpFloatBin ¶
ExpFloatBin creates a filter expression that reads a float bin value.
func ExpFloatBinChecked ¶ added in v1.2.0
ExpFloatBinChecked creates a filter expression that reads a float bin value.
func ExpFloatVal ¶
ExpFloatVal creates a constant float value expression.
func ExpGreater ¶
ExpGreater creates a "left > right" comparison expression.
func ExpGreaterOrEqual ¶
ExpGreaterOrEqual creates a "left >= right" comparison expression.
func ExpIntBinChecked ¶ added in v1.2.0
ExpIntBinChecked creates a filter expression that reads an integer bin value.
func ExpLessOrEqual ¶
ExpLessOrEqual creates a "left <= right" comparison expression.
func ExpNotEqual ¶
ExpNotEqual creates a "left != right" comparison expression.
func ExpOrChecked ¶ added in v1.2.0
ExpOrChecked creates a logical OR of all sub-expressions.
func ExpStringBin ¶
ExpStringBin creates a filter expression that reads a string bin value.
func ExpStringBinChecked ¶ added in v1.2.0
ExpStringBinChecked creates a filter expression that reads a string bin value.
func ExpStringVal ¶
ExpStringVal creates a constant string value expression.
func ExpStringValChecked ¶ added in v1.2.0
ExpStringValChecked creates a constant string value expression.
func HasPrimaryOnly ¶
HasPrimaryOnly returns true when Header.Flags requests primary-only execution for a scan/count request. Unrelated opcodes ignore the flag.
func IsValidationError ¶ added in v1.2.0
IsValidationError reports whether err was returned by protocol request validation.
func MarshalBatchGetResults ¶
func MarshalBatchGetResults(results []BatchGetResult) []byte
MarshalBatchGetResults encodes batch GET results into a byte slice.
Wire format: [Count:4B][Result1][Result2]... Each result: [ResultCode:1B][Generation:4B][NumBins:2B][Bins...] Each bin uses the standard ResponseBin wire format.
func ReleaseOperations ¶
func ReleaseOperations(ops *[]Operation)
ReleaseOperations returns an Operation slice to the pool after clearing all Data references to prevent memory leaks.
func ReleaseRequest ¶
func ReleaseRequest(req *Request)
ReleaseRequest returns a Request to the pool after clearing all references. Operation.Data and BatchRecord slices are zeroed to prevent memory leaks.
func ReleaseResponse ¶
func ReleaseResponse(resp *Response)
ReleaseResponse returns a Response to the pool after clearing all fields. The Bins backing array is retained; individual entries are zeroed to release Data slice references for GC.
func ReleaseResponseBuf ¶
func ReleaseResponseBuf(b *[]byte)
ReleaseResponseBuf returns a buffer to the pool after resetting its length.
Types ¶
type BatchGetResult ¶
type BatchGetResult struct {
ResultCode uint8
Generation uint32
Bins []ResponseBin
}
BatchGetResult holds the server-side result for one key in a batch GET.
func UnmarshalBatchGetResults ¶
func UnmarshalBatchGetResults(buf []byte) ([]BatchGetResult, error)
UnmarshalBatchGetResults decodes batch GET results from the wire format.
type BatchRecord ¶
type BatchRecord struct {
Key []byte
TTL uint32
Generation uint32
Flags uint16 // per-record flags (CreateOnly, Replace, WriteMerge, PreserveTTL, etc.)
Operations []Operation
}
BatchRecord holds per-key data for a batch PUT or OPERATE request (T16.7).
type Field ¶
Field represents a typed field in the protocol payload.
Wire format: [FieldType:1B][FieldLen:4B][FieldData:var]
func UnmarshalField ¶
UnmarshalField reads a single Field from buf. Returns the field, bytes consumed, and any error.
func (*Field) MarshalSize ¶
MarshalSize returns the total wire size of the field.
type Header ¶
type Header struct {
Magic [2]byte
Version uint8
OpCode uint8
Flags uint16
PartitionID uint16
Generation uint32
PayloadLen uint32
RequestID uint32
}
Header is the 20-byte fixed header for every protocol frame.
Layout (BigEndian):
[0:2] Magic "FD" (0x46, 0x44) [2] Version 0x01 [3] OpCode operation code [4:6] Flags bit flags [6:8] PartitionID 0-4095 [8:12] Generation optimistic locking [12:16] PayloadLen payload size in bytes [16:20] RequestID multiplexing request ID (0 = legacy synchronous mode)
type Operation ¶
Operation represents a single operation within an OPERATE request.
Wire format: [OpType:1B][BinNameLen:1B][BinName:var][ParticleType:1B][Flags:1B][DataLen:4B][Data:var]
func UnmarshalOperation ¶
UnmarshalOperation reads a single Operation from buf. Returns the operation, bytes consumed, and any error.
func (*Operation) MarshalSize ¶
MarshalSize returns the total wire size of the operation.
type Request ¶
type Request struct {
Header Header
Namespace string
Set string
Key []byte
Digest [20]byte
Group string // LSH group name (FieldGroup)
Operations []Operation
TTL uint32
FilterExpression []byte // serialized filter expression tree (FieldFilter)
// Pre-resolved namespace/set IDs set by the transport layer's per-connection
// cache (T10.5). When NsResolved is true, the engine skips the registry lock.
NsID uint16
SetID uint16
NsResolved bool
// BatchKeys holds multiple keys for native batch operations (T16.6).
// Populated by unmarshalBatchGetPayload; slices reference the payload buffer.
BatchKeys [][]byte
// BatchRecords holds per-key record data for native batch PUT/OPERATE (T16.7).
// Populated by unmarshalBatchWritePayload.
BatchRecords []BatchRecord
}
Request represents a parsed client request.
func AcquireRequest ¶
func AcquireRequest() *Request
AcquireRequest returns a pooled Request with pre-allocated Operations slice. Caller must call ReleaseRequest after the request has been fully processed.
func (*Request) Marshal ¶
Marshal encodes the full request (header + payload). Sets Header.Magic, Header.Version, and Header.PayloadLen automatically.
func (*Request) MarshalChecked ¶ added in v1.2.0
MarshalChecked validates and then encodes the full request.
func (*Request) MarshalInto ¶
MarshalInto encodes the full request into buf and returns the number of bytes written. buf must be at least MarshalSize() bytes. Sets Header.Magic, Header.Version, and Header.PayloadLen automatically.
func (*Request) MarshalIntoChecked ¶ added in v1.2.0
MarshalIntoChecked validates and then encodes the full request into buf.
func (*Request) MarshalPayload ¶
MarshalPayload encodes the request payload (excluding the 16-byte header).
Payload format: [NumFields:2B][NumOps:2B][TTL:4B][Fields...][Operations...]
func (*Request) MarshalPayloadChecked ¶ added in v1.2.0
MarshalPayloadChecked validates and then encodes the request payload.
func (*Request) MarshalSize ¶
MarshalSize returns the total wire size of the request (header + payload) without allocating the output buffer. Use with MarshalInto for zero-alloc marshaling on hot paths.
func (*Request) Reset ¶
func (r *Request) Reset()
Reset clears all fields for reuse, retaining allocated backing arrays for Key, FilterExpression, and Operations slices. This enables per-connection Request reuse without re-allocating on every request.
func (*Request) UnmarshalPayload ¶
UnmarshalPayload decodes the request payload (excluding the 16-byte header). When called on a Reset() request, this method reuses existing backing arrays for Key, FilterExpression, and Operations to minimize allocations.
type Response ¶
type Response struct {
Header Header
ResultCode uint8
Generation uint32
Bins []ResponseBin
}
Response represents a server response to a client.
func AcquireResponse ¶
func AcquireResponse() *Response
AcquireResponse returns a pooled Response with pre-allocated Bins slice. Caller must call ReleaseResponse after the response has been fully written.
func (*Response) Marshal ¶
Marshal encodes the full response (header + payload). Sets Header.Magic, Header.Version, Header.Generation, and Header.PayloadLen automatically. Uses MarshalInto internally to produce the result in a single allocation.
func (*Response) MarshalInto ¶
MarshalInto encodes the full response into buf and returns the number of bytes written. buf must be at least MarshalSize() bytes. Sets Header.Magic, Header.Version, Header.Generation, and Header.PayloadLen automatically.
func (*Response) MarshalPayload ¶
MarshalPayload encodes the response payload (excluding the 16-byte header).
Payload format: [ResultCode:1B][NumBins:2B][Reserved:1B][Bins...]
func (*Response) MarshalPayloadInto ¶
MarshalPayloadInto encodes the response payload into the provided buffer, growing it if necessary. Returns the buffer (which may be a new slice if growth was needed). Callers should update their pointer with the returned slice to ensure pool-returned buffers reflect any capacity growth.
func (*Response) MarshalSize ¶
MarshalSize returns the total wire size of the response (header + payload) without allocating. Use with MarshalInto for zero-alloc marshaling.
func (*Response) Reset ¶
func (r *Response) Reset()
Reset clears all fields for reuse, retaining the Bins backing array.
func (*Response) UnmarshalPayload ¶
UnmarshalPayload decodes the response payload (excluding the 16-byte header).
type ResponseBin ¶
ResponseBin represents a single bin in a response payload.
Wire format: [BinNameLen:1B][BinName:var][ParticleType:1B][DataLen:4B][Data:var]
type ScanRecord ¶
type ScanRecord struct {
Generation uint32
Bins []ResponseBin
}
ScanRecord represents one record in a scan response.
func DecodeScanResponse ¶
func DecodeScanResponse(data []byte) (uint32, []ScanRecord, error)
DecodeScanResponse decodes a scan blob into a continuation cursor and records.