Documentation
¶
Overview ¶
Package dbrpc is the client/server DB: it serves an embedded ClassAd log (package db) over a message transport (CEDAR in production), with out-of-order request multiplexing so a slow call never head-of-line-blocks others on the same connection. See DESIGN.md.
Index ¶
- Constants
- Variables
- func OpName(op uint8) string
- type AdKV
- type AdReject
- type AggFunc
- type AggRow
- type AggSpec
- type CallStats
- type Catalog
- type Client
- func (c *Client) Admin(ctx context.Context, action string, args ...string) (string, error)
- func (c *Client) AdminTable(ctx context.Context, table, action string, args ...string) (string, error)
- func (c *Client) Aggregate(ctx context.Context, constraint string, groupBy []string, aggs []AggSpec) ([]AggRow, error)
- func (c *Client) AggregateBucketed(ctx context.Context, constraint string, groups []GroupCol, aggs []AggSpec) ([]AggRow, error)
- func (c *Client) AggregateBucketedTable(ctx context.Context, table, constraint string, groups []GroupCol, ...) ([]AggRow, error)
- func (c *Client) AggregateTable(ctx context.Context, table, constraint string, groupBy []string, ...) ([]AggRow, error)
- func (c *Client) ArchiveAppend(ctx context.Context, name, adText string) error
- func (c *Client) ArchiveQuery(ctx context.Context, name, constraint string, limit int) ([]string, error)
- func (c *Client) ArchiveRotate(ctx context.Context, name string) (int, error)
- func (c *Client) ArchiveTables(ctx context.Context) ([]string, error)
- func (c *Client) BackupKeyTable(ctx context.Context, table string) ([]byte, error)
- func (c *Client) Begin(ctx context.Context) (*Tx, error)
- func (c *Client) BeginTable(ctx context.Context, table string) (*Tx, error)
- func (c *Client) Close() error
- func (c *Client) ConvertTableToMemory(ctx context.Context, name string) error
- func (c *Client) CreateArchiveTable(ctx context.Context, name string, cfg db.ArchiveConfig) error
- func (c *Client) CreateExporter(ctx context.Context, def db.ExporterDef) error
- func (c *Client) CreateTable(ctx context.Context, name string) error
- func (c *Client) CreateTableInMemory(ctx context.Context, name string) error
- func (c *Client) CreateView(ctx context.Context, name string, spec db.ViewSpec) error
- func (c *Client) DeleteWhere(ctx context.Context, constraint string) (int, error)
- func (c *Client) DeleteWhereTable(ctx context.Context, table, constraint string) (int, error)
- func (c *Client) Diagnostics(ctx context.Context) (*Diagnostics, error)
- func (c *Client) DiagnosticsTable(ctx context.Context, table string) (*Diagnostics, error)
- func (c *Client) DropExporter(ctx context.Context, name string) error
- func (c *Client) DropTable(ctx context.Context, name string) error
- func (c *Client) DropView(ctx context.Context, name string) error
- func (c *Client) Explain(ctx context.Context, constraint string) (*db.QueryExplain, error)
- func (c *Client) ExplainTable(ctx context.Context, table, constraint string) (*db.QueryExplain, error)
- func (c *Client) GetExporter(ctx context.Context, name string) (db.ExporterDef, bool, error)
- func (c *Client) GetExporterState(ctx context.Context, name string) ([]byte, bool, error)
- func (c *Client) ListExporters(ctx context.Context) ([]ExporterInfo, error)
- func (c *Client) ListViews(ctx context.Context) ([]string, error)
- func (c *Client) MatchExplain(ctx context.Context, reqTable, jobSelector, resTable, targetWhere string) (*db.MatchExplain, error)
- func (c *Client) MatchSorted(ctx context.Context, jobText string, limit int) ([]string, error)
- func (c *Client) MatchSortedTable(ctx context.Context, table, jobText string, limit int) ([]string, error)
- func (c *Client) MatchTables(ctx context.Context, reqTable, resTable, keyAttr, reqWhere, targetWhere string, ...) ([]MatchRow, error)
- func (c *Client) Ordered(ctx context.Context, index int, partition string) ([]OrderedRow, error)
- func (c *Client) OrderedTable(ctx context.Context, table string, index int, partition string) ([]OrderedRow, error)
- func (c *Client) PutExporterState(ctx context.Context, name string, state []byte) error
- func (c *Client) Query(ctx context.Context, constraint string) ([]string, error)
- func (c *Client) QueryAsOfTable(ctx context.Context, table, constraint string, limit int, asOf time.Time) ([]string, error)
- func (c *Client) QueryLimit(ctx context.Context, constraint string, limit int) ([]string, error)
- func (c *Client) QueryRaw(ctx context.Context, constraint string) ([]string, error)
- func (c *Client) QueryRawProject(ctx context.Context, table, constraint string, attrs []string, limit int) ([]string, error)
- func (c *Client) QueryRawProjectStream(ctx context.Context, table, constraint string, attrs []string, limit int, ...) error
- func (c *Client) QueryRawTable(ctx context.Context, table, constraint string, limit int) ([]string, error)
- func (c *Client) QueryRawTableStream(ctx context.Context, table, constraint string, limit int, ...) error
- func (c *Client) QueryRawWireStream(ctx context.Context, table, constraint string, attrs []string, limit int, ...) error
- func (c *Client) QueryTable(ctx context.Context, table, constraint string, limit int) ([]string, error)
- func (c *Client) QueryTableStream(ctx context.Context, table, constraint string, limit int, ...) error
- func (c *Client) Restore(ctx context.Context, r io.Reader) error
- func (c *Client) RestoreTable(ctx context.Context, table string, r io.Reader) error
- func (c *Client) SetEncryptedAttrs(ctx context.Context, table string, attrs ...string) (string, error)
- func (c *Client) Snapshot(ctx context.Context, w io.Writer) error
- func (c *Client) SnapshotTable(ctx context.Context, table string, w io.Writer) error
- func (c *Client) Tables(ctx context.Context) ([]string, error)
- func (c *Client) TruncateTable(ctx context.Context, table string) (string, error)
- func (c *Client) Watch(ctx context.Context, cursor []byte) (<-chan WatchEvent, func(), error)
- func (c *Client) WatchHead(ctx context.Context, table string) ([]byte, error)
- func (c *Client) WatchTable(ctx context.Context, table string, cursor []byte) (<-chan WatchEvent, func(), error)
- type Diagnostics
- type ExporterInfo
- type GroupCol
- type MatchRow
- type MsgConn
- type OrderedRow
- type Pool
- func (p *Pool) Begin(ctx context.Context) (*Tx, error)
- func (p *Pool) Close() error
- func (p *Pool) MatchSorted(ctx context.Context, jobText string, limit int) ([]string, error)
- func (p *Pool) Ordered(ctx context.Context, index int, partition string) ([]OrderedRow, error)
- func (p *Pool) Query(ctx context.Context, constraint string) ([]string, error)
- func (p *Pool) Watch(ctx context.Context, cursor []byte) (<-chan WatchEvent, func(), error)
- type ProposeFunc
- type QueryLog
- type ServeOptions
- type Server
- func (s *Server) Close()
- func (s *Server) ServeConn(conn MsgConn) error
- func (s *Server) ServeConnOpts(conn MsgConn, opts ServeOptions) error
- func (s *Server) SetProposeHook(fn ProposeFunc)
- func (s *Server) StartIdemReaper(interval, maxAge time.Duration) (stop func())
- func (s *Server) StartMaintenance(interval time.Duration, opts db.MaintainOptions)
- func (s *Server) StartTxnReaper(interval, maxIdle time.Duration) (stop func())
- type ServerError
- type Tx
- func (t *Tx) Abort(ctx context.Context) error
- func (t *Tx) Commit(ctx context.Context) error
- func (t *Tx) CommitIdempotent(ctx context.Context, idemKey string) error
- func (t *Tx) DeleteAttribute(ctx context.Context, key, name string) error
- func (t *Tx) DestroyClassAd(ctx context.Context, key string) error
- func (t *Tx) LookupAttr(ctx context.Context, key, name string) (string, bool, error)
- func (t *Tx) LookupClassAd(ctx context.Context, key string) (string, bool, error)
- func (t *Tx) NewClassAd(ctx context.Context, key, adText string) error
- func (t *Tx) NewClassAdBatch(ctx context.Context, items []AdKV) ([]AdReject, error)
- func (t *Tx) NewClassAdBatchPipelined(ctx context.Context, items []AdKV, chunkSize int) ([]AdReject, error)
- func (t *Tx) SetAttribute(ctx context.Context, key, name, expr string) error
- type WatchEvent
- type WriteKind
- type WriteOp
Constants ¶
const DefaultTable = "ads"
DefaultTable is the table name a single-DB server serves and the client targets when a table is not named -- the historical, single-collection view.
Variables ¶
var ErrBucketedUnsupported = errors.New("dbrpc: server does not support bucketed aggregation")
ErrBucketedUnsupported is returned by AggregateBucketed against a server too old to implement the opcode (it rejects the request), so a caller can fall back to client-side bucketing.
var ErrConnClosed = errors.New("dbrpc: connection closed")
ErrConnClosed reports that the dbrpc connection is no longer usable. It wraps the underlying transport cause, so errors.Is(err, ErrConnClosed) identifies the class while errors.Unwrap reaches the specific I/O error.
var WireBatchBudget = 64 << 10
WireBatchBudget caps one wire-row batch frame's payload bytes. It bounds the per-stream buffer on BOTH sides (each holds ~one frame), amortizes the per-frame syscall/wakeup cost, and stays well under the transport's 1MB message ceiling. Measured sensitivity (2000x21KB-ad scans over TCP loopback): 16KB->64KB gains ~6%, 64KB->256KB ~4%, beyond 256KB flat -- so the default stays memory-lean at 64KB (~128KB per active stream across both sides) and a deployment can raise it for the last few percent on whole-ad scans (projected streams are insensitive: their rows are small enough that every budget batches deeply).
Functions ¶
Types ¶
type AdReject ¶ added in v0.13.0
AdReject reports an ad a batch writer could not apply (unparseable text), by its index in the items slice, with the server's error. The other ads were applied; the caller typically logs the rejects and carries on.
type AggRow ¶
AggRow is one group's result: the group-by column values followed by the aggregate values, all rendered as strings (aligned with the request's group columns and aggregate specs).
type AggSpec ¶
AggSpec is one aggregate in a query: a function over an argument attribute. Arg "*" (only meaningful for COUNT) counts every row in the group; otherwise Arg is an attribute name evaluated per ad.
type CallStats ¶ added in v0.16.3
type CallStats struct {
Op uint8 // request op byte (see OpName)
WriteWait time.Duration // blocked acquiring the write lock (another send ahead)
Send time.Duration // in conn.WriteMsg -- getting the request onto the wire
Wait time.Duration // from send complete to response received
}
CallStats is the per-call timing breakdown delivered to Client.Observer. The three durations partition a unary round-trip and pinpoint a stall: a large WriteWait means another sender held the single-writer lock; a large Send means conn.WriteMsg itself blocked (the socket's send buffer filled because the peer was not reading -- comms/server backpressure, not this client); a large Wait means the request left promptly but the server (or return path) was slow.
type Catalog ¶
type Catalog interface {
// Table returns the named table's DB.
Table(name string) (*db.DB, bool)
// CreateTable creates (or returns the existing) named table.
CreateTable(name string) (*db.DB, error)
// CreateTableInMemory creates (or returns the existing) named table as RAM-only.
CreateTableInMemory(name string) (*db.DB, error)
// ConvertTableToMemory drops an existing table's on-disk backing, keeping its data in
// RAM only. DAEMON-gated by the server (it changes a table's durability).
ConvertTableToMemory(name string) error
// DropTable removes the named table and its data.
DropTable(name string) error
// Tables lists the table names.
Tables() []string
// ArchiveTable / CreateArchiveTable / ArchiveTables manage append-only history
// tables. A single-table server does not support them.
ArchiveTable(name string) (*db.ArchiveTable, bool)
CreateArchiveTable(name string, cfg db.ArchiveConfig) (*db.ArchiveTable, error)
ArchiveTables() []string
// CreateView / DropView / Views manage materialized views; ViewBacking returns a view's
// in-memory backing so reads resolve a view name to its materialized rows.
CreateView(name string, spec db.ViewSpec) error
DropView(name string) error
Views() []string
ViewBacking(name string) (*db.DB, bool)
// Exporter registry: passive storage of external-sink definitions and their opaque
// resume state. The server never runs exporters; it only persists these for the
// out-of-process exporter that reads them.
CreateExporter(def db.ExporterDef) error
DropExporter(name string) error
Exporters() []db.ExporterDef
Exporter(name string) (db.ExporterDef, bool)
SaveExporterState(name string, state []byte) error
LoadExporterState(name string) ([]byte, bool, error)
}
Catalog is the set of named tables the server serves. *db.Catalog implements it; a single-DB server wraps its DB as a one-table catalog.
type Client ¶
type Client struct {
// Observer, if set before use, receives a timing breakdown for each completed unary
// call. It lets an embedder (e.g. a collector's Prometheus metrics) localize where a
// round-trip spends its time -- client-side write-lock contention, the socket write
// (TCP backpressure when the server stops reading), or the server+return wait --
// without this package depending on any metrics library. Must not block.
Observer func(CallStats)
// contains filtered or unexported fields
}
Client is one multiplexed connection to a dbrpc Server. It issues requests with monotonic ids and a single reader goroutine demuxes responses by id, so many calls (and independent transactions) proceed concurrently over the one connection with no head-of-line blocking. Safe for concurrent use. For many connections, see Pool.
func NewClient ¶
NewClient runs the mux over conn. Close (or a transport error) fails all in-flight and future calls.
func (*Client) Admin ¶
Admin runs a management action (index/hot-set) on the default table. Requires a DAEMON-authorized connection (see AdminTable).
func (*Client) AdminTable ¶
func (c *Client) AdminTable(ctx context.Context, table, action string, args ...string) (string, error)
AdminTable runs a management action on the named table; it returns the server's human-readable result. Every admin action retunes or restructures the store, so it requires DAEMON authorization -- refused on read-only and ordinary read-write connections alike.
func (*Client) Aggregate ¶
func (c *Client) Aggregate(ctx context.Context, constraint string, groupBy []string, aggs []AggSpec) ([]AggRow, error)
Aggregate runs a server-side GROUP BY: the server buckets the constraint match by the group-by column tuple in a hash map and returns one AggRow per group. With no group columns it returns a single row aggregating the whole match. The aggregation happens on the server, so only the (small) grouped result crosses the wire, not every matched ad.
func (*Client) AggregateBucketed ¶ added in v0.13.0
func (c *Client) AggregateBucketed(ctx context.Context, constraint string, groups []GroupCol, aggs []AggSpec) ([]AggRow, error)
AggregateBucketed is Aggregate with group columns that may be time-bucketed (see GroupCol), pushing the bucketing to the server so only the grouped rows cross the wire. Against a server that does not implement the opcode it returns an error that wraps ErrBucketedUnsupported.
func (*Client) AggregateBucketedTable ¶ added in v0.13.0
func (c *Client) AggregateBucketedTable(ctx context.Context, table, constraint string, groups []GroupCol, aggs []AggSpec) ([]AggRow, error)
AggregateBucketedTable is AggregateBucketed on the named table.
func (*Client) AggregateTable ¶
func (c *Client) AggregateTable(ctx context.Context, table, constraint string, groupBy []string, aggs []AggSpec) ([]AggRow, error)
AggregateTable is Aggregate on the named table.
func (*Client) ArchiveAppend ¶ added in v0.7.0
ArchiveAppend appends an ad (old-ClassAd text) to the named history table.
func (*Client) ArchiveQuery ¶ added in v0.7.0
func (c *Client) ArchiveQuery(ctx context.Context, name, constraint string, limit int) ([]string, error)
ArchiveQuery returns up to limit (<= 0 = all) newest-first matches (old-ClassAd texts) from the named history table -- the condor_history "last K" pattern.
func (*Client) ArchiveRotate ¶ added in v0.7.0
ArchiveRotate enforces the named archive's retention policy now (using the server's clock for age-based rules), returning how many sealed segments were dropped.
func (*Client) ArchiveTables ¶ added in v0.7.0
ArchiveTables lists the history table names.
func (*Client) BackupKeyTable ¶ added in v0.7.0
BackupKeyTable retrieves the named table's backup key -- the escrow key that decrypts its encrypted snapshots independently of the pool keys. DAEMON-level. Errors if encryption is not enabled.
func (*Client) BeginTable ¶
BeginTable starts a new independent transaction on the named table.
func (*Client) ConvertTableToMemory ¶ added in v0.10.2
ConvertTableToMemory drops an existing table's on-disk backing, keeping its current contents in RAM only (they are gone after a server restart). Requires DAEMON authorization. Best run during low write activity: a write that races the conversion can be lost (the server takes a consistent snapshot but does not globally quiesce writers).
func (*Client) CreateArchiveTable ¶ added in v0.7.0
CreateArchiveTable creates (or no-ops if present) an append-only history table. cfg configures indexes / zone maps / retention on first creation.
func (*Client) CreateExporter ¶ added in v0.14.0
CreateExporter registers an external-sink exporter definition. DAEMON-only. The server stores the definition (and later its resume state) but never runs the exporter -- an out-of-process exporter reads these back and does the work.
func (*Client) CreateTable ¶
CreateTable creates (or no-ops if present) the named table.
func (*Client) CreateTableInMemory ¶ added in v0.10.2
CreateTableInMemory creates (or no-ops if present) the named table as RAM-only: its data lives only in memory and is not recovered across a server restart. On a persistent server this avoids the disk I/O of persistence for high-churn, reconstructible data.
func (*Client) CreateView ¶ added in v0.12.0
CreateView creates a materialized view named name from spec. The server materializes it synchronously and then maintains it live from the base table's change stream, so an error (e.g. the base table exceeds the view's cardinality limit) is reported here. A view is queried like a table (SELECT ... FROM <name>) but is read-only.
func (*Client) DeleteWhere ¶ added in v0.8.0
DeleteWhere removes every ad matching constraint from the default table and returns the number removed. The delete runs server-side as a single call -- the db.DeleteWhere pushdown (batched, optimistic-retry, self-healing) -- rather than a per-key query-then-delete round trip per ad. Refused on a read-only connection.
func (*Client) DeleteWhereTable ¶ added in v0.8.0
DeleteWhereTable is DeleteWhere against a named table. Express a time-based expiry sweep as the constraint (e.g. "<now> > LastHeardFrom + Lifetime").
func (*Client) Diagnostics ¶
func (c *Client) Diagnostics(ctx context.Context) (*Diagnostics, error)
Diagnostics fetches the default table's storage stats, hot set, indexes, and tuning suggestions.
func (*Client) DiagnosticsTable ¶
DiagnosticsTable fetches the named table's diagnostics.
func (*Client) DropExporter ¶ added in v0.14.0
DropExporter removes an exporter's definition and resume state. DAEMON-only.
func (*Client) DropView ¶ added in v0.12.0
DropView removes a materialized view (its definition and its in-memory data).
func (*Client) ExplainTable ¶
func (c *Client) ExplainTable(ctx context.Context, table, constraint string) (*db.QueryExplain, error)
ExplainTable reports how the named table would execute a constraint query.
func (*Client) GetExporter ¶ added in v0.14.0
GetExporter returns a single exporter's full definition (including Config). DAEMON-only. The bool is false when no exporter of that name exists.
func (*Client) GetExporterState ¶ added in v0.14.0
GetExporterState returns an exporter's last checkpointed resume-state blob. DAEMON-only. The bool is false when the exporter has never checkpointed (start from the beginning).
func (*Client) ListExporters ¶ added in v0.14.0
func (c *Client) ListExporters(ctx context.Context) ([]ExporterInfo, error)
ListExporters returns the registered exporters' names and kinds (no config).
func (*Client) MatchExplain ¶
func (c *Client) MatchExplain(ctx context.Context, reqTable, jobSelector, resTable, targetWhere string) (*db.MatchExplain, error)
MatchExplain reports how matchmaking the first request in reqTable matching jobSelector against resTable would execute: the job's Requirements rewritten over the slot (job constants baked in) and which resulting probes prune via a resource index. jobSelector is a constraint (e.g. `Key == "1.0"`) identifying the request.
func (*Client) MatchSorted ¶
MatchSorted returns job's matches in the default table, ranked best-first, at most limit (<=0 = all).
func (*Client) MatchSortedTable ¶
func (c *Client) MatchSortedTable(ctx context.Context, table, jobText string, limit int) ([]string, error)
MatchSortedTable returns job's ranked matches in the named table.
func (*Client) MatchTables ¶
func (c *Client) MatchTables(ctx context.Context, reqTable, resTable, keyAttr, reqWhere, targetWhere string, limit int, significantAttrs []string) ([]MatchRow, error)
MatchTables performs cross-table matchmaking as a greedy assignment: it walks the requests in reqTable matching reqWhere (in table order) and gives each one the single best-ranked resource in resTable — bilaterally matching, passing the resource-side filter targetWhere, and not already assigned to an earlier request — then removes that resource from the pool. limit bounds the number of *requests* assigned (the first `limit` in order), not resources per request. The result is one row per assigned request (Resource is "" when it could not be placed). keyAttr is the ad attribute holding each row's key.
significantAttrs, if non-empty, enables autoclustering: requests whose significant attributes are textually identical share one ranked-candidate computation (the matchmaking runs once per distinct signature and is reused; assignment still consumes resources per request), mirroring HTCondor's significant-attribute autoclusters. It must list every attribute the match depends on (the request's Requirements and Rank, and the request attributes the resources' Requirements reference).
func (*Client) Ordered ¶
Ordered streams one partition of the index-th configured ordered index in sort order (the negotiator resource-request path). One-shot: the whole partition is returned (the server-side resume cursor is not carried over the wire).
func (*Client) OrderedTable ¶
func (c *Client) OrderedTable(ctx context.Context, table string, index int, partition string) ([]OrderedRow, error)
OrderedTable streams one partition of an ordered index in the named table.
func (*Client) PutExporterState ¶ added in v0.14.0
PutExporterState durably stores an exporter's opaque resume-state blob. DAEMON-only. The exporter calls this after downstream has accepted its data (the at-least-once boundary).
func (*Client) Query ¶
Query returns the committed ads (old-ClassAd texts) in the default table ("ads") matching a constraint. The server streams results; a slow scan does not block other calls.
func (*Client) QueryAsOfTable ¶ added in v0.12.0
func (c *Client) QueryAsOfTable(ctx context.Context, table, constraint string, limit int, asOf time.Time) ([]string, error)
QueryAsOfTable is QueryTable for a point-in-time ("AS OF") query: it returns the ads in the named table matching constraint as they were at asOf. The server errors if time travel is not enabled on the table or asOf is older than the retained window.
func (*Client) QueryLimit ¶
QueryLimit is Query with a row cap (<= 0 = all) on the default table.
func (*Client) QueryRaw ¶ added in v0.8.0
QueryRaw is Query but returns each ad as old-ClassAd wire text (the AST-free relay form for the caller): the server renders straight from the stored representation via the db QueryRaw pushdown, and the caller can forward the text without building a ClassAd. Private attributes are stripped unless the connection is privileged.
func (*Client) QueryRawProject ¶ added in v0.10.0
func (c *Client) QueryRawProject(ctx context.Context, table, constraint string, attrs []string, limit int) ([]string, error)
QueryRawProject is QueryRawTable with a server-side projection: each returned ad carries only the attributes in attrs (matched case-insensitively) plus MyType/TargetType, so a query for a few attributes does not pull every attribute of every ad across the wire. An empty attrs behaves like QueryRawTable (all attributes). Private attributes are stripped unless the connection is privileged.
func (*Client) QueryRawProjectStream ¶ added in v0.13.0
func (c *Client) QueryRawProjectStream(ctx context.Context, table, constraint string, attrs []string, limit int, yield func(row string) bool) error
QueryRawProjectStream is QueryRawProject (server-side projection) with the streaming delivery of QueryRawTableStream.
func (*Client) QueryRawTable ¶ added in v0.8.0
func (c *Client) QueryRawTable(ctx context.Context, table, constraint string, limit int) ([]string, error)
QueryRawTable is QueryRaw against a named table with an optional limit.
func (*Client) QueryRawTableStream ¶ added in v0.13.0
func (c *Client) QueryRawTableStream(ctx context.Context, table, constraint string, limit int, yield func(row string) bool) error
QueryRawTableStream is QueryRawTable that hands each matching ad's old-ClassAd wire text to yield as it arrives, instead of collecting the whole result into a slice -- so a relay (e.g. the collector) can forward each ad to its own client without buffering the entire result set. yield returns false to stop early. See streamEach for the error contract (a failure can arrive after some rows have been yielded).
func (*Client) QueryRawWireStream ¶ added in v0.16.4
func (c *Client) QueryRawWireStream(ctx context.Context, table, constraint string, attrs []string, limit int, redact bool, yield func(row []byte) bool) error
QueryRawWireStream streams matching ads as wire-form rows (self-contained inline-names subset ads -- render them with collections.RenderRawAdInline), batched many rows per frame (WireBatchBudget on the server side). The row slice passed to yield aliases the frame buffer and is valid only until yield returns; redact requests source-side private-attribute stripping even on a privileged connection. Requires a server with opQueryRawWire; an older server answers respBad and the error surfaces here (callers fall back to the text row stream).
func (*Client) QueryTable ¶
func (c *Client) QueryTable(ctx context.Context, table, constraint string, limit int) ([]string, error)
QueryTable returns the committed ads in the named table matching constraint, stopping after at most limit matches (<= 0 = all). The limit is pushed to the server, which stops the scan early.
func (*Client) QueryTableStream ¶ added in v0.13.0
func (c *Client) QueryTableStream(ctx context.Context, table, constraint string, limit int, yield func(row string) bool) error
QueryTableStream is QueryTable that hands each matching ad's text to yield as it arrives instead of collecting the whole result first (see streamEach). yield returns false to stop early.
func (*Client) RestoreTable ¶ added in v0.7.0
RestoreTable replaces the named table with the snapshot read from r. DAEMON-level and destructive: the server spools the upload and restores under the DB-wide lock. The upload streams in chunks, so the client does not buffer the whole snapshot.
func (*Client) SetEncryptedAttrs ¶ added in v0.7.0
func (c *Client) SetEncryptedAttrs(ctx context.Context, table string, attrs ...string) (string, error)
SetEncryptedAttrs sets the explicit attributes encrypted at rest on the named table (private attributes are always encrypted). It is a DAEMON-level action: the server refuses it unless the connection is privileged. Passing no attributes clears the explicit set. Returns the server's human-readable result.
func (*Client) SnapshotTable ¶ added in v0.7.0
SnapshotTable streams a consistent backup of the named table to w. DAEMON-level: a snapshot carries every attribute, including private ones. The server streams it in chunks, so neither side buffers the whole database.
func (*Client) TruncateTable ¶ added in v0.7.0
TruncateTable removes every ad from the named table. It is a DAEMON-level action (destructive, DB-wide locked): the server refuses it unless the connection is privileged. Returns the server's human-readable result.
func (*Client) Watch ¶
Watch streams changes committed after cursor (nil = from now) on the channel, which closes when the returned stop is called, the connection fails, or the server ends the stream. A full replay leads with a reset event.
func (*Client) WatchHead ¶ added in v0.7.0
WatchHead returns an opaque cursor at the current head of table's change log, so a following WatchTable(table, cursor) streams only subsequent changes (no replay of current contents) -- the "tail from now" path.
func (*Client) WatchTable ¶
func (c *Client) WatchTable(ctx context.Context, table string, cursor []byte) (<-chan WatchEvent, func(), error)
WatchTable streams changes to the named table.
type Diagnostics ¶
type Diagnostics struct {
Stats db.Stats `json:"stats"`
OpStats db.OpStats `json:"opStats"`
Hot []string `json:"hot"`
CategoricalIndexes []string `json:"categoricalIndexes"`
ValueIndexes []string `json:"valueIndexes"`
IndexSizes db.IndexSizes `json:"indexSizes"`
Codec db.CodecStats `json:"codec"`
Suggestions []db.IndexSuggestion `json:"suggestions"`
DropSuggestions []db.DropSuggestion `json:"dropSuggestions"`
// EncryptionEnabled reports whether encryption at rest is active; EncryptedAttrs is
// the explicit encrypted-attribute set (private attributes are always encrypted and
// are not listed here).
EncryptionEnabled bool `json:"encryptionEnabled"`
EncryptedAttrs []string `json:"encryptedAttrs,omitempty"`
}
Diagnostics is a snapshot of the store's storage, hot set, indexes, and index tuning advice -- the payload of the diagnostic ".stats"/".indexes"/".hot" commands.
type ExporterInfo ¶ added in v0.14.0
ExporterInfo is the name+kind pair returned by ListExporters. It deliberately omits the exporter's Config, which may hold credentials and is only returned by GetExporter to a DAEMON-authorized client.
type GroupCol ¶ added in v0.13.0
GroupCol is one GROUP BY column for a (possibly bucketed) aggregate: the attribute Attr, optionally floored into fixed-width buckets. BucketWidth == 0 groups by the raw attribute value; BucketWidth > 0 (seconds) groups by the epoch-aligned bucket floor(number(Attr)/BucketWidth)*BucketWidth, and a row whose Attr is not a finite number drops out of the result. This is the shared shape a bucketed aggregate (here) and a bucketed materialized view can both group by.
type MatchRow ¶
MatchRow is one matchmaking result: a request key, the resource it matched, and the request's Rank of that resource (Rank is "" when the request has no numeric Rank for it).
type MsgConn ¶
MsgConn is a reliable, ordered, bidirectional message transport: each WriteMsg / ReadMsg carries one discrete frame. CEDAR's stream.Stream satisfies it via an adapter (see cedaradapter); tests use a length-prefixed net.Pipe. WriteMsg may be called concurrently with ReadMsg, but not concurrently with itself -- the mux serializes writers.
func NewCedarConn ¶
NewCedarConn wraps an established CEDAR stream (from a client dial, or a server HandlerFunc's Conn.Stream) as a dbrpc transport. ctx bounds the connection's I/O.
func NewStreamConn ¶
func NewStreamConn(rw io.ReadWriteCloser) MsgConn
NewStreamConn frames messages over an ordered byte stream. Exposed so a caller can run dbrpc over any io.ReadWriteCloser (e.g. a plain TCP conn) without CEDAR.
type OrderedRow ¶
OrderedRow is one ad from an ordered scan (old-ClassAd text) with its cluster signature -- run-length-fold equal signatures into a resource-request list.
type Pool ¶
type Pool struct {
// contains filtered or unexported fields
}
Pool is a set of multiplexed connections to one Server, load-balanced round-robin. It borrows the database/sql idea of a connection pool, but adapts it: an SQL driver needs a connection per in-flight query (connections do not mux), so its pool serializes checkout; here each Client already multiplexes many concurrent calls, so the pool exists for throughput across connections and fault isolation, not mutual exclusion. A transaction begun through the pool pins the connection it started on (its ops go over that one Client, in order), while that connection keeps serving everyone else.
func NewPool ¶
NewPool dials n connections with dial and multiplexes each. On any dial error it closes the connections already opened and returns the error.
func (*Pool) Begin ¶
Begin starts a transaction on a pool connection; the returned Tx's operations all run over that connection (server-side transaction state + op ordering).
func (*Pool) MatchSorted ¶
MatchSorted runs a ranked match on a pool connection.
type ProposeFunc ¶ added in v0.7.0
ProposeFunc applies a committing transaction's ops to the replicated store via consensus. table is the transaction's table; ops preserve issue order. It returns nil on a quorum-committed apply, or an error (e.g. not-the-leader) that is surfaced to the client.
type QueryLog ¶ added in v0.10.0
type QueryLog struct {
Op string // the query opcode: "Query", "QueryRaw", ...
Table string // the queried table
Constraint string // the constraint expression ("" / "true" = match-all)
Limit int // the client's LIMIT (0 = unlimited)
Rows int // rows streamed back
Duration time.Duration // wall-clock time to run + stream the query
}
QueryLog is one observed query, passed to ServeOptions.QueryLog.
type ServeOptions ¶
type ServeOptions struct {
// ReadOnly rejects the mutating operations (NewClassAd, DestroyClassAd,
// SetAttribute, DeleteAttribute) with an error; reads, snapshots (Begin),
// and queries still work. A read-only peer may still Begin/Abort a
// transaction to get a stable snapshot for reads.
ReadOnly bool
// IncludePrivate renders returned ads with their private (secret)
// attributes intact (classad.StringWithPrivate). When false (the default),
// private attributes are stripped from every ad this connection sees, so an
// under-privileged peer never learns claim ids and other secrets.
IncludePrivate bool
// Privileged admits the DAEMON-level administrative actions -- ALL of the admin
// table (index/hot/compact/rewrite/codec.retrain, plus the security/durability ones
// like the encryption toggle and truncate). These retune or restructure the store,
// so an ordinary WRITE-level session (which may read and write ads) is refused them;
// only a DAEMON peer sets this true. Read-only diagnostics are a separate opcode and
// are not gated here.
Privileged bool
// QueryLog, if set, is called once per streamed query with a summary of what
// the client asked for and what it cost. It is an opt-in query log for
// operators: it makes visible, for example, a client that fetches every
// attribute of every ad instead of projecting server-side (a slow, chatty
// query pattern). Called from the connection's read-loop goroutine, so it must
// not block.
QueryLog func(QueryLog)
}
ServeOptions scopes what a single served connection may do. The zero value is full read/write access with private attributes excluded from returned ads (the historical ServeConn behavior). A privilege-scoped front end (e.g. an HTCondor daemon serving READ vs WRITE peers) sets these per connection.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server serves an embedded ClassAd log (*db.DB) to remote clients. It is embeddable: create it around a DB, optionally start its managed maintenance goroutines, and hand it each accepted connection via ServeConn. Concurrent connections and concurrent in-flight requests per connection are supported; requests are dispatched as they arrive and responses carry the request id, so a slow call never head-of-line-blocks others.
func NewServer ¶
NewServer returns a single-table server over d, served as table "ads". The caller owns d's lifetime. Table create/drop are unsupported on this server.
func NewServerCatalog ¶
NewServerCatalog returns a multi-table server over cat.
func (*Server) Close ¶
func (s *Server) Close()
Close stops the server's managed goroutines. It does not close the DB.
func (*Server) ServeConn ¶
ServeConn runs the request loop on one connection until it errors or the peer closes. Blocking; run one per accepted connection. Watches started on the connection are cancelled when it returns. Equivalent to ServeConnOpts with the zero ServeOptions (full read/write, private attributes excluded).
func (*Server) ServeConnOpts ¶
func (s *Server) ServeConnOpts(conn MsgConn, opts ServeOptions) error
ServeConnOpts is ServeConn scoped by opts: a read-only and/or private-stripping view of the same DB. Use it to serve a privilege-scoped peer (e.g. an HTCondor READ-level client) from the same Server.
func (*Server) SetProposeHook ¶ added in v0.7.0
func (s *Server) SetProposeHook(fn ProposeFunc)
SetProposeHook routes committing writes through fn (raft) instead of the local store. Call once before serving. Passing nil restores direct local commits (the default). When set, the server is otherwise read-only against its local store: the hook is the sole writer.
func (*Server) StartIdemReaper ¶ added in v0.9.0
StartIdemReaper runs reapIdemMarkers every interval, deleting idempotency markers older than maxAge, until the returned stop is called. maxAge should exceed the longest window over which a client might replay a unit of work (its retry budget), so a marker is never reaped while a late replay could still arrive. Servers that never see CommitIdempotent need not start it (there is nothing to reap).
func (*Server) StartMaintenance ¶
func (s *Server) StartMaintenance(interval time.Duration, opts db.MaintainOptions)
StartMaintenance starts server-managed background maintenance: a single goroutine that, each tick, re-enumerates the catalog's tables and runs one Maintain pass (index auto-tune, hot-set refresh, and -- if opts.Retrain -- dictionary retrain) on each. Re-enumerating each tick means tables created after startup are maintained too (the old per-table start missed them).
The cadence is adaptive: interval is a floor, but the wait before the next pass is raised to keep maintenance under maintenanceMaxDutyCycle of wall-clock time -- so on a large store where a pass (dominated by dictionary retrain's recompaction) takes minutes, passes automatically space out rather than consuming the daemon. Stopped by Close.
func (*Server) StartTxnReaper ¶ added in v0.9.0
StartTxnReaper runs reapIdleTxns every interval, aborting transactions idle longer than maxIdle, until the returned stop is called. Optional: disconnect cleanup is automatic; a server that wants to bound transactions abandoned on still-open connections starts this.
type ServerError ¶ added in v0.9.0
type ServerError struct{ Msg string }
ServerError is a logical error the server returned for a request (wire status stErr): a bad constraint, an unknown table, a malformed op. It is deterministic -- replaying the request fails the same way -- so callers should surface it rather than retry.
func (*ServerError) Error ¶ added in v0.9.0
func (e *ServerError) Error() string
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx is a client-side handle to a server transaction. Its operations are issued in order over the client (the transaction is server-side state); different Tx (even on one Client) proceed concurrently.
func (*Tx) Commit ¶
Commit applies the transaction, returning *db.ConflictError with the conflicted keys if any lost a write-write race (the rest committed), or nil.
func (*Tx) CommitIdempotent ¶ added in v0.9.0
CommitIdempotent is Commit with exactly-once semantics across retries: the server records a durable marker under idemKey, committed atomically with this transaction's writes, so replaying the SAME unit of work (same idemKey) after an ambiguous failure -- a reconnect where the original commit's fate is unknown -- applies it at most once. The caller must generate idemKey ONCE per unit of work and reuse it verbatim on every replay. Use this for non-idempotent transactions (e.g. relative updates, appends); an already-idempotent-by-key workload can use the cheaper plain Commit. Returns the same results as Commit (nil, or *db.ConflictError on a genuine write-write conflict).
func (*Tx) DeleteAttribute ¶
DeleteAttribute removes key's attribute name.
func (*Tx) DestroyClassAd ¶
DestroyClassAd removes key.
func (*Tx) LookupAttr ¶
LookupAttr returns key's attribute name (unparsed expression) as the transaction sees it, or ("", false).
func (*Tx) LookupClassAd ¶
LookupClassAd returns key's ad (old-ClassAd text) as the transaction sees it.
func (*Tx) NewClassAd ¶
NewClassAd stores the ad (old-ClassAd text) under key.
func (*Tx) NewClassAdBatch ¶ added in v0.13.0
NewClassAdBatch stores many ads under one transaction in a single round-trip, instead of one request/ack per ad. It returns the ads the server rejected (bad text) so the caller can log them; the rest are applied. The whole request must fit the stream's max message size, so for a large batch prefer NewClassAdBatchPipelined, which chunks and pipelines automatically.
func (*Tx) NewClassAdBatchPipelined ¶ added in v0.13.0
func (t *Tx) NewClassAdBatchPipelined(ctx context.Context, items []AdKV, chunkSize int) ([]AdReject, error)
NewClassAdBatchPipelined stores many ads under one transaction with the round-trips pipelined: it splits items into chunks of chunkSize ads and sends EVERY chunk frame back-to-back without waiting for any chunk's ack, then collects all the acks. So the chunks flow independently of the acks and the wire cost is ~one round-trip regardless of ad count -- not one per ad, nor one serialized round-trip per chunk -- while each message stays small and the server applies a whole chunk under a single transaction- lock acquisition (chunkSize goroutines/locks for the batch, not one per ad).
It returns the ads the server rejected (unparseable), indexed into items. A whole- chunk failure -- a dropped connection, or the transaction gone ("no such transaction") -- is returned as an error so the caller aborts and replays the batch. chunkSize <= 0 defaults to 64.
type WatchEvent ¶
type WatchEvent struct {
Kind uint8 // 0 upsert, 1 delete, 2 reset (see db.WatchKind)
Key string
AdText string
Cursor []byte
}
WatchEvent is one change delivered over a Watch. AdText is the ad's old-ClassAd text (empty for a delete/reset). Cursor resumes the watch just after this event.