transport

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2026 License: Apache-2.0 Imports: 30 Imported by: 0

Documentation

Overview

Package transport implements FDB's TCP wire protocol: framing, handshake, and request/response multiplexing via endpoint tokens.

Index

Constants

View Source
const (
	DefaultMinCoalesceDelay = 10 * time.Microsecond
	DefaultMaxCoalesceDelay = 20 * time.Microsecond
)

MIN_COALESCE_DELAY and MAX_COALESCE_DELAY (flow/Knobs.cpp:211-212).

View Source
const (
	// ObjectSerializerFlag signals FlatBuffers serialization (always set in modern FDB).
	ObjectSerializerFlag uint64 = 0x1000000000000000

	// CompatibleProtocolVersionMask: top 48 bits must match for compatibility.
	CompatibleProtocolVersionMask uint64 = 0xFFFFFFFFFFFF0000

	// FDB 7.3 protocol version (without flags).
	ProtocolVersion73 uint64 = 0x0FDB00B073000000

	// FLAG_IPV6 in ConnectPacket.flags.
	FlagIPv6 uint16 = 1
)

Protocol version constants.

View Source
const (
	// WLTokenFirstAvailable is the first available well-known token ID.
	WLTokenFirstAvailable = 3

	// WLTokenClientLeaderRegGetLeader is the getLeader endpoint.
	WLTokenClientLeaderRegGetLeader = 3

	// WLTokenClientLeaderRegOpenDatabase is the openDatabase endpoint
	// used for coordinator bootstrap (OpenDatabaseCoordRequest → ClientDBInfo).
	WLTokenClientLeaderRegOpenDatabase = 4

	// WLTokenProtocolInfo is the protocol info endpoint (stable value).
	WLTokenProtocolInfo = 10
)

Well-known endpoint token IDs. These are deterministic UIDs that FDB coordinators listen on. From fdbrpc/include/fdbrpc/WellKnownEndpoints.h

View Source
const ConnectPacketSize = 44

ConnectPacketSize is the wire size of the ConnectPacket both sides exchange on TCP connection establishment. Packed struct (no padding), 44 bytes total.

Layout:

Offset  Size  Field
0       4     connectPacketLength (uint32 LE) = 40 (excludes itself)
4       8     protocolVersion (uint64 LE, with objectSerializerFlag bit 60)
12      2     canonicalRemotePort (uint16 LE)
14      8     connectionId (uint64 LE)
22      4     canonicalRemoteIp4 (uint32 LE)
26      2     flags (uint16 LE, bit 0 = FLAG_IPV6)
28      16    canonicalRemoteIp6 (16 bytes, only meaningful if FLAG_IPV6)

Total: 4 + 40 = 44 bytes.

View Source
const WLTokenEndpointNotFound = 0

WLTokenEndpointNotFound is WLTOKEN_ENDPOINT_NOT_FOUND (FlowTransport.h:39).

View Source
const WLTokenPingPacket = 1

WLTokenPingPacket is the well-known token for PING keepalive.

Variables

View Source
var DefaultVerifyPolicy = &VerifyPolicy{rules: []verifyRule{{verifyCert: true}}}

DefaultVerifyPolicy is libfdb_c's default, Check.Valid=1: the chain must verify against the configured roots, and nothing else is checked.

View Source
var ErrConnClosed = errors.New("connection closed")

ErrConnClosed is the identity sentinel for a connection teardown. Every error this package delivers for a torn-down connection matches it via errors.Is(err, ErrConnClosed).

Exported so a caller can tell a TRANSPORT teardown apart from an answer the cluster actually gave. The delivered error additionally carries FDB code 1030 request_maybe_delivered (see ConnClosedError), so downstream code has two structural handles: errors.Is against this sentinel while the transport error travels as-is, and the 1030 code once a facade has converted it to its own error type (which drops wrap-chain identity) — matching the rendered message is not one.

View Source
var ErrEndpointNotFound = errors.New("endpoint not found")

ErrEndpointNotFound identifies a reply failed because the server no longer has the request's endpoint. It is NOT a connection teardown.

Functions

func BuildPingRequest

func BuildPingRequest(replyToken UID) []byte

BuildPingRequest builds a PingRequest FlatBuffers body. ReplyPromise's object-serializer trait emits a nested table with an inline UID.

func CaptureWireLog

func CaptureWireLog(w io.Writer) (stop func())

CaptureWireLog writes the wire log to w in the binary format until the returned stop is called. Once stop returns, nothing more is written to w, even by a frame logged concurrently, so w may then be read. It replaces any log already set (FDB_WIRE_LOG); stop removes the capture, leaving none.

func LogRecv

func LogRecv(token UID, body []byte)

LogRecv records an inbound frame.

func LogSend

func LogSend(token UID, body []byte)

LogSend records an outbound frame.

func NetDesign

func NetDesign() string

NetDesign reports the writer design new connections use by default: "" for the legacy writer, "d" for timer-coalesced design D, or "ng" for D-NG.

func NotifySuspend

func NotifySuspend(ctx context.Context)

NotifySuspend fires ctx's signal, if it carries one: the caller is about to wait.

func WriteConnectPacket

func WriteConnectPacket(w io.Writer, localAddr net.Addr, connectionID uint64) error

WriteConnectPacket sends a ConnectPacket to the connection.

func WriteFrame

func WriteFrame(w io.Writer, token UID, body []byte, tls bool) error

WriteFrame writes a framed message to w. If tls is true, the checksum is omitted.

Types

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is a multiplexed FDB connection. Multiple concurrent requests share one TCP connection, matched by endpoint tokens.

Lifecycle: after Close() returns, zero goroutines are running. If the server kills the connection, readLoop cancels the context and IsClosed() returns true — the connection pool will evict it.

func Dial

func Dial(ctx context.Context, addr string, tlsConfig *tls.Config, dialFn DialFunc, opts ...DialOption) (*Conn, error)

Dial connects to an FDB process, exchanges ConnectPackets, and starts the read/write/monitor loops.

tlsConfig is the single source of truth for transport security: non-nil wraps the connection in TLS using that standard *crypto/tls.Config (bring any config — in-memory certs, rotation via GetClientCertificate, custom VerifyPeerCertificate, cipher/version policy); nil means plaintext. There is no separate "use TLS" bool to disagree with it, so a connection can never be silently downgraded. dialFn overrides the dialer (nil → net.Dialer).

func (*Conn) AdaptiveLinger

func (c *Conn) AdaptiveLinger() time.Duration

AdaptiveLinger reports the connection's active adaptive linger window (0 when disabled or when using the legacy writer).

func (*Conn) BytesReceived

func (c *Conn) BytesReceived() int64

BytesReceived returns the socket bytes received since the handshake, frame headers and partial frames included. The connection monitor watches it.

func (*Conn) ClearSendOrder

func (c *Conn) ClearSendOrder(order *sendqueue.Queue)

ClearSendOrder detaches a drained dial generation. The writer retains its finite prefix and held channels until those accepted frames have drained.

func (*Conn) Close

func (c *Conn) Close() error

Close closes the connection and waits for its loop goroutines to exit. Safe to call multiple times. After Close returns, zero goroutines are running on this connection.

Shutdown sequence (matches C++ connectionKeeper):

  1. Cancel context — signals all waiters that conn is dead
  2. Close TCP socket — unblocks readLoop's ReadFrame
  3. failConnection delivers errors to all pending requests
  4. readLoop, naLoop/writeLoop, connectionMonitor and coldControlLoop exit and signal loopWG; the monitor first releases its PING reply (RFC-269)
  5. Close returns

func (*Conn) CoalesceDelay

func (c *Conn) CoalesceDelay() (minDelay, maxDelay time.Duration, waits bool)

CoalesceDelay reports the connection's write delay bounds and whether it waits.

func (*Conn) Done

func (c *Conn) Done() <-chan struct{}

Done returns a channel that is closed when the connection is dead. Use in select statements to detect connection death.

func (*Conn) Flush

func (c *Conn) Flush() error

Flush checks cold-dial admission and liveness on D-NG, or waits for a flush marker acknowledgment when WithLegacyWriter() is active.

func (*Conn) FlushContext

func (c *Conn) FlushContext(ctx context.Context) error

FlushContext checks ctx, cold-dial order, and connection liveness on D-NG (or waits for an ordered flush marker when WithLegacyWriter() is active).

func (*Conn) HasPendingReply

func (c *Conn) HasPendingReply(token UID) bool

HasPendingReply reports whether token still owns a reply registration.

func (*Conn) IsClosed

func (c *Conn) IsClosed() bool

IsClosed returns true if the connection has been closed or the server killed it. Uses context cancellation — works for both shutdown paths.

func (*Conn) PeerProtocolVersion

func (c *Conn) PeerProtocolVersion() uint64

PeerProtocolVersion returns the peer's protocol version.

func (*Conn) PrepareReply

func (c *Conn) PrepareReply() (UID, <-chan Response, *ReplyHandle)

PrepareReply allocates a reply token and registers it for response routing. Use this when you need the token BEFORE building the request body (e.g., to embed it in the FDB request's Reply field).

Returns a ReplyHandle whose Cancel() removes the pending token. Call handle.Release() when done to return it to the pool.

func (*Conn) PrepareReplyTo

func (c *Conn) PrepareReplyTo(dest UID) (UID, <-chan Response, *ReplyHandle)

PrepareReplyTo is PrepareReply for a request that will be sent to dest, so an ENDPOINT_NOT_FOUND for dest fails this reply instead of leaving it to time out.

func (*Conn) Send

func (c *Conn) Send(destToken UID, body []byte) (replyToken UID, replyCh <-chan Response, err error)

Send sends a request and returns a channel that will receive the response. The destToken identifies the remote endpoint (e.g., a StorageServer's getValue endpoint). The replyToken is a fresh token for routing the response back.

func (*Conn) SendAndWait

func (c *Conn) SendAndWait(ctx context.Context, destToken UID, body []byte) ([]byte, error)

SendAndWait sends a request and blocks until the response arrives.

func (*Conn) SendFrame

func (c *Conn) SendFrame(destToken UID, body []byte) error

SendFrame queues a raw frame on the connection's writer (returning once appended on D-NG, or after write/tail handoff on WithLegacyWriter()).

func (*Conn) SendFrameContext

func (c *Conn) SendFrameContext(ctx context.Context, token UID, body []byte) (enqueued bool, err error)

SendFrameContext enqueues a frame (or waits for its flush on WithLegacyWriter); cancelling ctx ends admission/high-water/flush wait without retracting queued bytes.

func (*Conn) SendFrameContextOrdered

func (c *Conn) SendFrameContextOrdered(ctx context.Context, token UID, body []byte, permit *sendqueue.Permit) (bool, error)

SendFrameContextOrdered sends using a place reserved before a cold peer dial. The place is released on acceptance, before any flush or reply wait. Its owner must pass it here: a nil-permit send on the same connection can wait for that still-owned place and deadlock. Release abandoned places instead.

func (*Conn) SendFrameDeferred

func (c *Conn) SendFrameDeferred(destToken UID, body []byte) error

SendFrameDeferred queues a raw frame without waiting for a socket write.

func (*Conn) SendFrameDeferredContext

func (c *Conn) SendFrameDeferredContext(ctx context.Context, token UID, body []byte) (bool, error)

SendFrameDeferredContext transfers an immutable copy to the write queue without waiting for a socket write acknowledgment (the bool reports enqueue, not wire delivery).

func (*Conn) SendFrameDeferredContextOrdered

func (c *Conn) SendFrameDeferredContextOrdered(ctx context.Context, token UID, body []byte, permit *sendqueue.Permit) (bool, error)

SendFrameDeferredContextOrdered is the deferred form with a cold dial place.

func (*Conn) SendFrameEagerContext

func (c *Conn) SendFrameEagerContext(ctx context.Context, token UID, body []byte) (bool, error)

SendFrameEagerContext is SendFrameDeferredContext for a frame nothing is about to join (enqueues on D-NG; writes directly when idle on WithLegacyWriter()).

func (*Conn) SendFrameEagerContextOrdered

func (c *Conn) SendFrameEagerContextOrdered(ctx context.Context, token UID, body []byte, permit *sendqueue.Permit) (bool, error)

SendFrameEagerContextOrdered is the eager form with a cold dial place.

func (*Conn) SetDebug

func (c *Conn) SetDebug(enabled bool)

SetDebug enables frame-level debug tracing to stderr.

func (*Conn) SetEndpointNotFoundHandler

func (c *Conn) SetEndpointNotFoundHandler(fn func(UID))

SetEndpointNotFoundHandler installs fn to observe every ENDPOINT_NOT_FOUND token this connection receives, whether or not a reply is still waiting.

type ConnClosedError

type ConnClosedError struct {
	// contains filtered or unexported fields
}

ConnClosedError is the teardown error delivered to in-flight requests and queued senders when the connection is torn down (by Close, the monitor, a read error, or a write error). It matches BOTH errors.Is(err, ErrConnClosed) (teardown identity) and errors.As(err, **wire.FDBError) with code 1030 request_maybe_delivered, so the client's retry machinery sees the same coded, C++-faithful condition libfdb_c's loadBalance sees. Cause (the underlying read/write error, when there is one) is carried in the message only — NOT in the Unwrap chain — so a teardown can never spuriously match errors.Is/As probes aimed at its cause (e.g. a context error check).

func (*ConnClosedError) Error

func (e *ConnClosedError) Error() string

func (*ConnClosedError) Unwrap

func (e *ConnClosedError) Unwrap() []error

type ConnectFailedError

type ConnectFailedError struct {
	Addr string
	// contains filtered or unexported fields
}

ConnectFailedError is a failed connect to a peer, as a request waiting on that connect observes it. C++ connectionKeeper turns any connect or handshake failure, including its CONNECTION_MONITOR_TIMEOUT, into connection_failed (FlowTransport.actor.cpp:819-869, Net2.actor.cpp:363-391 and 413-430), discards the peer's unsent unreliable packets and fires peer->disconnect (FlowTransport.actor.cpp:933, 1001-1004). Every tryGetReply queued on the peer then completes with request_maybe_delivered (fdbrpc.h:797-816, genericactors.actor.h:380-385), whether or not its packet ever left the client. So this matches errors.As(err, **wire.FDBError) with code 1030 and nothing else: the dial error is message-only, so a dial timeout cannot match a caller's context probes.

func NewConnectFailedError

func NewConnectFailedError(addr string, cause error) *ConnectFailedError

NewConnectFailedError codes cause, the error of a failed dial to addr.

func (*ConnectFailedError) Cause

func (e *ConnectFailedError) Cause() error

Cause returns the dial error, for diagnostics.

func (*ConnectFailedError) Error

func (e *ConnectFailedError) Error() string

func (*ConnectFailedError) Unwrap

func (e *ConnectFailedError) Unwrap() error

type ConnectPacket

type ConnectPacket struct {
	ProtocolVersion     uint64
	CanonicalRemotePort uint16
	ConnectionID        uint64
	CanonicalRemoteIP4  uint32
	Flags               uint16
	CanonicalRemoteIP6  [16]byte
}

ConnectPacket represents the FDB connection handshake packet.

func ReadConnectPacket

func ReadConnectPacket(r io.Reader) (*ConnectPacket, error)

ReadConnectPacket reads a ConnectPacket from the connection.

func (*ConnectPacket) HasObjectSerializerFlag

func (p *ConnectPacket) HasObjectSerializerFlag() bool

HasObjectSerializerFlag returns true if the protocol version uses FlatBuffers.

func (*ConnectPacket) IsCompatible

func (p *ConnectPacket) IsCompatible(ourVersion uint64) bool

IsCompatible returns true if the peer's protocol version is compatible.

func (*ConnectPacket) IsIPv6

func (p *ConnectPacket) IsIPv6() bool

IsIPv6 returns true if the canonical address is IPv6.

func (*ConnectPacket) Marshal

func (p *ConnectPacket) Marshal() []byte

Marshal serializes the ConnectPacket to wire format (44 bytes).

func (*ConnectPacket) Unmarshal

func (p *ConnectPacket) Unmarshal(buf []byte) error

Unmarshal deserializes a ConnectPacket from wire format.

type DialFunc

type DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)

DialFunc is the signature for custom dialers. Same as net.Dialer.DialContext. Default is net.Dialer{}.DialContext. Override for testing (fault injection, custom Docker networking, traffic shaping).

type DialOption

type DialOption func(*Conn)

DialOption configures a Conn before its loop goroutines start.

func WithAdaptiveLinger

func WithAdaptiveLinger(d time.Duration) DialOption

WithAdaptiveLinger configures Nagle-style adaptive linger on the D-NG writer (0 disables; the last linger/coalesce option wins; RFC-282).

func WithCoalesceDelay

func WithCoalesceDelay(minDelay, maxDelay time.Duration) DialOption

WithCoalesceDelay sets the connection's timer-based batch delay bounds (default 0, 0 on D-NG; 10/20 µs on WithLegacyWriter(); the last linger/coalesce option wins).

func WithLegacyWriter

func WithLegacyWriter() DialOption

WithLegacyWriter pins the legacy writer (writeLoop, direct writes, writer turns) whatever FDBGO_NET_DESIGN says. Tests of those mechanics use it.

func WithSendOrder

func WithSendOrder(order *sendqueue.Queue) DialOption

WithSendOrder attaches one finite cold cohort before the connection loops start. Prefix and held frames have independent bounded admission channels.

type EndpointNotFoundError

type EndpointNotFoundError struct {
	Token UID
}

EndpointNotFoundError is delivered to every pending reply whose request went to Token. It matches ErrEndpointNotFound and FDB code 1030: C++ tryGetReply completes such a request with request_maybe_delivered (genericactors.actor.h:375-378) and leaves the connection alone.

func (*EndpointNotFoundError) Error

func (e *EndpointNotFoundError) Error() string

func (*EndpointNotFoundError) Unwrap

func (e *EndpointNotFoundError) Unwrap() []error

type FrameReader

type FrameReader struct {
	// contains filtered or unexported fields
}

FrameReader reads framed messages with a persistent header buffer to avoid per-frame heap allocations for the 4-byte length + 8-byte checksum reads. Not safe for concurrent use — intended for single-goroutine readLoop.

func (*FrameReader) Read

func (fr *FrameReader) Read(r io.Reader, tls bool) (token UID, body []byte, err error)

Read reads one framed message from r. Returns the endpoint token and the message body (without token).

type PeerVerifyError

type PeerVerifyError struct {
	Reason string
	Err    error // the chain error, when the chain did not verify
}

PeerVerifyError reports a peer certificate the policy rejects.

func (*PeerVerifyError) Error

func (e *PeerVerifyError) Error() string

func (*PeerVerifyError) Unwrap

func (e *PeerVerifyError) Unwrap() error

type ReplyHandle

type ReplyHandle struct {
	// contains filtered or unexported fields
}

ReplyHandle holds state for a pending reply. Pooled to avoid closure allocation in PrepareReply (the cancel closure captured conn+token+ch, causing a heap alloc on every RPC call — ~9% of total allocs in SaveRecord benchmarks).

func (*ReplyHandle) Cancel

func (h *ReplyHandle) Cancel()

Cancel removes the pending reply from the connection's pending map and returns the reply channel to the pool. Safe to call on a handle with a nil conn (no-op).

func (*ReplyHandle) KeepReadyOrCancel

func (h *ReplyHandle) KeepReadyOrCancel() bool

KeepReadyOrCancel leaves a published response for the caller's normal receive, or cancels an unpublished reply atomically. Like TakeReadyOrCancel, this needs exclusive handle ownership. It never adds a second channel producer.

func (*ReplyHandle) NotifyWait

func (h *ReplyHandle) NotifyWait(ctx context.Context)

NotifyWait marks suspension only when the response is not already published. The caller owns the handle and has not received from its channel yet.

func (*ReplyHandle) Release

func (h *ReplyHandle) Release()

Release returns the handle to the pool. Call EITHER after a successful receive (no Cancel) OR after Cancel. On the success path h.ch is still set and is pooled here: response publication and token deletion share the token's pendingShard.mu lock, in that order. Once the caller receives the response, that publisher has no further channel send, and the lock excludes another publisher until deletion. Cancel nils h.ch, so the cancel path never double-pools.

func (*ReplyHandle) TakeReadyOrCancel

func (h *ReplyHandle) TakeReadyOrCancel() (Response, bool)

TakeReadyOrCancel chooses response publication or cancellation under the connection's reply lock. The caller must exclusively own this handle and channel (no concurrent receive/Cancel/Release). Release is still required.

type Response

type Response struct {
	Body []byte
	Err  error
	// RecvAt is when the read loop delivered this reply (≈ arrival time). Set only
	// on a successful body delivery; lets a caller measure send→receive latency
	// independent of when it gets around to consuming the reply (RFC-114).
	RecvAt time.Time
}

Response is a received message from the peer.

type SuspendSignal

type SuspendSignal struct {
	// contains filtered or unexported fields
}

SuspendSignal marks the first wait of a goroutine that carries it in its context: the point where a flow actor would suspend at its first wait that is not ready. The client's NativeAPI getRange fallback starts end's resolveKey there, after begin's (NativeAPI.actor.cpp:4465-4469). Every wait on a request's path fires it before blocking: the dial wait, high-water backpressure (or on the legacy writer a full write queue, the flush acknowledgment, and the writer turn's coalescing delay), the reply wait, and delays.

func WithSuspendHandoff

func WithSuspendHandoff(ctx context.Context, resume <-chan struct{}, beforeWait func()) (context.Context, *SuspendSignal)

WithSuspendHandoff also holds the notifying worker until resume closes. Fire remains nonblocking so completion and panic cleanup cannot wait on a successor. beforeWait optionally observes an unready gate, outside the signal's Once.

func WithSuspendSignal

func WithSuspendSignal(ctx context.Context) (context.Context, *SuspendSignal)

WithSuspendSignal returns ctx carrying a new signal. The owner must Fire it when the goroutine ends, whether or not it waited.

func (*SuspendSignal) Done

func (s *SuspendSignal) Done() <-chan struct{}

Done is closed at the first wait, or when the owner fires it.

func (*SuspendSignal) Fire

func (s *SuspendSignal) Fire()

Fire closes Done once.

type UID

type UID struct {
	First  uint64
	Second uint64
}

UID is a 128-bit identifier (two uint64s). Used for endpoint tokens.

func NewUID

func NewUID() UID

NewUID generates a random 128-bit UID for endpoint tokens. Uses a single atomic progression on fastRNGState per 128-bit UID.

func ReadFrame

func ReadFrame(r io.Reader, tls bool) (token UID, body []byte, err error)

ReadFrame reads one framed message from r. Returns the endpoint token and the message body (without token). Deprecated: Use FrameReader.Read for reduced allocations.

func WellKnownToken

func WellKnownToken(id int) UID

WellKnownToken returns the UID for a well-known endpoint token. In C++: Endpoint::wellKnownToken(id) = UID(-1, id). The first part is all-ones (0xFFFFFFFFFFFFFFFF), second part is the token ID.

type VerifyPeersError

type VerifyPeersError struct {
	Rule   string
	Reason string
}

VerifyPeersError reports a verify-peers string libfdb_c refuses to parse.

func (*VerifyPeersError) Error

func (e *VerifyPeersError) Error() string

type VerifyPolicy

type VerifyPolicy struct {
	// contains filtered or unexported fields
}

VerifyPolicy is a parsed verify-peers setting, the policy libfdb_c applies to a peer certificate (flow/TLSConfig.actor.cpp TLSPolicy). Any rule that matches accepts the peer.

func ParseVerifyPeers

func ParseVerifyPeers(s string) (*VerifyPolicy, error)

ParseVerifyPeers parses a verify-peers string as set_verify_peers and TLSPolicy::Rule do (TLSConfig.actor.cpp:503-611): rules split on '|', each a comma-separated list of term[<>]?=value.

func (*VerifyPolicy) Verify

func (p *VerifyPolicy) Verify(certs []*x509.Certificate, roots *x509.CertPool) error

Verify applies the policy to the peer's certificates, leaf first, as TLSPolicy::verify_peer does: a rule with Check.Valid=0 accepts any peer; otherwise the chain must verify against roots and one rule must match it. Nil roots trust nothing, as libfdb_c with no CA; never the system roots.

func (*VerifyPolicy) VerifyConnection

func (p *VerifyPolicy) VerifyConnection(roots *x509.CertPool) func(tls.ConnectionState) error

VerifyConnection returns a tls.Config.VerifyConnection hook applying the policy against roots, reading no host name; the config needs InsecureSkipVerify.

type WireLog

type WireLog struct {
	// contains filtered or unexported fields
}

WireLog records every frame sent/received on FDB connections. Enable via FDB_WIRE_LOG=/path/to/file.bin (binary format) or FDB_WIRE_LOG=stderr (human-readable hex to stderr).

Binary format per entry:

[1] direction: 'S' = send, 'R' = recv
[8] timestamp: nanoseconds since Unix epoch, little-endian uint64
[8] token.First: little-endian uint64
[8] token.Second: little-endian uint64
[4] body length: little-endian uint32
[N] body bytes

Use cmd/fdb-wirelog-dump to convert binary logs to human-readable form or diff two logs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL