diff --git a/README.md b/README.md index ecbef5741..a6daeb234 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ The main operator and integration tools under `cmd/` are: ## Future direction: from observation to action -The longer-term direction is for xtcp2 to take network actions as well as observe. goip already constructs requests for a growing set of write operations, but **live kernel writes remain incomplete and disabled**: supported write commands serialize requests to `GOIP_WRITE_OUT` for validation and refuse to apply them. The [write-path and parity documentation](docs/netlink/README.md) tracks that work; the [network-control gRPC design](docs/design-network-control-grpc.md) describes proposed APIs, not an available service. +The longer-term direction is for xtcp2 to take network actions as well as observe. goip constructs requests for a growing set of write operations, and the CLI's write commands serialize them to `GOIP_WRITE_OUT` for validation and refuse to apply them. The one live-write path is the opt-in [TCP route treatment controller](docs/tcp-controller.md): its actuator installs host routes in a private table through goip, with ownership and readback checks, and is disabled unless an operator enables it. The [write-path and parity documentation](docs/netlink/README.md) tracks the rest of that work; the [network-control gRPC design](docs/design-network-control-grpc.md) describes proposed APIs, not an available service. Future network control and true BGP-origin/next-hop ASN enrichment are separate developments. Neither is required to use today's collection, inspection, or operational alerting features. diff --git a/build/containers/clickhouse/format_schemas/xtcp_flat_record.proto b/build/containers/clickhouse/format_schemas/xtcp_flat_record.proto index 657a035bb..794de6e47 100644 --- a/build/containers/clickhouse/format_schemas/xtcp_flat_record.proto +++ b/build/containers/clickhouse/format_schemas/xtcp_flat_record.proto @@ -94,7 +94,7 @@ message XtcpFlatRecord { "class_id", "sock_opt", "c_group"; // ==== metadata (1-299) ===================================================== - // Free: 3-9, 11-19, 22-29, 33-39, 44-49, 52-59, 63-99, 108-119, 125-199, + // Free: 3-9, 11-19, 33-39, 44-49, 52-59, 63-99, 108-119, 125-199, // 208-219, 225-299. Uplink slots are fixed at two (100s, 200s); a third slot // would take 250-274, NOT 300 (that is the enrichment block). @@ -123,6 +123,17 @@ message XtcpFlatRecord { // -location flag or LOCATION env. Constant for every record from one // daemon instance. string location = 21; + // Controller provenance. Empty/zero means observation-only legacy producer. + string agent_id = 22; + string host_boot_id = 23; + string collection_id = 24; + uint64 treatment_state_revision = 25; + string treatment_assignment_id = 26; + uint64 treatment_generation = 27; + int64 treatment_applied_timestamp_ns = 28; + // True only when the observed socket algorithm matches a verified route + // assignment in this namespace. This does not prove initial-window exposure. + bool treatment_algorithm_exposed = 29; // ---- metadata: network namespace identity (30s) -------------------------- // network namespace — best-effort human name (bind-mount name, else a diff --git a/build/containers/clickhouse/initdb.d/sql/xtcp_treatment_migration.sql b/build/containers/clickhouse/initdb.d/sql/xtcp_treatment_migration.sql new file mode 100644 index 000000000..c789114d7 --- /dev/null +++ b/build/containers/clickhouse/initdb.d/sql/xtcp_treatment_migration.sql @@ -0,0 +1,30 @@ +-- Apply to an existing deployment before enabling controller agents. +-- Additive migration: never drop telemetry tables or reset Kafka offsets. +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS agent_id String; +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS host_boot_id String; +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS collection_id String; +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS treatment_state_revision UInt64; +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS treatment_assignment_id String; +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS treatment_generation UInt64; +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS treatment_applied_timestamp_ns Int64; +ALTER TABLE xtcp.xtcp_flat_records_v2 ADD COLUMN IF NOT EXISTS treatment_algorithm_exposed Bool; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS agent_id String; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS host_boot_id String; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS collection_id String; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS treatment_state_revision UInt64; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS treatment_assignment_id String; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS treatment_generation UInt64; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS treatment_applied_timestamp_ns Int64; +ALTER TABLE xtcp.xtcp_flat_records ADD COLUMN IF NOT EXISTS treatment_algorithm_exposed Bool; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS agent_id String; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS host_boot_id String; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS collection_id String; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS treatment_state_revision UInt64; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS treatment_assignment_id String; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS treatment_generation UInt64; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS treatment_applied_timestamp_ns Int64; +ALTER TABLE xtcp.xtcp_flat_records_kafka ADD COLUMN IF NOT EXISTS treatment_algorithm_exposed Bool; +ALTER TABLE xtcp.xtcp_flat_records_v2_mv MODIFY QUERY +SELECT fromUnixTimestamp64Nano(timestamp_ns) AS timestamp_ns, * EXCEPT (timestamp_ns) +FROM xtcp.xtcp_flat_records_kafka +WHERE length(_error) = 0 AND schema_version = 2; diff --git a/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records.sql b/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records.sql index 2d1ae1108..4454e1a77 100644 --- a/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records.sql +++ b/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records.sql @@ -342,6 +342,14 @@ CREATE TABLE IF NOT EXISTS xtcp.xtcp_flat_records_v2 -- https://clickhouse.com/docs/en/sql-reference/data-types/lowcardinality hostname LowCardinality(String), location LowCardinality(String), + agent_id String, + host_boot_id String, + collection_id String, + treatment_state_revision UInt64, + treatment_assignment_id String, + treatment_generation UInt64, + treatment_applied_timestamp_ns Int64, + treatment_algorithm_exposed Bool, -- ---- metadata: network namespace identity (30s) ------------------------ netns String CODEC(ZSTD), diff --git a/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records_kafka.sql b/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records_kafka.sql index 4aad06239..78562a137 100644 --- a/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records_kafka.sql +++ b/build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records_kafka.sql @@ -49,6 +49,14 @@ CREATE TABLE IF NOT EXISTS xtcp.xtcp_flat_records_kafka -- https://clickhouse.com/docs/en/sql-reference/data-types/lowcardinality hostname LowCardinality(String), location LowCardinality(String), + agent_id String, + host_boot_id String, + collection_id String, + treatment_state_revision UInt64, + treatment_assignment_id String, + treatment_generation UInt64, + treatment_applied_timestamp_ns Int64, + treatment_algorithm_exposed Bool, -- ---- metadata: network namespace identity (30s) ------------------------ netns String CODEC(ZSTD), diff --git a/cmd/xtcp2-controller/main.go b/cmd/xtcp2-controller/main.go new file mode 100644 index 000000000..27ce825da --- /dev/null +++ b/cmd/xtcp2-controller/main.go @@ -0,0 +1,249 @@ +package main + +import ( + "context" + "crypto/tls" + "encoding/json" + "errors" + "flag" + "fmt" + "log" + "net" + "net/http" + "os" + "os/signal" + "strings" + "sync" + "syscall" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + chwarehouse "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence/clickhouse" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +func main() { + if e := run(); e != nil { + log.Print(e) + os.Exit(1) + } +} + +// options are the controller's command-line settings. +type options struct { + listen, statusListen string + cert, key, ca string + dsnFile string + migrate bool + clickhouse, table string + templateFile string + discoveryInterval, discoveryWindow time.Duration +} + +func parseFlags() (*options, error) { + o := new(options) + flag.StringVar(&o.listen, "listen", ":9443", "mTLS gRPC listener") + flag.StringVar(&o.statusListen, "statusListen", "127.0.0.1:9444", "mTLS status/metrics HTTP listener") + flag.StringVar(&o.cert, "cert", "", "server certificate") + flag.StringVar(&o.key, "key", "", "server private key") + flag.StringVar(&o.ca, "ca", "", "client CA") + flag.StringVar(&o.dsnFile, "databaseDSNFile", "", "file containing PostgreSQL DSN (or XTCP_CONTROLLER_DATABASE_DSN)") + flag.BoolVar(&o.migrate, "migrate", false, "apply additive PostgreSQL schema before serving") + flag.StringVar(&o.clickhouse, "clickhouse", "", "ClickHouse HTTP(S) endpoint; absent disables analysis and lease renewal") + flag.StringVar(&o.table, "clickhouseTable", "xtcp.xtcp_flat_records_v2", "source telemetry table") + flag.StringVar(&o.templateFile, "discoveryTemplates", "", "optional JSON array of candidate discovery templates") + flag.DurationVar(&o.discoveryInterval, "discoveryInterval", 30*time.Minute, "candidate discovery interval (at least one minute; checked on maintenance ticks)") + flag.DurationVar(&o.discoveryWindow, "discoveryWindow", time.Hour, "candidate discovery lookback (one minute to seven days)") + flag.Parse() + if o.discoveryInterval < time.Minute || o.discoveryInterval > 24*time.Hour || o.discoveryWindow < time.Minute || o.discoveryWindow > 7*24*time.Hour { + return nil, fmt.Errorf("discovery interval must be 1m..24h and window 1m..168h") + } + return o, nil +} + +// dsn reads the PostgreSQL DSN from the file flag or the environment. +func (o *options) dsn() (string, error) { + dsn := os.Getenv("XTCP_CONTROLLER_DATABASE_DSN") + if o.dsnFile != "" { + b, e := os.ReadFile(o.dsnFile) + if e != nil { + return "", e + } + dsn = strings.TrimSpace(string(b)) + } + if dsn == "" { + return "", fmt.Errorf("PostgreSQL DSN required") + } + return dsn, nil +} + +// templates loads the discovery templates, which need a warehouse. +func (o *options) templates(warehouse *chwarehouse.Client) ([]controller.DiscoveryTemplate, error) { + if o.templateFile == "" { + return nil, nil + } + b, e := os.ReadFile(o.templateFile) + if e != nil { + return nil, e + } + var templates []controller.DiscoveryTemplate + if e = json.Unmarshal(b, &templates); e != nil { + return nil, e + } + if warehouse == nil { + return nil, fmt.Errorf("discovery requires ClickHouse") + } + return templates, nil +} + +// openStore connects to PostgreSQL and applies the schema when asked. +func (o *options) openStore(ctx context.Context) (*postgres.Store, error) { + dsn, err := o.dsn() + if err != nil { + return nil, err + } + db, err := postgres.Open(ctx, dsn) + if err != nil { + return nil, err + } + if o.migrate { + if err = db.Migrate(ctx); err != nil { + return nil, errors.Join(err, db.Close()) + } + } + return db, nil +} + +// warehouse is one adapter behind two ports: evidence.Source for analysis +// and lease renewal, evidence.Warehouse for discovery. Both are nil without +// -clickhouse. +func (o *options) warehouse() (*chwarehouse.Client, evidence.Source) { + if o.clickhouse == "" { + return nil, nil + } + w := &chwarehouse.Client{URL: o.clickhouse, Table: o.table, Username: os.Getenv("XTCP_CLICKHOUSE_USER"), Password: os.Getenv("XTCP_CLICKHOUSE_PASSWORD")} + return w, w +} + +func run() (err error) { + o, err := parseFlags() + if err != nil { + return err + } + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT) + defer cancel() + tlsConfig, e := identity.TLSConfig(o.cert, o.key, o.ca, "", true) + if e != nil { + return e + } + db, e := o.openStore(ctx) + if e != nil { + return e + } + defer func() { + if cerr := db.Close(); cerr != nil { + log.Printf("database close: %v", cerr) + } + }() + warehouse, source := o.warehouse() + s := &controller.Server{Store: db, Hub: controller.NewNotificationHub(), DiscoveryWindow: o.discoveryWindow, EvidenceSource: source} + templates, e := o.templates(warehouse) + if e != nil { + return e + } + // grpcServer.Serve owns the listener and closes it when it stops. + listener, e := (&net.ListenConfig{}).Listen(ctx, "tcp", o.listen) + if e != nil { + return e + } + grpcServer := grpc.NewServer(append(controller.GRPCOptions(), grpc.Creds(credentials.NewTLS(tlsConfig)))...) + pb.RegisterAgentControlServiceServer(grpcServer, s) + pb.RegisterOperatorServiceServer(grpcServer, s) + var wg sync.WaitGroup + wg.Add(2) + go func() { defer wg.Done(); s.RunNotifications(ctx) }() + go func() { defer wg.Done(); housekeep(ctx, s, source, warehouse, templates, o.discoveryInterval) }() + statusServer := &http.Server{Addr: o.statusListen, Handler: s.StatusHandler(), TLSConfig: tlsConfig.Clone(), ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: time.Minute} + failed := make(chan error, 2) + go func() { failed <- grpcServer.Serve(listener) }() + if o.statusListen != "" { + go func() { + l, e := (&net.ListenConfig{}).Listen(ctx, "tcp", o.statusListen) + if e != nil { + failed <- e + return + } + failed <- statusServer.Serve(tls.NewListener(l, statusServer.TLSConfig)) + }() + } + log.Printf("xtcp2 controller listening on %s; human review required", o.listen) + select { + case <-ctx.Done(): + case e = <-failed: + cancel() + } + shutdown, done := context.WithTimeout(context.Background(), 5*time.Second) + defer done() + if serr := statusServer.Shutdown(shutdown); serr != nil { + log.Printf("status listener shutdown: %v", serr) + } + stopped := make(chan struct{}) + go func() { grpcServer.GracefulStop(); close(stopped) }() + select { + case <-stopped: + case <-shutdown.Done(): + grpcServer.Stop() + } + wg.Wait() + if e == grpc.ErrServerStopped || e == http.ErrServerClosed { + return nil + } + return e +} + +// housekeep runs maintenance every minute, and discovery on its own +// cadence, under the housekeeping lease until ctx is done. +func housekeep(ctx context.Context, s *controller.Server, source evidence.Source, warehouse *chwarehouse.Client, templates []controller.DiscoveryTemplate, interval time.Duration) { + tick := time.NewTicker(time.Minute) + defer tick.Stop() + nextDiscovery := time.Now() + leader := false + for { + // Discovery is due on this replica's own cadence whether or not + // it holds the lease, so a follower that becomes leader does not + // run a backlog of passes. + var due evidence.Warehouse + if warehouse != nil && !time.Now().Before(nextDiscovery) { + due = warehouse + // Keep the cadence independent of query duration; otherwise a + // one-minute interval can accidentally skip every other tick. + for !nextDiscovery.After(time.Now()) { + nextDiscovery = nextDiscovery.Add(interval) + } + } + held, e := s.Housekeep(ctx, source, due, templates) + if e != nil { + log.Printf("controller housekeeping: %v", e) + } + // A failed Lease call reports held=false with an error; that is + // not a follower, so the leader state is kept until it answers. + if (e == nil || held) && held != leader { + leader = held + if held { + log.Print("controller housekeeping: this replica holds the lease") + } else { + log.Print("controller housekeeping: another replica holds the lease; skipping passes") + } + } + select { + case <-ctx.Done(): + return + case <-tick.C: + } + } +} diff --git a/cmd/xtcp2-controllerctl/main.go b/cmd/xtcp2-controllerctl/main.go new file mode 100644 index 000000000..5a2615442 --- /dev/null +++ b/cmd/xtcp2-controllerctl/main.go @@ -0,0 +1,92 @@ +package main + +import ( + "context" + "flag" + "fmt" + "log" + "os" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +func main() { + if e := run(); e != nil { + log.Print(e) + os.Exit(1) + } +} +func run() error { + target := flag.String("controller", "localhost:9443", "controller address") + name := flag.String("serverName", "", "TLS server name") + cert := flag.String("cert", "", "operator certificate") + key := flag.String("key", "", "operator key") + ca := flag.String("ca", "", "server CA") + method := flag.String("method", "inspect", "propose, analyze, review, control, inspect") + file := flag.String("file", "", "protobuf-text request file (empty InspectRequest if omitted)") + flag.Parse() + tls, e := identity.TLSConfig(*cert, *key, *ca, *name, false) + if e != nil { + return e + } + conn, e := grpc.NewClient(*target, grpc.WithTransportCredentials(credentials.NewTLS(tls)), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(treatment.MaxStateBytes))) + if e != nil { + return e + } + defer func() { + if cerr := conn.Close(); cerr != nil { + log.Printf("close: %v", cerr) + } + }() + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + client := pb.NewOperatorServiceClient(conn) + var req, response proto.Message + switch *method { + case "propose": + req = new(pb.ProposeRequest) + case "review": + req = new(pb.ReviewRequest) + case "analyze": + req = new(pb.AnalyzeRequest) + case "control": + req = new(pb.ControlRequest) + case "inspect": + req = new(pb.InspectRequest) + default: + return fmt.Errorf("unknown method %q", *method) + } + if *file != "" { + b, e := os.ReadFile(*file) + if e != nil { + return e + } + if e = prototext.Unmarshal(b, req); e != nil { + return e + } + } + switch r := req.(type) { + case *pb.ProposeRequest: + response, e = client.Propose(ctx, r) + case *pb.ReviewRequest: + response, e = client.Review(ctx, r) + case *pb.AnalyzeRequest: + response, e = client.Analyze(ctx, r) + case *pb.ControlRequest: + response, e = client.Control(ctx, r) + case *pb.InspectRequest: + response, e = client.Inspect(ctx, r) + } + if e != nil { + return e + } + fmt.Print(prototext.Format(response)) + return nil +} diff --git a/cmd/xtcp2-treatment-agent/main.go b/cmd/xtcp2-treatment-agent/main.go new file mode 100644 index 000000000..d28debbb0 --- /dev/null +++ b/cmd/xtcp2-treatment-agent/main.go @@ -0,0 +1,75 @@ +// xtcp2-treatment-agent runs the TCP route treatment agent as its own +// process: the mTLS check-in loop, desired-state watch, journal and kernel +// route reconciliation, beside an xtcp2 daemon that reads the journal with +// -treatmentAttribution. It is the same library cmd/xtcp2 embeds when built +// with the treatment tag; the watchdog (xtcp2-treatmentctl -mode=watchdog) +// stays a separate process in both arrangements. +// +// SIGHUP checks in and reconciles immediately; SIGINT/SIGTERM stop the agent +// and leave installed routes for the next start or the watchdog to govern. +package main + +import ( + "context" + "flag" + "log" + "os" + "os/signal" + "syscall" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/agent" +) + +var ( + version = "dev" + commit = "none" + date = "unknown" +) + +func main() { + if err := run(); err != nil { + log.Print(err) + os.Exit(1) + } +} + +func run() (err error) { + config := flag.String("config", "/etc/xtcp2/controller-agent.json", "agent configuration (shared with xtcp2-treatmentctl)") + showVersion := flag.Bool("version", false, "print version and exit") + flag.Parse() + if *showVersion { + log.Printf("xtcp2-treatment-agent %s (%s, %s)", version, commit, date) + return nil + } + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer cancel() + c, err := agent.LoadConfig(*config) + if err != nil { + return err + } + a, err := agent.New(ctx, c) + if err != nil { + return err + } + defer func() { + if cerr := a.Close(); cerr != nil && err == nil { + err = cerr + } + }() + hup := make(chan os.Signal, 1) + signal.Notify(hup, syscall.SIGHUP) + defer signal.Stop(hup) + go func() { + for { + select { + case <-ctx.Done(): + return + case <-hup: + a.Wake() + } + } + }() + log.Printf("xtcp2-treatment-agent %s: %s journal=%s", version, c, c.Directory) + a.Run(ctx) + return nil +} diff --git a/cmd/xtcp2-treatmentctl/main.go b/cmd/xtcp2-treatmentctl/main.go new file mode 100644 index 000000000..845b6bb9b --- /dev/null +++ b/cmd/xtcp2-treatmentctl/main.go @@ -0,0 +1,90 @@ +// xtcp2-treatmentctl is the local, filesystem-permission-protected emergency +// interface and independent lease watchdog. It never needs a controller RPC, +// a certificate or DNS: it builds on pkg/treatment/local and +// pkg/treatment/reconcile only, and the import-boundary test keeps it that way. +package main + +import ( + "context" + "flag" + "fmt" + "log" + "os" + "os/signal" + "path/filepath" + "syscall" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/local" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" +) + +func main() { + if err := run(); err != nil { + log.Print(err) + os.Exit(1) + } +} +func run() error { + config := flag.String("config", "/etc/xtcp2/controller-agent.json", "agent configuration") + mode := flag.String("mode", "status", "status, suspend, resume, reconcile, or watchdog") + reason := flag.String("reason", "", "required for suspend/resume") + flag.Parse() + ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer cancel() + c, e := local.LoadConfig(*config) + if e != nil { + return e + } + h, e := local.New(c, nil) + if e != nil { + return e + } + switch *mode { + case "status": + // Read without the lock: the snapshot is replaced atomically and + // status must answer while a reconcile pass holds the journal. + b, e := os.ReadFile(filepath.Join(c.Directory, reconcile.SnapshotFile)) + if e != nil { + return e + } + _, e = os.Stdout.Write(b) + return e + case "suspend", "resume": + // Waits for a reconcile pass in progress; a watchdog pass is bounded + // at 25 s, so a longer wait means the journal is wedged. + hold, cancelHold := context.WithTimeout(ctx, 30*time.Second) + defer cancelHold() + if e = h.Reconciler.SuspendLocal(hold, *mode == "suspend", *reason); e != nil { + return e + } + case "reconcile": + case "watchdog": + t := time.NewTicker(30 * time.Second) + defer t.Stop() + for { + pass, cancelPass := context.WithTimeout(ctx, 25*time.Second) + _, e = h.Reconciler.Run(pass, nil, reconcile.ModeExpiryOnly) + cancelPass() + if e != nil { + log.Printf("watchdog: %v", e) + } + select { + case <-ctx.Done(): + return nil + case <-t.C: + } + } + default: + return fmt.Errorf("unknown mode %q", *mode) + } + s, e := h.Reconciler.Run(ctx, nil, reconcile.ModeFull) + if s != nil { + if b, err := reconcile.MarshalText(s); err == nil { + if _, werr := os.Stdout.Write(b); werr != nil && e == nil { + e = werr + } + } + } + return e +} diff --git a/cmd/xtcp2/testdata/defineflags-golden.txt b/cmd/xtcp2/testdata/defineflags-golden.txt index 589ae7241..235a9e412 100644 --- a/cmd/xtcp2/testdata/defineflags-golden.txt +++ b/cmd/xtcp2/testdata/defineflags-golden.txt @@ -121,6 +121,8 @@ s3UploadMaxAttempts 10 s3parquet: max upload attempts (original + retries) befor tag label applied to the protobuf timeout 5s Poll timeout per name space topic xtcp Kafka or NSQ topic +treatmentAttribution optional journal directory of a standalone xtcp2-treatment-agent (its config's directory, default /var/lib/xtcp2/routes); this daemon only reads the snapshot and stamps treatment provenance onto records. Mutually exclusive with -treatmentConfig +treatmentConfig optional controller agent JSON config, running the treatment agent inside this daemon; needs a build with the treatment tag; route application requires enable_apply. Mutually exclusive with -treatmentAttribution uplinkCount 2 number of uplink slots to populate for LLDP/NIC enrichment (hosts are typically dual-homed = 2; max 2). Falls back to UPLINK_COUNT env. uplinkInterfaces comma-separated explicit uplink interface names (e.g. "eth0,eth1") overriding default-route auto-detection for -enrichLldp/-enrichNic. Falls back to UPLINK_INTERFACES env. v false show version diff --git a/cmd/xtcp2/treatments.go b/cmd/xtcp2/treatments.go new file mode 100644 index 000000000..0618020cd --- /dev/null +++ b/cmd/xtcp2/treatments.go @@ -0,0 +1,125 @@ +package main + +import ( + "context" + "errors" + "fmt" + "sync" + "sync/atomic" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + "github.com/randomizedcoder/xtcp2/pkg/treatment/attribution" +) + +// The treatment feature reaches the daemon in one of two ways, selected by +// flag and never both: +// +// - -treatmentAttribution : always compiled. A standalone +// xtcp2-treatment-agent owns the journal in ; the daemon only reads +// the snapshot and stamps provenance onto records. No gRPC client, no +// TLS material, no kernel writes in this process. +// - -treatmentConfig : compiled only with the `treatment` build tag +// (treatments_embedded.go), which registers embeddedTreatmentAgent. The +// agent runs in-process and feeds the same stamper. +// +// Asking an untagged binary for -treatmentConfig is fatal, like asking a slim +// build for an enricher it lacks: a missing build tag is a property of the +// artifact, identical on every host, and must not degrade silently. +// +// Location has one rule in both modes. The agent's location is bound to its +// certificate (spiffe://xtcp/agent//) and evidence queries +// filter by it. When this daemon has no -location/LOCATION of its own, its +// records take the agent's, logged once. When it has one and the agent's +// differs, the embedded agent refuses to start, naming both, and the +// attribution watcher keeps the daemon's label and logs the disagreement +// once (pkg/treatment/attribution). Nothing rewrites a label silently. + +// treatmentFeeder is whichever mode is running. +type treatmentFeeder struct { + stamp func(*flat.XtcpFlatRecord) + wake func() +} + +var activeTreatments atomic.Pointer[treatmentFeeder] + +// embeddedTreatmentAgent is nil unless built with -tags treatment. location +// is the daemon's own, after -location and LOCATION, empty when it has none. +var embeddedTreatmentAgent func(ctx context.Context, path, location string) (*treatmentFeeder, func(), error) + +var errTreatmentNotCompiled = errors.New("-treatmentConfig requested but the treatment agent is not compiled into this binary; rebuild with '-tags treatment' (or use a full `xtcp2` Nix attribute), or run xtcp2-treatment-agent beside this daemon and point it at the journal with -treatmentAttribution") + +// checkTreatmentFlags rejects the combinations that are configuration +// errors regardless of the controller's availability. +func checkTreatmentFlags(configPath, attributionDir string) error { + if configPath != "" && attributionDir != "" { + return errors.New("-treatmentConfig and -treatmentAttribution are mutually exclusive: either embed the agent or read a standalone agent's journal") + } + if configPath != "" && embeddedTreatmentAgent == nil { + return errTreatmentNotCompiled + } + return nil +} + +// checkTreatmentLocation applies the location rule to the embedded agent: +// an empty daemon location adopts the agent's; a set one must equal it. +func checkTreatmentLocation(daemon, agent string) error { + if daemon != "" && daemon != agent { + return fmt.Errorf("this daemon's -location/LOCATION is %q but the treatment agent's certificate-bound location is %q; set them equal or drop -location so records take the agent's", daemon, agent) + } + return nil +} + +// treatmentStamper is the hook installed on the collector, nil when no mode +// is active. +func treatmentStamper() func(*flat.XtcpFlatRecord) { + if f := activeTreatments.Load(); f != nil { + return f.stamp + } + return nil +} + +// reconcileTreatments is the SIGHUP action: check in now, or re-read the +// journal now. +func reconcileTreatments() { + if f := activeTreatments.Load(); f != nil { + f.wake() + } +} + +// startTreatments starts the selected mode and returns its stop function. +// Errors from here are runtime conditions (unreadable config, bad journal +// directory, controller unreachable) and must not stop socket telemetry. +func startTreatments(parent context.Context, configPath, attributionDir, location string) (func(), error) { + if err := checkTreatmentFlags(configPath, attributionDir); err != nil { + return nil, err + } + switch { + case configPath != "": + ctx, cancel := context.WithCancel(parent) + f, stop, err := embeddedTreatmentAgent(ctx, configPath, location) + if err != nil { + cancel() + return nil, err + } + activeTreatments.Store(f) + return func() { cancel(); stop(); activeTreatments.CompareAndSwap(f, nil) }, nil + case attributionDir != "": + return startAttribution(parent, attributionDir, location) + } + return func() {}, nil +} + +func startAttribution(parent context.Context, dir, location string) (func(), error) { + var stamper attribution.Stamper + w, err := attribution.NewWatcher(attribution.WatchConfig{Dir: dir, Location: location}, &stamper) + if err != nil { + return nil, fmt.Errorf("treatment attribution: %w", err) + } + ctx, cancel := context.WithCancel(parent) + f := &treatmentFeeder{stamp: stamper.Stamp, wake: w.Wake} + activeTreatments.Store(f) + var wg sync.WaitGroup + wg.Add(1) + go func() { defer wg.Done(); w.Run(ctx) }() + return func() { cancel(); wg.Wait(); activeTreatments.CompareAndSwap(f, nil) }, nil +} diff --git a/cmd/xtcp2/treatments_embedded.go b/cmd/xtcp2/treatments_embedded.go new file mode 100644 index 000000000..8e9b31901 --- /dev/null +++ b/cmd/xtcp2/treatments_embedded.go @@ -0,0 +1,41 @@ +//go:build treatment + +package main + +import ( + "context" + "log" + "sync" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/agent" +) + +// Built with -tags treatment: the controller agent runs inside the daemon +// and stamps records in-process. This file is the only place cmd/xtcp2 +// imports pkg/treatment/agent, so an untagged build links neither the gRPC +// client nor the TLS identity code. +func init() { embeddedTreatmentAgent = startEmbeddedTreatmentAgent } + +func startEmbeddedTreatmentAgent(ctx context.Context, path, location string) (*treatmentFeeder, func(), error) { + c, err := agent.LoadConfig(path) + if err != nil { + return nil, nil, err + } + // Before any credential is read: a label disagreement is a deployment + // error, not a runtime one, and the message should be the first thing + // in the log. + if err = checkTreatmentLocation(location, c.Location); err != nil { + return nil, nil, err + } + if location == "" { + log.Printf("treatment agent: this daemon has no -location/LOCATION; records take the agent's %q", c.Location) + } + a, err := agent.New(ctx, c) + if err != nil { + return nil, nil, err + } + var wg sync.WaitGroup + wg.Add(1) + go func() { defer wg.Done(); a.Run(ctx) }() + return &treatmentFeeder{stamp: a.Stamp, wake: a.Wake}, func() { wg.Wait(); a.Close() }, nil +} diff --git a/cmd/xtcp2/treatments_embedded_test.go b/cmd/xtcp2/treatments_embedded_test.go new file mode 100644 index 000000000..55c70ab73 --- /dev/null +++ b/cmd/xtcp2/treatments_embedded_test.go @@ -0,0 +1,63 @@ +//go:build treatment + +package main + +import ( + "context" + "os" + "path/filepath" + "strings" + "testing" +) + +// With the tag the embedded agent is registered and -treatmentConfig is a +// runtime path: an unreadable config is an error, not a fatal build mismatch. +func TestEmbeddedTreatmentAgentRegistered(t *testing.T) { + if embeddedTreatmentAgent == nil { + t.Fatal("treatment tag did not register the embedded agent") + } + if err := checkTreatmentFlags("/etc/xtcp2/controller-agent.json", ""); err != nil { + t.Fatalf("tagged build refused -treatmentConfig: %v", err) + } + path := filepath.Join(t.TempDir(), "agent.json") + if err := os.WriteFile(path, []byte(`{"agent_id":"host","location":"dc","controller":"127.0.0.1:1","certificate":"/nonexistent.crt","private_key":"/nonexistent.key","ca":"/nonexistent-ca.crt"}`), 0600); err != nil { + t.Fatal(err) + } + stop, err := startTreatments(context.Background(), path, "", "dc") + if err == nil || stop != nil || !strings.Contains(err.Error(), "nonexistent") { + t.Fatalf("missing credentials must fail at start: %v", err) + } + if activeTreatments.Load() != nil { + t.Fatal("failed start left a feeder active") + } +} + +// The embedded agent's location rule runs before any credential is read. +func TestEmbeddedTreatmentAgentLocation(t *testing.T) { + path := filepath.Join(t.TempDir(), "agent.json") + if err := os.WriteFile(path, []byte(`{"agent_id":"host","location":"dc1","controller":"127.0.0.1:1","certificate":"/nonexistent.crt","private_key":"/nonexistent.key","ca":"/nonexistent-ca.crt"}`), 0600); err != nil { + t.Fatal(err) + } + for _, tc := range []struct { + name, description string + daemon string + expected string + }{ + {"unset", "positive: a daemon without a location adopts the agent's and proceeds to credentials", "", "nonexistent"}, + {"equal", "positive: an equal location proceeds to credentials", "dc1", "nonexistent"}, + {"differs", "negative: a different location is refused before any credential is read", "dc2", `"dc2"`}, + } { + t.Run(tc.name, func(t *testing.T) { + stop, err := startTreatments(context.Background(), path, "", tc.daemon) + if err == nil || stop != nil || !strings.Contains(err.Error(), tc.expected) { + t.Fatalf("%s: err=%v, want %q", tc.description, err, tc.expected) + } + if tc.name == "differs" && strings.Contains(err.Error(), "nonexistent") { + t.Fatalf("%s: credentials were read before the location check", tc.description) + } + if activeTreatments.Load() != nil { + t.Fatal("failed start left a feeder active") + } + }) + } +} diff --git a/cmd/xtcp2/treatments_test.go b/cmd/xtcp2/treatments_test.go new file mode 100644 index 000000000..d2c2a52d8 --- /dev/null +++ b/cmd/xtcp2/treatments_test.go @@ -0,0 +1,200 @@ +package main + +import ( + "context" + "errors" + "net/netip" + "os" + "strings" + "syscall" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/gen/go/xtcp_config" + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" + "golang.org/x/sys/unix" +) + +func TestSIGHUPReconcilesWithoutRebaselineOrShutdown(t *testing.T) { + sigs := make(chan os.Signal, 3) + complete := make(chan struct{}, 1) + complete <- struct{}{} + reconciled := make(chan struct{}, 1) + rebaselined := make(chan struct{}, 1) + done := make(chan struct{}) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go func() { + awaitSignalAndShutdown(sigs, cancel, complete, time.Second, false, func() { rebaselined <- struct{}{} }, func() { reconciled <- struct{}{} }) + close(done) + }() + sigs <- syscall.SIGHUP + select { + case <-reconciled: + case <-time.After(time.Second): + t.Fatal("SIGHUP did not reconcile") + } + select { + case <-ctx.Done(): + t.Fatal("SIGHUP shut down daemon") + case <-rebaselined: + t.Fatal("SIGHUP changed link baseline") + default: + } + sigs <- syscall.SIGUSR1 + select { + case <-rebaselined: + case <-time.After(time.Second): + t.Fatal("SIGUSR1 regression") + } + sigs <- syscall.SIGTERM + select { + case <-done: + case <-time.After(time.Second): + t.Fatal("SIGTERM did not stop") + } +} + +func TestCheckTreatmentFlags(t *testing.T) { + saved := embeddedTreatmentAgent + t.Cleanup(func() { embeddedTreatmentAgent = saved }) + for _, tc := range []struct { + name, description string + config, dir string + compiled bool + expected string + }{ + {"none", "positive: neither flag is the observation-only daemon", "", "", false, ""}, + {"attribution", "positive: the journal reader is always available", "", "/var/lib/xtcp2/routes", false, ""}, + {"embedded-tagged", "positive: -treatmentConfig works when the agent is compiled in", "/etc/xtcp2/a.json", "", true, ""}, + {"embedded-untagged", "negative: -treatmentConfig without the build tag is a fatal artifact mismatch", "/etc/xtcp2/a.json", "", false, "not compiled into this binary"}, + {"both", "negative: both modes at once is a configuration error even when tagged", "/etc/xtcp2/a.json", "/var/lib/xtcp2/routes", true, "mutually exclusive"}, + {"both-untagged", "corner: mutual exclusion is reported before the missing tag", "/etc/xtcp2/a.json", "/var/lib/xtcp2/routes", false, "mutually exclusive"}, + } { + t.Run(tc.name, func(t *testing.T) { + embeddedTreatmentAgent = nil + if tc.compiled { + embeddedTreatmentAgent = func(context.Context, string, string) (*treatmentFeeder, func(), error) { return nil, nil, nil } + } + err := checkTreatmentFlags(tc.config, tc.dir) + if tc.expected == "" { + if err != nil { + t.Fatalf("%s: %v", tc.description, err) + } + return + } + if err == nil || !strings.Contains(err.Error(), tc.expected) { + t.Fatalf("%s: expected %q, got %v", tc.description, tc.expected, err) + } + if tc.name == "embedded-untagged" && !errors.Is(err, errTreatmentNotCompiled) { + t.Fatal("missing tag must be the sentinel error so main can make it fatal") + } + }) + } +} + +// The location rule for the embedded agent, with the daemon's label resolved +// the way main resolves it: -location first, LOCATION from the environment +// over it. The standalone counterpart (keep the daemon's label, adopt when +// there is none) is pkg/treatment/attribution's TestWatcherRefresh rows. +func TestCheckTreatmentLocation(t *testing.T) { + for _, tc := range []struct { + name, description string + flag, env string + agent string + expected []string // substrings of the error; empty means start + }{ + {"flag-unset", "positive: no -location and no LOCATION adopts the agent's certificate-bound location", "", "", "dc1", nil}, + {"flag-equal", "positive: -location equal to the agent's starts", "dc1", "", "dc1", nil}, + {"env-equal", "positive: LOCATION equal to the agent's starts", "", "dc1", "dc1", nil}, + {"flag-differs", "negative: -location differing from the agent's refuses, naming both", "dc2", "", "dc1", []string{`"dc2"`, `"dc1"`}}, + {"env-differs", "negative: LOCATION differing from the agent's refuses the same way; the flag alone is not what counts", "", "dc2", "dc1", []string{`"dc2"`, `"dc1"`}}, + {"env-over-flag", "corner: LOCATION overrides -location, as it does for every record, so the override is what is compared", "dc1", "dc2", "dc1", []string{`"dc2"`}}, + {"case", "boundary: labels are compared exactly; DC1 is not dc1", "DC1", "", "dc1", []string{`"DC1"`, `"dc1"`}}, + } { + t.Run(tc.name, func(t *testing.T) { + if tc.env != "" { + t.Setenv("LOCATION", tc.env) + } else { + os.Unsetenv("LOCATION") + } + c := &xtcp_config.XtcpConfig{Location: tc.flag} + envOverrideLabeling(c, 0) + err := checkTreatmentLocation(c.Location, tc.agent) + if len(tc.expected) == 0 { + if err != nil { + t.Fatalf("%s: %v", tc.description, err) + } + return + } + if err == nil { + t.Fatalf("%s: expected an error", tc.description) + } + for _, want := range tc.expected { + if !strings.Contains(err.Error(), want) { + t.Fatalf("%s: error %q does not name %s", tc.description, err, want) + } + } + }) + } +} + +// Attribution mode installs a stamper fed from the journal directory and +// SIGHUP re-reads it; stopping removes the feeder. +func TestStartTreatmentsAttributionMode(t *testing.T) { + dir := t.TempDir() + now := time.Unix(1700000000, 0) + cubic := "cubic" + d := &treatment.DesiredState{AgentID: "host-1", Revision: 1, IssuedAt: now, Assignments: []treatment.Assignment{{ExperimentID: "trial-1", Generation: 1, Mode: treatment.ModeStable, Treatment: treatment.Treatment{ID: "cubic", Revision: 1, Destination: netip.MustParsePrefix("192.0.2.1/32"), Settings: treatment.TCPSettings{CongestionControl: &cubic}}}}} + write := func(revision uint64) { + d.Revision = revision + err := reconcile.Journal{Dir: dir}.WithLock(context.Background(), func(s *reconcile.State, save func() error) error { + *s = reconcile.State{AgentID: "host-1", Location: "dc1", BootID: "boot-1", Desired: d, Records: []reconcile.Record{{ApplicationRecord: treatment.ApplicationRecord{Assignment: d.Assignments[0], Status: treatment.ApplyVerified, AppliedAt: now}}}} + return save() + }) + if err != nil { + t.Fatal(err) + } + } + write(1) + if treatmentStamper() != nil { + t.Fatal("stamper active before start") + } + stop, err := startTreatments(context.Background(), "", dir, "dc1") + if err != nil { + t.Fatal(err) + } + stamp := treatmentStamper() + if stamp == nil { + t.Fatal("attribution mode installed no stamper") + } + var st unix.Stat_t + if err := unix.Stat("/proc/self/ns/net", &st); err != nil { + t.Skip("cannot resolve own network namespace") + } + r := &flat.XtcpFlatRecord{Location: "dc1", NetnsInode: st.Ino, InetDiagMsgFamily: 2, InetDiagMsgSocketDestination: []byte{192, 0, 2, 1}, InetDiagCong: "cubic"} + deadline := time.Now().Add(5 * time.Second) + for stamp(r); r.TreatmentStateRevision != 1 && time.Now().Before(deadline); stamp(r) { + time.Sleep(10 * time.Millisecond) + } + if r.TreatmentStateRevision != 1 || r.AgentId != "host-1" || r.TreatmentAssignmentId != "trial-1" || !r.TreatmentAlgorithmExposed { + t.Fatalf("journal not attributed: %+v", r) + } + write(2) + reconcileTreatments() + for stamp(r); r.TreatmentStateRevision != 2 && time.Now().Before(deadline); stamp(r) { + time.Sleep(10 * time.Millisecond) + } + if r.TreatmentStateRevision != 2 { + t.Fatal("SIGHUP did not re-read the journal") + } + stop() + if treatmentStamper() != nil { + t.Fatal("stop left the feeder active") + } + if _, err := startTreatments(context.Background(), "", "", "dc1"); err != nil { + t.Fatal("no-mode start must succeed") + } +} diff --git a/cmd/xtcp2/xtcp2.go b/cmd/xtcp2/xtcp2.go index 4d56205ed..53edfe198 100644 --- a/cmd/xtcp2/xtcp2.go +++ b/cmd/xtcp2/xtcp2.go @@ -253,32 +253,34 @@ var ( // short and lets the per-section helpers (printFlags, buildConfig, // startProfile) take a single argument instead of 30 positional ones. type mainFlags struct { - nltimeout *uint64 - pollFrequency *time.Duration - pollTimeout *time.Duration - maxLoops *uint64 - netlinkers *uint - nlmsgSeq *uint - packetSize *uint64 - packetSizeMply *uint - writeFiles *uint - capturePath *string - modulus *uint64 - marshal *string - columns *string - envelopeFlushBytes *uint - envelopeFlushRows *uint - kafkaCompression *string - s3Endpoint *string - s3Bucket *string - s3Prefix *string - s3AccessKey *string - s3SecretKey *string - s3Region *string - s3SkipBucketProbe *bool - s3AllowInsecure *bool - s3CAFile *string - s3ParquetFlushBytes *uint + treatmentConfig *string + treatmentAttribution *string + nltimeout *uint64 + pollFrequency *time.Duration + pollTimeout *time.Duration + maxLoops *uint64 + netlinkers *uint + nlmsgSeq *uint + packetSize *uint64 + packetSizeMply *uint + writeFiles *uint + capturePath *string + modulus *uint64 + marshal *string + columns *string + envelopeFlushBytes *uint + envelopeFlushRows *uint + kafkaCompression *string + s3Endpoint *string + s3Bucket *string + s3Prefix *string + s3AccessKey *string + s3SecretKey *string + s3Region *string + s3SkipBucketProbe *bool + s3AllowInsecure *bool + s3CAFile *string + s3ParquetFlushBytes *uint pollJitterPct *uint s3FlushInterval *time.Duration @@ -444,6 +446,8 @@ func defaultDest() string { // of all 92 are pinned by cmd/xtcp2/testdata/defineflags-golden.txt. func defineFlags() *mainFlags { f := &mainFlags{} + f.treatmentConfig = flag.String("treatmentConfig", "", "optional controller agent JSON config, running the treatment agent inside this daemon; needs a build with the treatment tag; route application requires enable_apply. Mutually exclusive with -treatmentAttribution") + f.treatmentAttribution = flag.String("treatmentAttribution", "", "optional journal directory of a standalone xtcp2-treatment-agent (its config's directory, default /var/lib/xtcp2/routes); this daemon only reads the snapshot and stamps treatment provenance onto records. Mutually exclusive with -treatmentConfig") f.nltimeout = flag.Uint64("nltimeout", nltimeoutCst, "Netlink socket timeout in milliseconds. Zero(0) for no timeout") f.pollFrequency = flag.Duration("frequency", pollFrequencyCst, "Poll frequency") f.pollTimeout = flag.Duration("timeout", pollTimeoutCst, "Poll timeout per name space") @@ -1098,7 +1102,7 @@ func runMain(ctx context.Context) int { defer cancel() complete := make(chan struct{}, signalChannelSizeCst) - initSignalHandler(cancel, complete, linkMonitorHTTP.rebaseline) + initSignalHandler(cancel, complete, linkMonitorHTTP.rebaseline, reconcileTreatments) f := defineFlags() flag.Parse() @@ -1128,6 +1132,12 @@ func runMain(ctx context.Context) int { fmt.Fprintln(os.Stderr, "xtcp2: config validation failed:", err) return exitUsage } + if err := checkTreatmentFlags(*f.treatmentConfig, *f.treatmentAttribution); err != nil { + // A build without the agent, or both modes at once, is a property of + // the deployment that is identical on every host: fail loudly. + fmt.Fprintln(os.Stderr, "xtcp2:", err) + return exitUsage + } specs, warnings, err := listeners.Resolve(c, readSecretFile) for _, w := range warnings { log.Printf("WARNING: %s", w) @@ -1176,6 +1186,14 @@ func runMain(ctx context.Context) int { return exitCodeFor(err) } + // c.Location, not the flag: LOCATION from the environment counts too. + stopTreatments, err := startTreatments(runCtx, *f.treatmentConfig, *f.treatmentAttribution, c.Location) + if err != nil { + // Controller availability/configuration must not stop socket telemetry. + log.Printf("treatment agent unavailable: %v", err) + } else { + defer stopTreatments() + } daemonRunner(runCtx, cancel, c, grpcLns) closeGRPCListeners(grpcLns) // The signal handler exits once complete is sent, so drain first. @@ -1195,6 +1213,9 @@ func runMain(ctx context.Context) int { // and run RunWithPoller until ctx cancels the WG. func runDaemonDefault(ctx context.Context, cancel context.CancelFunc, c *xtcp_config.XtcpConfig, grpcLns []xtcp.GRPCListener) { x := xtcp.NewXTCP(ctx, cancel, c) + if stamp := treatmentStamper(); stamp != nil { + x.SetTreatmentStamper(stamp) + } x.SetGRPCListeners(grpcLns) detach, err := linkMonitorHTTP.attach(x) if err != nil { @@ -1338,15 +1359,15 @@ func envWithoutKey(env []string, key string) []string { // goroutine, so a SIGTERM sent while flags are still being parsed takes the // graceful path instead of Go's default, which exits at once. (Go drops a // SIGUSR1 that arrives before any Notify; it never kills the process.) -func initSignalHandler(cancel context.CancelFunc, complete <-chan struct{}, rebaseline func()) { +func initSignalHandler(cancel context.CancelFunc, complete <-chan struct{}, rebaseline func(), reconcile ...func()) { c := notifySignals() - go awaitSignalAndShutdown(c, cancel, complete, cancelSleepTimeCst, true, rebaseline) + go awaitSignalAndShutdown(c, cancel, complete, cancelSleepTimeCst, true, rebaseline, reconcile...) } // notifySignals routes SIGINT, SIGTERM and SIGUSR1 to the returned channel. func notifySignals() chan os.Signal { c := make(chan os.Signal, signalChannelSizeCst) - signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGUSR1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGHUP) return c } @@ -1363,12 +1384,20 @@ func awaitSignalAndShutdown( timeout time.Duration, doExit bool, rebaseline func(), + reconcile ...func(), ) { // SIGUSR1 never shuts down; a nil rebaseline ignores it. - for sig := <-sigs; sig == syscall.SIGUSR1; sig = <-sigs { - if rebaseline != nil { + for sig := <-sigs; sig == syscall.SIGUSR1 || sig == syscall.SIGHUP; sig = <-sigs { + if sig == syscall.SIGUSR1 && rebaseline != nil { rebaseline() } + if sig == syscall.SIGHUP { + for _, fn := range reconcile { + if fn != nil { + fn() + } + } + } } log.Printf("Signal caught, closing application") cancel() diff --git a/cmd/xtcp2/xtcp2_flags_helpers_test.go b/cmd/xtcp2/xtcp2_flags_helpers_test.go index a33f39ccd..71c129f4f 100644 --- a/cmd/xtcp2/xtcp2_flags_helpers_test.go +++ b/cmd/xtcp2/xtcp2_flags_helpers_test.go @@ -89,7 +89,7 @@ const ( // mainFlags field must be a registered flag and every registered flag must // have a field. A flag added without a field, or a field that stops being // registered, is the drift this file exists to notice. - mainFlagsFieldCountCst = 128 + mainFlagsFieldCountCst = 130 // + treatmentConfig (embedded agent) and treatmentAttribution (journal reader) printFlagsGoldenCst = "testdata/printflags-golden.txt" defineFlagsGoldenCst = "testdata/defineflags-golden.txt" @@ -155,32 +155,34 @@ func populatedMainFlags() *mainFlags { ms := func(v int) *time.Duration { d := time.Duration(v) * time.Millisecond; return &d } return &mainFlags{ - nltimeout: u64(101), - pollFrequency: ms(102), - pollTimeout: ms(103), - maxLoops: u64(104), - netlinkers: u(105), - nlmsgSeq: u(106), - packetSize: u64(107), - packetSizeMply: u(108), - writeFiles: u(109), - capturePath: s("capturePath-v"), - modulus: u64(110), - marshal: s("marshal-v"), - columns: s("columns-v"), - envelopeFlushBytes: u(111), - envelopeFlushRows: u(112), - kafkaCompression: s("kafkaCompression-v"), - s3Endpoint: s("s3Endpoint-v"), - s3Bucket: s("s3Bucket-v"), - s3Prefix: s("s3Prefix-v"), - s3AccessKey: s(fakeS3AccessSentinelCst), - s3SecretKey: s(fakeS3SigningSentinelCst), - s3Region: s("s3Region-v"), - s3SkipBucketProbe: b(true), - s3AllowInsecure: b(true), - s3CAFile: s("s3CAFile-v"), - s3ParquetFlushBytes: u(113), + treatmentConfig: s("/etc/xtcp2/test-treatment-config.json"), + treatmentAttribution: s("/var/lib/xtcp2/test-treatment-routes"), + nltimeout: u64(101), + pollFrequency: ms(102), + pollTimeout: ms(103), + maxLoops: u64(104), + netlinkers: u(105), + nlmsgSeq: u(106), + packetSize: u64(107), + packetSizeMply: u(108), + writeFiles: u(109), + capturePath: s("capturePath-v"), + modulus: u64(110), + marshal: s("marshal-v"), + columns: s("columns-v"), + envelopeFlushBytes: u(111), + envelopeFlushRows: u(112), + kafkaCompression: s("kafkaCompression-v"), + s3Endpoint: s("s3Endpoint-v"), + s3Bucket: s("s3Bucket-v"), + s3Prefix: s("s3Prefix-v"), + s3AccessKey: s(fakeS3AccessSentinelCst), + s3SecretKey: s(fakeS3SigningSentinelCst), + s3Region: s("s3Region-v"), + s3SkipBucketProbe: b(true), + s3AllowInsecure: b(true), + s3CAFile: s("s3CAFile-v"), + s3ParquetFlushBytes: u(113), pollJitterPct: u(114), s3FlushInterval: ms(115), diff --git a/docs/README.md b/docs/README.md index 9bcd20b99..13c8efc29 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # xtcp2 documentation -This is the documentation hub for **xtcp2**, a Linux network observability suite for TCP socket diagnostics, network-state inspection, Ethernet/RDMA port health, and enriched telemetry. If you just want the feature summary or to build and run it, start with the [top-level README](../README.md). This hub explains *how it works* and links to detailed feature documentation. +This is the documentation hub for **xtcp2**, a Linux network observability suite for TCP socket diagnostics, network-state inspection, Ethernet/RDMA port health, and enriched telemetry. xtcp2 observes by default and changes nothing on the host; the one exception is the opt-in, human-reviewed [TCP route treatment controller](tcp-controller.md), which an operator has to deploy and enable and whose actuator only ever touches routes it owns. If you just want the feature summary or to build and run it, start with the [top-level README](../README.md). This hub explains *how it works* and links to detailed feature documentation. ## Table of contents @@ -30,6 +30,14 @@ This project is a complete rewrite of the original [xtcp](https://github.com/ran Each feature has a dedicated document with its own table of contents and component breakdown. +### [Reviewed TCP route treatments](tcp-controller.md) + +An optional controller uses ClickHouse evidence and PostgreSQL state to propose +destination-specific TCP treatments, run human-reviewed canaries, and withdraw +failed trials. Agents persist protobuf-text journals and reconcile owned routes; +an independent watchdog enforces trial expiry. Route application is disabled by +default. The controller has its own mTLS listener and operator client. + ### [Netlink TCP collection](netlink/collection.md) Reads TCP socket state from the kernel via the `inet_diag` netlink interface. A registry of 13 attribute deserializers (`info`, `cong`, `meminfo`, `skmem`, `bbr`, `dctcp`, `vegas`, `tos`, `tc`, `shut`, `classid`, `cgroup`, `sockopt`) decodes each socket's attributes into a flat record; you choose which to decode with `-deserializers`. @@ -44,7 +52,7 @@ Combines `/proc//ns/net` discovery with bind-mounted namespaces under `/run ### [Ethernet/RDMA statistics and link health](../cmd/go-link-monitor/README.md) -`go-link-monitor` collects netdev, ethtool driver/PHY, RDMA, and host protocol statistics. It tracks a persisted up-link baseline, speed/duplex/width, flaps, errors, and collector health, exposing a sparse problem summary and detailed Prometheus category/interface paths. It is also [embedded in xtcp2 and enabled by default](design-linkmonitor-in-xtcp2.md). Optional read-only [goip HTTP paths](../cmd/go-link-monitor/IP-ARGV-PATHS-DESIGN.md) support remote inspection. Alerting systems consume the signals; the monitor does not perform remediation. +`go-link-monitor` collects netdev, ethtool driver/PHY, RDMA, and host protocol statistics. It tracks a persisted up-link baseline, speed/duplex/width, flaps, errors, and collector health, exposing a sparse problem summary and detailed Prometheus category/interface paths. It is also [embedded in xtcp2 and enabled by default](design-linkmonitor-in-xtcp2.md). Optional read-only [goip HTTP paths](../cmd/go-link-monitor/IP-ARGV-PATHS-DESIGN.md) support remote inspection. Alerting systems consume the signals; the monitor does not perform remediation. The only xtcp2 component that changes host state is the opt-in [treatment controller](tcp-controller.md), and it does so only after operator review. ### [Metadata enrichment](design-metadata-enrichment.md) diff --git a/docs/benchmarks/tcp-controller/after.txt b/docs/benchmarks/tcp-controller/after.txt new file mode 100644 index 000000000..76591e3ea --- /dev/null +++ b/docs/benchmarks/tcp-controller/after.txt @@ -0,0 +1,90 @@ +goos: linux +goarch: amd64 +pkg: github.com/randomizedcoder/xtcp2/pkg/treatment +cpu: AMD Ryzen Threadripper PRO 3945WX 12-Cores +BenchmarkFleetEvidence/Validate/100-24 15618 22979 ns/op 3500 B/op 3 allocs/op +BenchmarkFleetEvidence/Validate/100-24 15716 22848 ns/op 3500 B/op 3 allocs/op +BenchmarkFleetEvidence/Validate/100-24 15710 23008 ns/op 3500 B/op 3 allocs/op +BenchmarkFleetEvidence/Safety/100-24 10000 32458 ns/op 10499 B/op 9 allocs/op +BenchmarkFleetEvidence/Safety/100-24 10000 32123 ns/op 10499 B/op 9 allocs/op +BenchmarkFleetEvidence/Safety/100-24 8842 34691 ns/op 10499 B/op 9 allocs/op +BenchmarkFleetEvidence/Evaluate/100-24 6694 59860 ns/op 12998 B/op 15 allocs/op +BenchmarkFleetEvidence/Evaluate/100-24 5942 61621 ns/op 12998 B/op 15 allocs/op +BenchmarkFleetEvidence/Evaluate/100-24 6594 58432 ns/op 12998 B/op 15 allocs/op +BenchmarkFleetEvidence/Validate/1000-24 1266 274384 ns/op 54673 B/op 5 allocs/op +BenchmarkFleetEvidence/Validate/1000-24 1401 272011 ns/op 54674 B/op 5 allocs/op +BenchmarkFleetEvidence/Validate/1000-24 1309 286308 ns/op 54676 B/op 5 allocs/op +BenchmarkFleetEvidence/Safety/1000-24 1011 364178 ns/op 164025 B/op 15 allocs/op +BenchmarkFleetEvidence/Safety/1000-24 1039 357506 ns/op 164026 B/op 15 allocs/op +BenchmarkFleetEvidence/Safety/1000-24 936 354571 ns/op 164032 B/op 15 allocs/op +BenchmarkFleetEvidence/Evaluate/1000-24 859 419171 ns/op 188634 B/op 21 allocs/op +BenchmarkFleetEvidence/Evaluate/1000-24 858 415074 ns/op 188635 B/op 21 allocs/op +BenchmarkFleetEvidence/Evaluate/1000-24 885 418120 ns/op 188635 B/op 21 allocs/op +BenchmarkFleetEvidence/Validate/10000-24 132 2717192 ns/op 437242 B/op 33 allocs/op +BenchmarkFleetEvidence/Validate/10000-24 133 2698856 ns/op 437236 B/op 33 allocs/op +BenchmarkFleetEvidence/Validate/10000-24 129 2779841 ns/op 437253 B/op 33 allocs/op +BenchmarkFleetEvidence/Safety/10000-24 91 4062183 ns/op 1311648 B/op 99 allocs/op +BenchmarkFleetEvidence/Safety/10000-24 98 4027768 ns/op 1311664 B/op 99 allocs/op +BenchmarkFleetEvidence/Safety/10000-24 93 4071155 ns/op 1311647 B/op 99 allocs/op +BenchmarkFleetEvidence/Evaluate/10000-24 80 4641976 ns/op 1557547 B/op 106 allocs/op +BenchmarkFleetEvidence/Evaluate/10000-24 86 4598309 ns/op 1557578 B/op 106 allocs/op +BenchmarkFleetEvidence/Evaluate/10000-24 86 4536670 ns/op 1557578 B/op 106 allocs/op +PASS +ok github.com/randomizedcoder/xtcp2/pkg/treatment 9.859s +goos: linux +goarch: amd64 +pkg: github.com/randomizedcoder/xtcp2/pkg/treatment/agent +cpu: AMD Ryzen Threadripper PRO 3945WX 12-Cores +BenchmarkStamp/routes=1/match=true-24 10065704 35.36 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=true-24 10003551 35.31 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=true-24 9843661 35.27 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=false-24 17960965 19.45 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=false-24 18524896 19.36 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=false-24 18477922 19.34 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=true-24 10218624 34.42 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=true-24 10379076 34.12 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=true-24 10432940 34.46 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=false-24 16772404 21.60 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=false-24 16571926 21.36 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=false-24 16649026 21.53 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=true-24 10058797 36.59 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=true-24 9458271 37.78 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=true-24 9816648 36.13 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=false-24 15207280 23.66 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=false-24 14958738 23.85 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=false-24 15022704 24.07 ns/op 0 B/op 0 allocs/op +BenchmarkPublish/1-24 1435836 250.2 ns/op 360 B/op 3 allocs/op +BenchmarkPublish/1-24 1423382 252.5 ns/op 360 B/op 3 allocs/op +BenchmarkPublish/1-24 1395063 257.7 ns/op 360 B/op 3 allocs/op +BenchmarkPublish/100-24 26905 13185 ns/op 9392 B/op 12 allocs/op +BenchmarkPublish/100-24 27619 13046 ns/op 9392 B/op 12 allocs/op +BenchmarkPublish/100-24 28101 12880 ns/op 9392 B/op 12 allocs/op +BenchmarkPublish/4096-24 511 687413 ns/op 652373 B/op 49 allocs/op +BenchmarkPublish/4096-24 523 690086 ns/op 652352 B/op 49 allocs/op +BenchmarkPublish/4096-24 523 680441 ns/op 652352 B/op 49 allocs/op +PASS +ok github.com/randomizedcoder/xtcp2/pkg/treatment/agent 9.879s +goos: linux +goarch: amd64 +pkg: github.com/randomizedcoder/xtcp2/pkg/treatment/controller +cpu: AMD Ryzen Threadripper PRO 3945WX 12-Cores +BenchmarkNotificationFleet/100-24 26011 13993 ns/op 0 B/op 0 allocs/op +BenchmarkNotificationFleet/100-24 26156 13745 ns/op 0 B/op 0 allocs/op +BenchmarkNotificationFleet/100-24 25989 13681 ns/op 0 B/op 0 allocs/op +BenchmarkNotificationFleet/1000-24 2479 141174 ns/op 43 B/op 0 allocs/op +BenchmarkNotificationFleet/1000-24 2698 139311 ns/op 40 B/op 0 allocs/op +BenchmarkNotificationFleet/1000-24 2552 138808 ns/op 42 B/op 0 allocs/op +BenchmarkNotificationFleet/10000-24 248 1463026 ns/op 3522 B/op 0 allocs/op +BenchmarkNotificationFleet/10000-24 244 1508009 ns/op 3579 B/op 0 allocs/op +BenchmarkNotificationFleet/10000-24 178 2066908 ns/op 4907 B/op 0 allocs/op +PASS +ok github.com/randomizedcoder/xtcp2/pkg/treatment/controller 3.349s +goos: linux +goarch: amd64 +pkg: github.com/randomizedcoder/xtcp2/internal/goip +cpu: AMD Ryzen Threadripper PRO 3945WX 12-Cores +BenchmarkTreatmentPlanRoute-24 371434 917.5 ns/op 756 B/op 10 allocs/op +BenchmarkTreatmentPlanRoute-24 402067 1501 ns/op 756 B/op 10 allocs/op +BenchmarkTreatmentPlanRoute-24 346634 1116 ns/op 756 B/op 10 allocs/op +PASS +ok github.com/randomizedcoder/xtcp2/internal/goip 1.344s diff --git a/docs/benchmarks/tcp-controller/before.txt b/docs/benchmarks/tcp-controller/before.txt new file mode 100644 index 000000000..8f170ecf1 --- /dev/null +++ b/docs/benchmarks/tcp-controller/before.txt @@ -0,0 +1,72 @@ +goos: linux +goarch: amd64 +pkg: github.com/randomizedcoder/xtcp2/pkg/treatment +cpu: AMD Ryzen Threadripper PRO 3945WX 12-Cores +BenchmarkFleetEvidence/Validate/100-24 12350 28991 ns/op 6703 B/op 9 allocs/op +BenchmarkFleetEvidence/Validate/100-24 12961 28114 ns/op 6703 B/op 9 allocs/op +BenchmarkFleetEvidence/Validate/100-24 12174 29855 ns/op 6704 B/op 9 allocs/op +BenchmarkFleetEvidence/Safety/100-24 8277 47316 ns/op 20110 B/op 27 allocs/op +BenchmarkFleetEvidence/Safety/100-24 7406 47468 ns/op 20111 B/op 27 allocs/op +BenchmarkFleetEvidence/Safety/100-24 7742 46274 ns/op 20110 B/op 27 allocs/op +BenchmarkFleetEvidence/Evaluate/100-24 4461 74733 ns/op 25877 B/op 51 allocs/op +BenchmarkFleetEvidence/Evaluate/100-24 4440 73695 ns/op 25877 B/op 51 allocs/op +BenchmarkFleetEvidence/Evaluate/100-24 4948 80849 ns/op 25879 B/op 51 allocs/op +BenchmarkFleetEvidence/Validate/1000-24 1104 318501 ns/op 108898 B/op 20 allocs/op +BenchmarkFleetEvidence/Validate/1000-24 1156 322431 ns/op 108898 B/op 20 allocs/op +BenchmarkFleetEvidence/Validate/1000-24 1144 324561 ns/op 108896 B/op 20 allocs/op +BenchmarkFleetEvidence/Safety/1000-24 643 562375 ns/op 326712 B/op 60 allocs/op +BenchmarkFleetEvidence/Safety/1000-24 640 558050 ns/op 326706 B/op 60 allocs/op +BenchmarkFleetEvidence/Safety/1000-24 656 552844 ns/op 326704 B/op 60 allocs/op +BenchmarkFleetEvidence/Evaluate/1000-24 544 666721 ns/op 375536 B/op 102 allocs/op +BenchmarkFleetEvidence/Evaluate/1000-24 556 640359 ns/op 375537 B/op 102 allocs/op +BenchmarkFleetEvidence/Evaluate/1000-24 561 672998 ns/op 375549 B/op 102 allocs/op +BenchmarkFleetEvidence/Validate/10000-24 100 3383939 ns/op 874017 B/op 79 allocs/op +BenchmarkFleetEvidence/Validate/10000-24 100 3430797 ns/op 874017 B/op 79 allocs/op +BenchmarkFleetEvidence/Validate/10000-24 100 3399253 ns/op 874004 B/op 79 allocs/op +BenchmarkFleetEvidence/Safety/10000-24 69 5898750 ns/op 2621959 B/op 239 allocs/op +BenchmarkFleetEvidence/Safety/10000-24 67 5839557 ns/op 2621904 B/op 239 allocs/op +BenchmarkFleetEvidence/Safety/10000-24 69 6979109 ns/op 2621891 B/op 239 allocs/op +BenchmarkFleetEvidence/Evaluate/10000-24 57 7482686 ns/op 3391637 B/op 317 allocs/op +BenchmarkFleetEvidence/Evaluate/10000-24 57 7597250 ns/op 3391704 B/op 317 allocs/op +BenchmarkFleetEvidence/Evaluate/10000-24 48 7077716 ns/op 3391590 B/op 317 allocs/op +PASS +ok github.com/randomizedcoder/xtcp2/pkg/treatment 10.133s +goos: linux +goarch: amd64 +pkg: github.com/randomizedcoder/xtcp2/pkg/treatment/agent +cpu: AMD Ryzen Threadripper PRO 3945WX 12-Cores +BenchmarkStamp/routes=1/match=true-24 10195333 34.84 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=true-24 9735492 33.69 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=true-24 10685922 33.50 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=false-24 16964254 18.90 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=false-24 18726810 19.14 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=1/match=false-24 19162561 23.49 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=true-24 10103883 35.42 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=true-24 10498788 33.87 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=true-24 10056416 35.61 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=false-24 16187679 21.65 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=false-24 14169679 26.08 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=100/match=false-24 13624152 22.02 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=true-24 10212040 35.09 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=true-24 10251448 34.39 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=true-24 9137064 39.17 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=false-24 15448830 22.74 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=false-24 14805097 26.18 ns/op 0 B/op 0 allocs/op +BenchmarkStamp/routes=4096/match=false-24 14845970 24.18 ns/op 0 B/op 0 allocs/op +PASS +ok github.com/randomizedcoder/xtcp2/pkg/treatment/agent 6.472s +goos: linux +goarch: amd64 +pkg: github.com/randomizedcoder/xtcp2/pkg/treatment/controller +cpu: AMD Ryzen Threadripper PRO 3945WX 12-Cores +BenchmarkNotificationFleet/100-24 26456 13532 ns/op 0 B/op 0 allocs/op +BenchmarkNotificationFleet/100-24 26252 13689 ns/op 0 B/op 0 allocs/op +BenchmarkNotificationFleet/100-24 26132 13644 ns/op 0 B/op 0 allocs/op +BenchmarkNotificationFleet/1000-24 2419 148186 ns/op 45 B/op 0 allocs/op +BenchmarkNotificationFleet/1000-24 2572 161498 ns/op 42 B/op 0 allocs/op +BenchmarkNotificationFleet/1000-24 2372 146506 ns/op 45 B/op 0 allocs/op +BenchmarkNotificationFleet/10000-24 226 1923710 ns/op 3864 B/op 0 allocs/op +BenchmarkNotificationFleet/10000-24 243 1516583 ns/op 3594 B/op 0 allocs/op +BenchmarkNotificationFleet/10000-24 190 1779397 ns/op 4597 B/op 0 allocs/op +PASS +ok github.com/randomizedcoder/xtcp2/pkg/treatment/controller 3.460s diff --git a/docs/benchmarks/tcp-controller/postgres-indexes.txt b/docs/benchmarks/tcp-controller/postgres-indexes.txt new file mode 100644 index 000000000..c05e54e6e --- /dev/null +++ b/docs/benchmarks/tcp-controller/postgres-indexes.txt @@ -0,0 +1,46 @@ +# nix build .#bench-tcp-controller-postgres-indexes +# postgres (PostgreSQL) 18.6, go version go1.27.3 linux/amd64 +=== RUN TestPostgresExperimentQueryIndexes +=== RUN TestPostgresExperimentQueryIndexes/old-destination + postgres_test.go:174: 100005 experiments: unindexed 22.274 ms, indexed 0.021 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/absent-destination + postgres_test.go:174: 100005 experiments: unindexed 21.472 ms, indexed 0.020 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/active-budget + postgres_test.go:174: 100005 experiments: unindexed 18.080 ms, indexed 0.016 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/idle-budget + postgres_test.go:174: 100005 experiments: unindexed 25.644 ms, indexed 0.020 ms (xtcp_treatment_experiments_location_status) +--- PASS: TestPostgresExperimentQueryIndexes (1.19s) + --- PASS: TestPostgresExperimentQueryIndexes/old-destination (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/absent-destination (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/active-budget (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/idle-budget (0.03s) +=== RUN TestPostgresExperimentQueryIndexes +=== RUN TestPostgresExperimentQueryIndexes/old-destination + postgres_test.go:174: 100005 experiments: unindexed 22.485 ms, indexed 0.023 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/absent-destination + postgres_test.go:174: 100005 experiments: unindexed 19.972 ms, indexed 0.019 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/active-budget + postgres_test.go:174: 100005 experiments: unindexed 18.097 ms, indexed 0.019 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/idle-budget + postgres_test.go:174: 100005 experiments: unindexed 24.627 ms, indexed 0.020 ms (xtcp_treatment_experiments_location_status) +--- PASS: TestPostgresExperimentQueryIndexes (1.18s) + --- PASS: TestPostgresExperimentQueryIndexes/old-destination (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/absent-destination (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/active-budget (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/idle-budget (0.03s) +=== RUN TestPostgresExperimentQueryIndexes +=== RUN TestPostgresExperimentQueryIndexes/old-destination + postgres_test.go:174: 100005 experiments: unindexed 20.488 ms, indexed 0.023 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/absent-destination + postgres_test.go:174: 100005 experiments: unindexed 19.139 ms, indexed 0.016 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/active-budget + postgres_test.go:174: 100005 experiments: unindexed 16.850 ms, indexed 0.016 ms (xtcp_treatment_experiments_destination) +=== RUN TestPostgresExperimentQueryIndexes/idle-budget + postgres_test.go:174: 100005 experiments: unindexed 24.134 ms, indexed 0.019 ms (xtcp_treatment_experiments_location_status) +--- PASS: TestPostgresExperimentQueryIndexes (1.20s) + --- PASS: TestPostgresExperimentQueryIndexes/old-destination (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/absent-destination (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/active-budget (0.02s) + --- PASS: TestPostgresExperimentQueryIndexes/idle-budget (0.03s) +PASS +ok github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres 3.566s diff --git a/docs/build-flavors.md b/docs/build-flavors.md index 3ffcfd95c..edc466944 100644 --- a/docs/build-flavors.md +++ b/docs/build-flavors.md @@ -259,9 +259,13 @@ The absent ones are published as `0` deliberately: a binary built without the ta | `enrich.go`, `enrich_core.go` | (none) | always | | `enrich_asn.go` | `//go:build enrich_asn` | only with `-tags enrich_asn` | | `enrich_locality.go` | `//go:build enrich_locality` | only with `-tags enrich_locality` | +| `cmd/xtcp2/treatments.go` (journal reader, `-treatmentAttribution`) | (none) | always | +| `cmd/xtcp2/treatments_embedded.go` (embedded agent, `-treatmentConfig`) | `//go:build treatment` | only with `-tags treatment` | Each tagged file calls `RegisterDestination(scheme, factory)` / `RegisterEnricher(name, factory)` from its `init()`. With the tag off the file isn't compiled, so the registry simply lacks that entry — no `!tag` stub file is needed. Both registries panic on a duplicate registration, which can only mean two files claimed the same tag. +The treatment agent follows the same shape one level up, in `cmd/xtcp2`: the untagged file registers nothing, so `-treatmentConfig` is refused with a message naming the tag and the standalone alternative, while `-treatmentAttribution` (read a standalone `xtcp2-treatment-agent`'s journal, stamp provenance) is always compiled. `mkGoBinary`'s `treatment` knob defaults to "on for the full destination set, off for the slim flavors", so `xtcp2` / `xtcp2-all` embed the agent and `xtcp2-min` & co. pair with the standalone binary. `pkg/treatment/boundaries_test.go` walks `cmd/xtcp2` both ways and asserts the untagged closure never reaches the agent, the TLS identity code or the RPC proto. See [tcp-controller.md](tcp-controller.md#agent-deployment). + The rule that makes this work is that **no tagged package's type may appear on the `XTCP` struct**: `dest` is a `Destination` interface, and the two enrichers are `asnLookuper` / `localityEnricher` interfaces declared in untagged code. A single `*ipasn.Index`-typed field would re-link parquet-go into every flavor and silently undo the whole scheme. The CLI distinguishes "unknown" from "known but not compiled in", for both: @@ -287,6 +291,7 @@ The destination case is *unavailable* — the daemon has nowhere to send records ```sh go test -tags 'enrich_asn enrich_locality' ./pkg/xtcp/ ./cmd/xtcp2/ go test -tags 'dest_s3parquet enrich_asn enrich_locality' ./pkg/xtcp/ +go test -tags treatment ./cmd/xtcp2/ ./cmd/xtcp2-treatment-agent/ # nix build .#test-focused-xtcp-treatment ``` `nix flake check` does this for you via `nix/tests/go-test-flavors.nix`, which has one target per flavor plus an `all` target. The registry and hot-path tests (`enrich_core_test.go`, `enrich_seam_test.go`) are deliberately **untagged** and derive their expectations from `EnricherCompiledIn`, so they assert correct behaviour in every flavor — including the builds that lack the code. @@ -294,9 +299,9 @@ go test -tags 'dest_s3parquet enrich_asn enrich_locality' ./pkg/xtcp/ ## Building outside Nix ```bash -# Full xtcp2 (every destination + every enricher): +# Full xtcp2 (every destination + every enricher + the embedded treatment agent): CGO_ENABLED=0 go build \ - -tags "netgo,osusergo,dest_kafka,dest_nats,dest_nsq,dest_valkey,dest_s3parquet,enrich_asn,enrich_locality" \ + -tags "netgo,osusergo,dest_kafka,dest_nats,dest_nsq,dest_valkey,dest_s3parquet,enrich_asn,enrich_locality,treatment" \ -ldflags "-s -w" -trimpath -o xtcp2 ./cmd/xtcp2 # Unix-domain-socket flavor (stdlib only, no enrichers): diff --git a/docs/examples/controller-agent.json b/docs/examples/controller-agent.json new file mode 100644 index 000000000..0a76b77a5 --- /dev/null +++ b/docs/examples/controller-agent.json @@ -0,0 +1,15 @@ +{ + "agent_id": "host-001", + "location": "dc-example", + "controller": "controller.example.net:9443", + "server_name": "controller.example.net", + "certificate": "/etc/xtcp2/agent.crt", + "private_key": "/etc/xtcp2/agent.key", + "ca": "/etc/xtcp2/controller-ca.crt", + "directory": "/var/lib/xtcp2/routes", + "enable_apply": false, + "table": 10002, + "rule_priority": 30000, + "protocol": 242, + "protected_prefixes": ["192.0.2.0/24", "2001:db8:ffff::/48"] +} diff --git a/docs/examples/controller-discovery.json b/docs/examples/controller-discovery.json new file mode 100644 index 000000000..53877fc95 --- /dev/null +++ b/docs/examples/controller-discovery.json @@ -0,0 +1,23 @@ +[ + { + "id": "nearby-cubic", + "location": "dc-example", + "congestion_control": "cubic", + "rto_min_ms": 5, + "quick_ack": true, + "initial_congestion_window": 100, + "initial_receive_window": 100, + "minimum_rtt_ms": 0, + "maximum_rtt_ms": 2, + "minimum_retransmission_ratio": 0, + "prefixes": ["10.0.0.0/8"] + }, + { + "id": "distant-loss-bbr", + "location": "dc-example", + "congestion_control": "bbr", + "minimum_rtt_ms": 150, + "maximum_rtt_ms": 2000, + "minimum_retransmission_ratio": 0.001 + } +] diff --git a/docs/examples/xtcp2-treatment-agent.service b/docs/examples/xtcp2-treatment-agent.service new file mode 100644 index 000000000..bf6983142 --- /dev/null +++ b/docs/examples/xtcp2-treatment-agent.service @@ -0,0 +1,21 @@ +[Unit] +Description=xtcp2 TCP route treatment agent (standalone) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=root +ExecStart=/usr/local/bin/xtcp2-treatment-agent -config=/etc/xtcp2/controller-agent.json +# Check in and reconcile now; the embedded agent does the same on SIGHUP. +ExecReload=/bin/kill -HUP $MAINPID +Restart=always +RestartSec=2s +StateDirectory=xtcp2 +StateDirectoryMode=0750 +AmbientCapabilities=CAP_NET_ADMIN CAP_SYS_PTRACE +CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_PTRACE +NoNewPrivileges=true + +[Install] +WantedBy=multi-user.target diff --git a/docs/examples/xtcp2-treatment-watchdog.service b/docs/examples/xtcp2-treatment-watchdog.service new file mode 100644 index 000000000..ca847fff4 --- /dev/null +++ b/docs/examples/xtcp2-treatment-watchdog.service @@ -0,0 +1,18 @@ +[Unit] +Description=xtcp2 independent TCP treatment lease watchdog +After=local-fs.target + +[Service] +Type=simple +User=root +ExecStart=/usr/local/bin/xtcp2-treatmentctl -mode=watchdog -config=/etc/xtcp2/controller-agent.json +Restart=always +RestartSec=2s +StateDirectory=xtcp2 +StateDirectoryMode=0750 +AmbientCapabilities=CAP_NET_ADMIN CAP_SYS_PTRACE +CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_PTRACE +NoNewPrivileges=true + +[Install] +WantedBy=multi-user.target diff --git a/docs/integration-testing.md b/docs/integration-testing.md index 38a36994d..179b98d83 100644 --- a/docs/integration-testing.md +++ b/docs/integration-testing.md @@ -8,6 +8,7 @@ A comprehensive Nix-driven setup that boots xtcp2 inside QEMU microvms alongside - [Test surfaces at a glance](#test-surfaces-at-a-glance) - [Quick start](#quick-start) - [Architecture](#architecture) +- [TCP controller integration](#tcp-controller-integration) - [Microvm flavors](#microvm-flavors) - [Components](#components) - [xtcp2 daemon](#xtcp2-daemon) @@ -27,6 +28,109 @@ A comprehensive Nix-driven setup that boots xtcp2 inside QEMU microvms alongside - [Typical workflows](#typical-workflows) - [Troubleshooting](#troubleshooting) +## TCP controller integration + +Run `nix run path:.#test-tcp-controller-vm -- --accel=auto` for a fresh +controller test, or `nix build path:.#checks.x86_64-linux.vm-tcp-controller -L` +for the cached KVM check. It also participates in `vm-all` and `integration-all`. +The configuration is in `nix/tests/tcp-controller/`; the test driver is Go in +`tools/tcp-controller-integration/`, using the generated controller gRPC client. + +Six agent guests run the existing `tcp_client` load generator and real xtcp2 +service. A seventh guest runs `tcp_server`, PostgreSQL, ClickHouse and the +controller. Six hosts satisfy the production requirement for four treated hosts +and two controls. Each agent has 32 connections to each of two destination +addresses. `tc netem` adds 5 ms and 80 ms of outbound delay respectively; +management traffic stays unshaped. UNIX datagram links connect the guests to a +bridge inside the controller guest, without host networking privileges or +external network access. Allow approximately 9 GiB for guest memory, plus QEMU +overhead. KVM is preferred; `--accel=tcg` is available for software emulation. + +The Go driver verifies measured RTT separation in ClickHouse, reviewed nearby +route application on one host (`congctl cubic`, `rto_min 5ms`, `quickack 1`, +`initcwnd 100`, `initrwnd 100`), existing Reno versus newly exposed CUBIC sockets, +durable prototext state across daemon/controller restarts, local and fleet holds, +and reviewed expansion to two hosts. It then raises one treated host's delay to +180 ms and requires automatic rollback from measured harm. Finally, it stops +the controller and one agent, advances that isolated guest's clock past the +unchanged one-hour trial lease, and requires the independent watchdog to remove +the route without resurrecting it after restart/reconnection. Main routes and +the system default congestion algorithm must remain unchanged. + +This is a functional safety test, not a benchmark claiming that CUBIC improves +the synthetic workload. Observation intervals are shortened to 20 seconds using +the existing policy configuration; production authorization and lease behavior +are unchanged. The test exercises the direct protobuf/HTTP ingest path, not the +Kafka pipeline or automatic candidate discovery. It does not test reboot or +completion of a fleet-wide rollout. + +Evidence is retained under `~/.cache/xtcp2-vm/tcp-controller//` (or +`$XDG_CACHE_HOME`): controller and agent serial logs, RTT measurements, agent +journals/routes/prototext state, a PostgreSQL dump and a bounded recent telemetry +sample. Runtime-generated credentials remain inside the disposable guests. +The unauthenticated fixture HTTP endpoint is test-only and confined to the +isolated guest network; production controller communication uses mTLS. + +For repeated changes over time, run the Go-driven soak variant: + +```sh +nix run path:.#test-tcp-controller-soak-vm -- --cycles=3 --interval=3m +``` + +The default takes roughly 30 minutes: three cycles of three RTT phases, followed +by a cooldown check. `--cycles=2..6` and `--interval=3m|4m|5m` control the run; +`--accel` and `--keep` work as in the short test. The optional cached check is +`checks.x86_64-linux.vm-tcp-controller-soak`. It is excluded from `vm-all` and +included in `integration-all -- --soak` as a fixed-cycle run; the aggregate's +`--duration` applies to its other soak runners. + +Each cycle sends the six agents to a fresh destination and changes its netem +delay from 180 ms to 5 ms and back to 180 ms. High RTT must produce no nearby +candidate. Low RTT must cause the **controller's scheduled discovery** to propose +a new experiment with the same five nearby route settings. The test verifies +that discovery has applied no routes, +then acts as an authenticated test operator to approve the first canary. It +checks all five installed kernel metrics and actual CUBIC socket exposure, +and rejects any unapproved expansion. When +RTT rises again, an active trial must roll back automatically based on measured +harm; the driver never requests a rollback. The aggressive profile can also +cross a safety guard during the low-RTT phase. Such an early withdrawal is +accepted only with valid harmful evidence, observed canary exposure and verified +route removal. It is recorded separately as `low_rtt_safety_rollback`, and the +test continues to require that the route stays withdrawn. At least one cycle +must exercise an injected-latency rollback with high RTT on the canary; early +withdrawals cannot substitute for that coverage. The summary reports both counts. + +This variant uses a one-minute discovery interval and lookback, leaving the +production defaults (30 minutes and one hour), review requirements, rollout +timing and 24-hour destination cooldown intact. Its discovery template explicitly +sets `maximum_rtt_increase=1.0` (100%): the production 10% guard allows only about +0.5 ms at this fixture's low RTT and can trigger before netem changes. The wider +test tolerance still requires automatic rollback for the 5 ms to 180 ms jump. +Production templates keep the 10% default unless explicitly configured otherwise. +The retransmission guard remains unchanged at 0.005 (0.5 percentage points). +Fresh destinations allow each +cycle to discover a new candidate without bypassing that cooldown. The final +phase revisits the first destination at low RTT and verifies that it stays +withdrawn. New load connections reset TCP_INFO's lifetime minimum RTT at the +start of discovery phases; the regression phase retains the treated sockets. +The fixed 80 ms reference traffic continues throughout. + +Evidence under `~/.cache/xtcp2-vm/tcp-controller-soak//artifacts/` +includes `soak-events.jsonl` (RTT changes, proposals, explicit test approvals and +automatic rollbacks), `soak-rtt.csv` (per-host RTT and algorithm/exposure samples +every 15 seconds), and `soak-summary.json`. These are written during the run so +they can be inspected while the guests are running. The controller still +requires an operator to approve treatment application; this test does not make +it an autonomous optimizer or demonstrate that CUBIC outperforms Reno. + +To view the decision timeline for a run: + +```sh +jq -r '[.at, .event, .destination, (.experiment.id // "")] | @tsv' \ + ~/.cache/xtcp2-vm/tcp-controller-soak//artifacts/soak-events.jsonl +``` + ## Introduction This is the heavy integration-testing side of xtcp2. Unit tests live in `pkg/*/_test.go` and are run by `go test ./...`; the work documented here exercises code paths that only fire under a real Linux kernel, real namespaces, real network sockets, a real Kafka broker, and so on. diff --git a/docs/netlink/README.md b/docs/netlink/README.md index 49f8ba50f..18030ac1b 100644 --- a/docs/netlink/README.md +++ b/docs/netlink/README.md @@ -59,8 +59,12 @@ nix run .#microvm-x86_64-goip-parity # the live tier; needs /dev/kvm, not r ## Two constraints worth knowing up front -> **No live kernel writes today.** Inspection sends read requests; implemented -> write verbs serialize dry-run requests for validation rather than applying them. +> **One live kernel write path, opted in.** Inspection sends read requests; +> the CLI's write verbs serialize dry-run requests for validation rather than +> applying them. The single exception is the treatment route actuator in +> [`internal/goip/actuate`](../../internal/goip/actuate), which installs +> host routes in a private table behind an explicit `enable_apply` setting +> ([tcp-controller.md](../tcp-controller.md#supported-routes-and-tcp-semantics)). The original expansion plan's read-only constraint was narrowed as dry-run write support landed. The first paths were `ip route` and `ip link` — see @@ -76,7 +80,13 @@ since its G3-T03, `RTM_NEWNEXTHOP` and `RTM_DELNEXTHOP`, and, since its G3-T04, `RTM_NEWADDRLABEL` and `RTM_DELADDRLABEL`, and, since its G3-T05, `RTM_SETNEIGHTBL` and `RTM_SETSTATS`, and, since its G3-T06, `RTM_NEWLINKPROP` and `RTM_DELLINKPROP`. Requests built there are written to a file for -comparison and never sent; no automated path applies a write to a live kernel. +comparison and never sent by the CLI. The one path that does send is +`goip.NetlinkSource.ApplyRouteControl`, reached only by the treatment +actuator: it admits acknowledged `RTM_NEWROUTE`/`RTM_DELROUTE`/`RTM_NEWRULE`/ +`RTM_DELRULE` requests built from `xtcpnl.RouteWrite` and `xtcpnl.RuleWrite`, +never from argv, and the actuator checks ownership and reads back after +every mutation. + Both dry runs have since landed on that gate: `goip link add|set|change|replace|delete` and `goip route add|change|replace|prepend|append|test|delete` build `ip`'s request @@ -90,7 +100,8 @@ now do too, and refuse with Supported families have expanded beyond those initial paths; the [coverage tracker](coverage-status.md) records current supported operations. Coverage of parsing and dry-run requests does not establish live mutation -support. Future action-taking is described in the +support; the actuator's two route forms and one rule are the whole of it. +Broader action-taking is described in the [network-control gRPC design](../design-network-control-grpc.md), which is a proposal rather than an available service. Comparisons with libraries that configure the kernel must preserve that distinction. diff --git a/docs/socket-analysis.md b/docs/socket-analysis.md index 94547c5fd..7abe320df 100644 --- a/docs/socket-analysis.md +++ b/docs/socket-analysis.md @@ -4,6 +4,10 @@ This guide is for a **data / analytics team** turning xtcp2's per-socket TCP tel Read [parquet-format.md](parquet-format.md) first for how to load the data and what the columns mean; this doc is the analysis companion. +To turn those observations into reviewed canaries, see the +[TCP treatment controller](tcp-controller.md), including destination scope, +actual socket exposure, persistence, and emergency withdrawal. + ## Table of contents - [The RTT-band mental model](#the-rtt-band-mental-model) diff --git a/docs/status-tcp-controller.md b/docs/status-tcp-controller.md new file mode 100644 index 000000000..c500e6043 --- /dev/null +++ b/docs/status-tcp-controller.md @@ -0,0 +1,308 @@ +# TCP route treatment controller: rework status + +Tracking document for the architecture-review rework of the treatment control +plane (PR #282, branch `feat/tcp-route-controller`). The plan is the review +itself: 12 work items applied as separate commits so the PR history reads as the +review being addressed. Items are listed in execution order. + +| # | Item | State | Commit | +| --- | --- | --- | --- | +| 1 | `pkg/treatment/identity` extracted; import-boundary test | done | 7dc118ca | +| 2 | `pkg/treatment` split by audience (`reconcile`, `experiment`, `agent`) | done | 2ca932f8 | +| 8 | proto moved to `xtcp_treatment/v1` with `buf.validate` rules | done | 460164b1 | +| 3 | explicit state machine; `Outcome` enum | done | 85b2cf59 | +| 4 | repository ports, relational schema, pgx, domain types, `wire` | done | eae1d87d | +| D1 | dual-mode agent, part 1: journal-specific proto, proto-free `reconcile`, `local`, `attribution`, watchdog off the agent | done | 6398338a | +| D2 | dual-mode agent, part 2: `-treatmentAttribution` journal watcher, `treatment` build tag, `cmd/xtcp2-treatment-agent`, Nix and module wiring | done | 87321a63, fix 20f3a35a | +| 5 | evidence port (`Source`, `CandidateSource`, `Warehouse`), ClickHouse as one adapter | done | caba9bc4 | +| 6 | auth as interceptor with per-RPC role option | done | d7fefee4 | +| 7 | typed `xtcpnl.RuleWrite`; backend to `internal/goip/actuate` | done | 3a2843b2 | +| 9 | identity/location startup check | done | 9372e0bf | +| 10 | blocking journal lock | done | 3478d9b3 | +| 11 | scale: notification watermark, heartbeat split, leader lease | done | 91ccde4a | +| 12 | docs: threat model, naming, SIGHUP, philosophy sentence | done | b6df3de9 | +| L | lint: comprehensive tier clean on the new code; `lint-baseline` gate passes | done | c3981ff1 | +| F1 | follow-up: `Experiments.List` and `Get` in a fixed number of statements | done | 75093584, lint 5ccc671e | +| F2 | follow-up: help smoke for the four treatment binaries and `zstd-probe` | done | 926c2c74 | +| F3 | follow-up: reproducible index timings (`bench-tcp-controller-postgres-indexes`) | done | 30a21cdd | +| F4 | follow-up: generated coverage table (`coverage-table.md` from the unit target) | done | 30a21cdd | +| F5 | follow-up: evidence bound to `(agent_id, boot_id, collection_id)` sessions | done | c2bf7d2d, cap 12cc5f6c, lint 87261db8 | + +Dual-mode agent (library + `cmd/xtcp2-treatment-agent` + `treatment` build tag +in `cmd/xtcp2`, with an `attribution` journal reader for the untagged daemon) +is decided and lands after item 4 as D1 and D2; the watchdog stays a separate +process. + +## D1 notes + +- The journal is `xtcp_treatment_journal.v1.Journal` (prototext), generated + into its own Go package so the host side never links the RPC stubs. Field + numbers and names differ from the old `LocalState`; an old snapshot fails + closed with "invalid treatment journal". No deployed journals exist yet. +- `reconcile.State`/`reconcile.Record` are the host-side types; `Record` + embeds `treatment.ApplicationRecord` plus the kernel-local fields, so a + check-in (`State.Reports()`) cannot leak route bytes by construction. +- `pkg/treatment/local` owns `Config`, `LoadConfig`, `HostIdentity` and the + goip adapter; `agent.Config` is an alias. The watchdog builds on `local` + and `reconcile` only. +- `pkg/treatment/attribution` holds the exposure index and `Stamp`; the agent + publishes an index after every pass (identity-only before the first). + +## Item 4 notes + +- Domain types live in `pkg/treatment/model.go` and `enums.go`; the generated + proto is wire-only and converted in `pkg/treatment/wire`. +- `Experiment.UpdatedAt` is a domain field (proto `updated_at = 14`) stamped by + the controller clock, so the discovery cooldown is testable on both stores. +- Evidence is stored once (`xtcp_treatment_evidence` + `_hosts`) with a content + digest; re-using an evidence ID for different content or another experiment + is `store.ErrEvidenceConflict`. The digest hashes timestamps at microsecond + precision because that is what `timestamptz` keeps. +- Every handler test runs against the in-memory store and, with + `XTCP_CONTROLLER_TEST_DSN`, against PostgreSQL; both stores pass the shared + conformance suite in `store/storetest`. + +## D2 notes + +- `cmd/xtcp2/treatments.go` is always built and owns `-treatmentAttribution` + (an `attribution.Watcher` over the journal directory) and the fatal checks; + `treatments_embedded.go` (`//go:build treatment`) registers the embedded + agent for `-treatmentConfig`. Both flags exist in every build so the flag + golden is flavor-neutral; the untagged daemon refuses `-treatmentConfig`. +- `mkGoBinary` gained `treatment ? null`: fat builds (full destination set) + embed the agent, slim flavors do not. `xtcp2-treatment-agent` joined + `binaryNames`; `test-focused-xtcp-treatment` runs the tagged daemon tests. +- The NixOS module gained `treatments.mode` (`embedded` | `standalone`), + `agentPackage` and `journalDirectory`; standalone adds the + `xtcp2-treatment-agent` service. The VM fixture runs standalone with + `xtcp2-min`, which exercises the journal watcher end to end. +- The boundary walk now honours build tags (`go/build.Context.MatchFile`), so + it asserts the untagged daemon never reaches the agent, identity or the + RPC proto, and the tagged one does reach the agent but never the controller. +- The first VM run of 87321a63 failed at the fresh six-host baseline with + `invalid evidence population`: in standalone mode the slim daemon had no + `-location`, so every record shipped `location=""` and the ClickHouse + analysis (which filters by location) saw no hosts. The watcher now adopts + the journal's location when the daemon has none and still keeps its own + when one is set (logged once either way). The rerun pinned to 20f3a35a + passed (seven sentinels). + +## Item 5 notes + +- `pkg/treatment/controller/evidence` holds the ports and the controller's + window policy (`WindowFor`, `SettleDelay`, `MaxWindow`); the controller + root no longer contains SQL text, an HTTP client or the word ClickHouse. +- `evidence/clickhouse` is the adapter: `analysis.sql` moved there unchanged, + the discovery query became `discovery.sql`, both embedded. `Candidates` + returns an error (not a skipped row) when a destination does not decode, + because that means the table is not the schema the adapter was written for. +- Handler tests use `fixedEvidence` and `fakeWarehouse`; the adapter keeps + the transport, evidence and (new) candidate contract tables plus the + real-SQL `TestClickHouseAnalysisCounterDeltas` the Nix harness greps for. +- `artifact_sha256` is documented as the digest of the unarchived response. + Archiving responses to the S3 destination remains a possible follow-up. + +## Item 6 notes + +- `identity.Policy` (method -> role) with `UnaryInterceptor`/`StreamInterceptor` + and `Authorize`; identity resolved once per call and stored in the context + (`WithIdentity`/`FromContext`). `identity.Agent`/`Operator` prefer that + identity and fall back to the peer, so handler-level tests and direct calls + are unchanged. Agent unary requests are additionally checked generically: + `GetAgentId()` must be the caller and a non-empty `GetLocation()` must be + the certificate's. +- `controller.RolePolicy()` derives the table from the proto option over + both service descriptors; `controller.GRPCOptions()` is what main passes + to `grpc.NewServer` (interceptors + message bounds). A method without a + role option is simply absent from the policy and refused for everyone. +- Tests: identity interceptor tables (unary, stream, resolve precedence), + the mTLS bufconn test now runs through the interceptors and checks an + undeclared method fails closed, and `TestEveryMethodAgainstEveryRole` + tries every served method with each of three callers. + +## Item 7 notes + +- `xtcpnl.RuleWrite` (+ `RuleAttr*`, `EncodeFibRuleHdr`, + `BuildRuleWriteRequest`) is `RouteWrite`'s counterpart for `RTM_NEWRULE`/ + `RTM_DELRULE`. `Table` is a u32: 1..255 goes in the header byte, above + that the header is `RT_TABLE_UNSPEC` and `FRA_TABLE` is written first, + which is also what the argv `table` keyword does at its position. +- `internal/goip/actuate` holds the backend (`actuate.Backend`, + `RouteTreatment`, `TCPRouteSettings`), split into `actuate.go`, `rules.go` + and `routes.go`; `rule()` builds from fields and refuses out-of-range + table/priority/protocol before encoding. `NetlinkSource.ApplyRouteControl` + stays in `internal/goip/route_control.go` because it needs the socket's + unexported descriptor; it is the only live-write entry point. +- Tests: `TestBuildRuleWriteRequest` (hand-written hex) and + `TestRuleWriteReadsBack` in `pkg/xtcpnl`; `TestRuleWriteTypedMatchesArgv` + in `internal/goip` compares typed and `parseRuleWriteArgs` bytes for the + treatment rule, v6, delete, table 255, /32, /128 and `not`; + `TestTreatmentRuleRequest` in `actuate` reads the owned rule back and + covers the refused ranges. The goip hermetic-import test pins the new + package in goip's closure; the Nix harness and docs point at + `./internal/goip/actuate`. + +## Item 9 notes + +- One rule for both modes, in `cmd/xtcp2/treatments.go`: an empty daemon + location adopts the agent's (logged once); a set one must equal the + agent's certificate-bound location. Embedded, `checkTreatmentLocation` + runs right after `agent.LoadConfig` and before any credential is read, + so a mismatch is the first line in the log and the agent does not start + (telemetry continues). Standalone, the attribution watcher already kept + the daemon's label and adopted the journal's when there was none + (20f3a35a); unchanged. +- main now passes `c.Location` (after `envOverrideLabeling`) to + `startTreatments`, so `LOCATION` from the environment counts in both + modes; it used to pass the raw flag. +- `agent.New` names both sides when config and certificate disagree. +- Tests: `TestCheckTreatmentLocation` (flag/env/equal/differs/override/case, + through `envOverrideLabeling`), tagged + `TestEmbeddedTreatmentAgentLocation` (unset and equal reach the + credential error, differs is refused before it), and the existing + attribution watcher rows for the standalone side. + +## Item 10 notes + +- `Journal.WithLock(ctx, fn)` waits for the flock (non-blocking attempts with + a 1 to 50 ms doubling delay, since a blocking flock cannot be interrupted by + a context) and returns `ErrJournalBusy` wrapping `ctx.Err()` at the + deadline, before reading the snapshot. Under the lock it sweeps + `.pending-*` files, which only a writer that died mid-write can leave. + `Reconciler.Run` passes its ctx; `SuspendLocal` gained a ctx and + `treatmentctl suspend|resume` bounds it at 30 s. `status` was already + lock-free and stays so; no `LOCK_NB` entry point is needed. +- Tests: `TestJournalLockWaits` (uncontended, contended-waits, ctx-deadline, + zero-budget), `TestJournalLockFreeReadUnderLock`, and + `TestJournalLockHolderDies`, which kills a child test process holding the + lock with a half-written temp file and checks the lock is free, the + snapshot intact and the temp file swept. + +## Item 11 notes + +- Notification scan: `Agents.DesiredRevisions` (full scan) became + `Agents.DesiredSince(ctx, since) []DesiredRevision{AgentID, Revision, + UpdatedAt}` with `>=` on `desired_updated_at`, ordered by stamp then ID. + `SaveDesired` and `Enroll` stamp with `clock_timestamp()` rather than + `now()`: `now()` is transaction start, which precedes the advisory lock, so + a stamp could sort before a row that committed earlier. With every stamping + writer under the mutation lock, stamps commit in order and the watermark + (newest stamp less a one-second margin, store clock only) cannot skip a + row; the margin covers a store clock step under a second and the hub drops + the repeats it causes. A step larger than the margin leaves that revision + to the agent's next check-in, which always returns desired state on a + revision mismatch. `TestNotifyWatermark` walks a scanner through first + scan, change, no change, equal stamp, scan failure, future stamp and + behind-watermark steps. +- Heartbeat split: `report_digest` column on `xtcp_treatment_agents` holds a + SHA-256 over the algorithm list and every record in insert-column form. + `Observe` does one `UPDATE ... FROM (... FOR UPDATE) RETURNING + o.report_digest` and rewrites the child rows only when the digest changed. + `TestPostgresObserveRewritesOnlyChangedReports` compares row `xmin` values + across identical, heartbeat-only, status, timestamp, order, algorithm and + dropped-record reports. +- Leader lease: `Store.Lease(ctx, name, fn) (held bool, err error)`. + Postgres takes `pg_try_advisory_lock(fnv64a(name))` on a dedicated + `db.Conn`, unlocks after `fn` with a bounded context, and discards the + connection if the unlock fails so a pooled connection never carries the + lock. Memory is a try-lock map outside the Tx snapshot. + `Server.Housekeep` runs `Maintain` and, when due, `Discover` under the + `housekeeping` lease; the controller main loop logs leader transitions + and advances its discovery cadence whether or not it held the lease. + Conformance rows: free, held-elsewhere, released-on-error, + independent-names, cancelled-context; `TestHousekeepLease` covers the + controller side. +- The schema is pre-release, so `report_digest` is added to the `CREATE + TABLE` rather than through an `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`. + +## Item 12 notes + +- `docs/tcp-controller.md` gained "Trust boundaries and threat model" + (principal table, defence in depth on the route, the evidence boundary: + host-stamped agent ID and location over an unauthenticated telemetry + pipeline, what bounds it today, what is not done) and "Names and surfaces" + (`treatment` for the feature, `controller` for the server role, `route` + for the kernel object; why `xtcp2-treatmentctl` is not part of `xtcp2ctl`; + the three configuration surfaces). The naming decision is to keep the + current binary names; no renames. +- SIGHUP: documented as "reconcile now" only, in both daemon modes and the + standalone agent; the daemon has no admin RPC yet, so the signal stays + until the network-control admin API exists. `xtcp2-treatmentctl + -mode=reconcile` is the controller-free full pass. +- `docs/README.md`: the hub intro and the link-monitor paragraph now say that + xtcp2 observes by default and that the treatment controller is the one + opt-in, operator-reviewed component that changes host state. + +## Lint notes + +- The comprehensive tier went from 107 findings to zero on the treatment + packages, the four binaries, `internal/goip/actuate` and the integration + tool, with no `//nolint`, no exclusions and no threshold changes. Long + functions (`reconcile.Run`, `Maintain`, `Control`, `Evaluate`, `Plan`, the + controller `main`) were split into named steps with unchanged behavior; + close, rollback and unlock errors are now joined into the returned error. +- The ClickHouse SQL test finds `clickhouse` on `PATH` (the unit check adds + it to `nativeBuildInputs`) instead of `XTCP_CLICKHOUSE_TEST_BINARY`. + +## Follow-up notes (F1-F5) + +- F1: `loadMany` reads experiment rows, cohorts and phases with + `id = ANY($1)`, then every referenced evidence document and its hosts in + two more statements; `List` adds the ID lookup. `TestPostgresListStatements` + pins List at six statements and Get at five whatever the population, using + `pgtest.OpenCounting` (a pgx query tracer) rather than a hook in the store. +- F2: `ipmeta-bootstrap` was also missing from `cmdNames` but exits 1 on + `-help` (its `ContinueOnError` flag set returns `flag.ErrHelp` as an error), + so it stays out; see TODO. +- F3: the index timings come from the Nix PostgreSQL 18.6 fixture: median + 22.27 ms without indexes, 0.023 ms with them, for an old destination's + cooldown lookup. The fixture setup is shared with the unit and race targets. +- F4: per-package coverage, no `-coverpkg`, so `pkg/treatment` reads 56.0%: + its enum, `Clone` and `Equal` methods are exercised from other packages. +- F5: the agent owns a per-process nonce, writes it into the journal header + on its first pass after starting (`Reconciler.CollectionID`; a reconciler + without one, the watchdog, keeps the header's), and reports it as + `Capabilities.collection_id`, which is now required. `Agents.Observe` + upserts the session and refreshes `last_seen` at most every five minutes; + `Agents.Sessions` returns sessions overlapping a window and housekeeping + prunes those older than eight days. `Sessions` returns at most + `MaxSessionsPerAgent` (8) per agent, the most recently seen, so an enrolled + host that rotates its nonce on every check-in unbinds only its own older + records instead of pushing the window past `evidence.MaxSessions` and + failing evidence for its whole cohort (raised by the commit security + review, fixed in the follow-up commit). Every evidence window (analyze, + maintenance, discovery baseline, and the VM driver's own baseline) carries + the population's sessions widened by ten minutes; `analysis.sql` + (`tcp-host-deltas-v2-bound`) measures only bound sockets and returns + `unbound_sockets` per host. Discovery keeps only enrolled candidates and + skips a candidate with fewer than three. The evidence digest hashes + `unbound_sockets` only when non-zero, so evidence stored before the column + keeps its digest. Schema additions are `ADD COLUMN IF NOT EXISTS`. The VM + test gains `TCP_CONTROLLER_BINDING_PASS`: the driver copies a cohort host's + recent records under a fake boot and nonce and requires `Analyze` to count + them as unbound; the safety analysis that follows runs with them present. The run at 87261db8 passed all eight sentinels; in the + binding evidence the spoofed host kept its 32 bound sockets and reported 32 + unbound, and the other five hosts reported none. +- Proto regeneration: `regen-protos` now emits protoc-gen-go v1.36.12 and a + newer protoc for C++, while the committed output for the other protos is + older, so only the two treatment protos' generated files were committed and + the drift in the rest was reverted. + +## TODO + +- The watchdog and `pkg/treatment/local` still link gRPC, through + `pkg/xtcpnl` -> `gen/go/xtcp_flat_record`, whose Go package carries that + proto's gRPC and gateway stubs. Generating the flat record's service stubs + into a separate package would let the boundary test forbid gRPC for every + goip user; `reconcile` is already gRPC-free. Boundary rule carries the TODO. + Needs the service in its own `.proto` with a separate `go_package` (a buf + `PACKAGE_SAME_GO_PACKAGE` exception keeps the wire method names) and a + networked `regen-protos`. +- Evidence windows travel as ClickHouse URL parameters. At 10,000 agents the + `agents` and `sessions` arrays approach ClickHouse's default 1 MiB + `http_max_uri_size`; move them to external data in the request body before + fleets that large. +- `ipmeta-bootstrap -help` exits 1; return 0 on `flag.ErrHelp` and add it to + the help smoke list. +- Regenerate all protos with the pinned generators in one commit so the + committed `gen/` matches `regen-protos` again. diff --git a/docs/tcp-controller-testing.md b/docs/tcp-controller-testing.md new file mode 100644 index 000000000..b3589dd86 --- /dev/null +++ b/docs/tcp-controller-testing.md @@ -0,0 +1,137 @@ +# TCP controller test and benchmark audit + +Audit date: 2026-10-25. All test drivers and benchmarks are Go. Nix provisions +fixtures; no Python driver is involved. + +## Reproduce + +```sh +nix build path:.#test-tcp-controller-unit --no-link --print-out-paths +nix build path:.#test-tcp-controller-race --no-link --print-out-paths +nix build path:.#bench-tcp-controller --no-link --print-out-paths +``` + +The first two targets are also flake checks, `tcp-controller-unit` and +`tcp-controller-race`. Their implementation is in +[`nix/tests/tcp-controller/quality.nix`](../nix/tests/tcp-controller/quality.nix). +They create a disposable PostgreSQL cluster using only a Unix socket and run +ClickHouse locally. They require the database tests to pass rather than silently +skip. No host routes are changed. Logs and coverage are retained in the output +store directory; benchmarks produce `benchmarks.txt`. + +The race target runs the feature suite and route-planning tests three times. +The benchmark target runs five one-second samples per case. Benchmark times are +observations, not CI thresholds: shared-machine load makes timing assertions +unreliable. Allocation counts are reported with `-benchmem`. + +For fast iteration without database fixtures: + +```sh +go test -ldflags=-checklinkname=0 ./pkg/treatment/... ./tools/tcp-controller-integration +CGO_ENABLED=1 go test -race -ldflags=-checklinkname=0 -count=10 \ + -run 'Concurrent|Notification|JournalConcurrent|AgentRun' ./pkg/treatment/... +go test -ldflags=-checklinkname=0 -run '^$' -bench . -benchmem ./pkg/treatment/... +``` + +Without `XTCP_CONTROLLER_TEST_DSN`, direct Go commands skip the PostgreSQL +tests; without a `clickhouse` binary on `PATH` they skip the ClickHouse SQL +test. The Nix targets supply both automatically. + +## Coverage and test contracts + +New contract tables carry a description and expected outcome: an error substring, +gRPC/HTTP status, decision outcome, or explicit state/boolean values. Every case +gets a fresh fixture. Coverage includes positive, negative, boundary and corner +cases; it is not based only on happy-path workflows. + +| Area | Cases and assertions | +| --- | --- | +| Validation | Nil inputs, identifier length/characters, IPv4/IPv6 host scope, DCTCP/ECN prerequisites, explicit false versus absent metrics, inclusive RTO/window limits, duplicate identities/destinations, predecessor scope, stable/trial leases, 4,096 assignments and 10,000 hosts, NaN/infinite/negative measurements, timestamp validity, provenance and policy limits. | +| Decisions | Every evaluation outcome, observation/freshness/clock-skew boundaries, minimum samples, missing hosts/exposure, treated and control harm, small cohorts, full-fleet safety, reviewed transitions, input immutability and exact RTT guard boundaries. | +| Persistence and reconciliation | Intent before mutation, crash recovery, stale/conflicting revisions and generations, expiry at the exact deadline, predecessor restoration, holds/tombstones, failed plan/install/verify/remove/enable, recovery after failure, corrupt/oversized journals, symlink rejection and competing writer exclusion. | +| Agent | Config defaults and malformed input, attribution versus actual algorithm exposure, IPv4/IPv6 and padded addresses, namespace separation, expiry and holds, immutable snapshots, concurrent publish/stamp/state reads, wake coalescing, connected/offline cancellation and identity inspection failure. | +| Controller | mTLS role and enrollment boundaries, authenticated status/readiness, desired-state watch cancellation, notification coalescing/reconnects, HTTP failures/body closure/size limits, SQL counter deltas/resets, real transaction/review races, durable holds, discovery ASN/prefix filters and cooldown across controller restart. | +| Route planning | Opt-in and private resource bounds, unsupported forwarding attributes, IPv6 encoding, explicit ECN/quickack enable/disable, preservation of unrelated metrics/locks, complete nearby profile and baseline immutability. | + +The table below is generated, not hand-collected: +`nix build .#test-tcp-controller-unit` writes it to `result/coverage-table.md` +from the unit run's `go test -cover` lines (PostgreSQL and ClickHouse fixtures +enabled, no skips), and `result/coverage.txt` holds the per-function figures. +`internal/goip/actuate` runs only its `TestTreatment*` tests there. The race +target (`test-tcp-controller-race`) runs the same packages three times under +`-race` and reports no coverage. + +| Package | Statements covered | +| --- | ---: | +| `pkg/treatment` | 56.0% | +| `pkg/treatment/agent` | 62.2% | +| `pkg/treatment/attribution` | 88.1% | +| `pkg/treatment/controller` | 74.4% | +| `pkg/treatment/controller/evidence` | 100.0% | +| `pkg/treatment/controller/evidence/clickhouse` | 93.9% | +| `pkg/treatment/controller/store/memory` | 95.9% | +| `pkg/treatment/controller/store/postgres` | 85.0% | +| `pkg/treatment/experiment` | 93.8% | +| `pkg/treatment/identity` | 90.5% | +| `pkg/treatment/local` | 70.5% | +| `pkg/treatment/reconcile` | 87.2% | +| `pkg/treatment/wire` | 86.2% | +| `tools/tcp-controller-integration` | 4.0% | +| `internal/goip/actuate` | 22.1% | + +`HealthyEvidence` and the treatment, TCP-settings, policy, evidence, proposal +and report validators reach 100% statement coverage; `Evaluate` 94.7%, +`ValidateDesired` 91.7%, socket stamping 100%, discovery 89.4%, the agent's +`Run` 97.4%, the reconciler's `Run` 85.0% and the attribution watcher's `Run` +84.8%. `pkg/treatment` reads lower than before the split because coverage is per +package (no `-coverpkg`): its enum, `Clone` and `Equal` methods are exercised +by the `wire`, store and controller tests, which do not count toward it. +Statement coverage is not branch coverage or a proof of correctness. + +Remaining gaps include some filesystem/syscall error paths, live namespace +inspection, TLS client construction, reconnect/backoff timing, and all +combinations of controller database failures. Kernel route mutation and network +behavior remain the responsibility of the existing disposable-namespace and +seven-guest VM tests. The integration harness itself has low unit coverage +(4.0%); most of its code only executes inside those VMs. This audit did not rerun +the 30-minute soak; the previous three-cycle soak passed before these changes. + +The new RTT boundary regression exposed floating-point cancellation: `5.5/5-1` +can be slightly greater than `0.1`. Safety checks now compute the relative +change from the difference; evaluation uses `Log1p` and compares in log space. +Tests accept exactly 10% and reject a measurable increase above it, including +fleet-size cases. Policy limits themselves are unchanged. + +## Benchmark review + +Host: AMD Ryzen Threadripper PRO 3945WX, Linux/amd64, Go 1.27.0. These are medians +of three 300ms samples from the direct Go commands, not the separate Nix run. +Raw results are retained in [before.txt](benchmarks/tcp-controller/before.txt) and +[after.txt](benchmarks/tcp-controller/after.txt). The later run includes additional +snapshot-publication and route-planning benchmarks that had no earlier baseline. + +| Operation, 10,000 hosts | Before | After | Bytes/op before → after | Allocs/op before → after | +| --- | ---: | ---: | ---: | ---: | +| Validate evidence | 3.40 ms | 2.72 ms | 874,017 → 437,242 | 79 → 33 | +| Fast safety gate | 5.90 ms | 4.06 ms | 2,621,904 → 1,311,648 | 239 → 99 | +| Evaluate experiment | 7.48 ms | 4.60 ms | 3,391,637 → 1,557,578 | 317 → 106 | + +The straightforward improvement was reserving map and slice capacity from known +population sizes. Evaluation time fell about 39% and allocated bytes about 54% +in these samples. There are no new caches, synchronization or retained mutable +state. Tests exercise the same decision contracts before and after allocation +changes. + +The per-socket hot path was already cheap: with 4,096 routes, a matched stamp +measured 36.6ns and a miss 23.9ns, both zero allocations. Snapshot rebuilding at +4,096 routes measured 0.69ms and 652KB; it occurs during reconciliation rather +than per socket. Full-profile route planning measured 1.12µs and 756 bytes per +operation. Notification benchmarks cover complete 100/1,000/10,000-host fanout, +including coalescing for slow readers. Their first publication initializes the +revision map, so reported bytes/op include that amortized startup cost. + +No additional optimization was justified for stamping or route encoding. The +controller microbenchmarks exclude database/network latency and cannot establish +fleet-wide throughput. Future scaling work should measure ClickHouse queries, +PostgreSQL transaction contention and journal fsync latency under realistic +fleet traffic before adding complexity to these in-memory paths. diff --git a/docs/tcp-controller.md b/docs/tcp-controller.md new file mode 100644 index 000000000..e4c571719 --- /dev/null +++ b/docs/tcp-controller.md @@ -0,0 +1,745 @@ +# Reviewed TCP route treatments + +xtcp2 can now opt into a separate controller that proposes TCP route treatments, +rolls them out after human review, and withdraws failed trials. Ordinary xtcp2 +collection and the goip CLI retain their existing behavior. The agent runs +either inside xtcp2 (`-treatmentConfig`, a build with the `treatment` tag) or +as the standalone `xtcp2-treatment-agent` beside an xtcp2 that only reads its +journal (`-treatmentAttribution`); see [Agent deployment](#agent-deployment). +Route application requires `enable_apply: true` in the agent configuration in +either arrangement. + +## Components and authority + +```mermaid +flowchart LR + D[xtcp2 socket collection] --> K[ClickHouse telemetry] + K --> A[Candidate discovery and evidence queries] + A --> C[xtcp2-controller] + H[Human operator via mTLS] --> C + C <--> P[(PostgreSQL experiments, assignments, holds, audit)] + C -->|revision notification| D + D -->|check-in and observed state| C + D --> J[Atomic protobuf-text journal] + J --> R[goip actuator, internal/goip/actuate] + R --> L[Owned Linux routes and TCP lookup rules] + W[Independent local lease watchdog] --> J +``` + +The implementation lives under [pkg/treatment](../pkg/treatment), split by +audience so that each binary links only the half of the contract it needs, with +a typed [protobuf contract](../proto/xtcp_treatment/v1/) (`xtcp_treatment.v1`: `treatment.proto` types, `agent.proto`, `operator.proto`) and a separate +[journal file format](../proto/xtcp_treatment_journal/v1/journal.proto) (`xtcp_treatment_journal.v1`) that the host side reads and writes without the RPC stubs: + +| Package | Used by | Contents | +| --- | --- | --- | +| `pkg/treatment` | everyone | the domain model (`Treatment`, `Experiment`, `Evidence`, `DesiredState`, enums), limits and validators; proto-free | +| `pkg/treatment/wire` | gRPC boundary | domain ↔ generated proto conversion; `Parse*` fails closed on unknown enums and invalid timestamps | +| `pkg/treatment/identity` | agent, controller, tools | SPIFFE URI identity, mTLS configuration, gRPC peer resolution, `Policy` interceptors that resolve the caller once per call | +| `pkg/treatment/reconcile` | agent, watchdog | intent journal (`State`, `Record`, the `xtcp_treatment_journal.v1` file format), reconciler, `Backend` interface, `Mode` (full or expiry-only); domain types only, no RPC proto, no gRPC | +| `pkg/treatment/local` | agent, watchdog, `treatmentctl` | the shared `controller-agent.json` config and the goip-backed reconciler built from it; no TLS, no controller | +| `internal/goip/actuate` | `local` | the route actuator: owned table, rule priority and protocol, baseline copy with TCP metrics, ownership and readback checks; requests come from `xtcpnl`'s typed `RouteWrite` and `RuleWrite` builders and reach the kernel only through `goip.NetlinkSource.ApplyRouteControl`, the one live-write path in goip | +| `pkg/treatment/attribution` | `xtcp2`, agent | the exposure index built from a journal snapshot and the hot-path telemetry stamp; the same code serves the embedded agent and a telemetry-only daemon | +| `pkg/treatment/experiment` | controller | evaluation statistics, cohort allocation, phase advancement, state machine; pure functions over domain types | +| `pkg/treatment/agent` | `xtcp2`, agent binary | check-in loop, watch stream, capabilities, over `local` and `attribution`; a library with two front ends | +| `pkg/treatment/controller` | `xtcp2-controller` | gRPC handlers, maintenance and discovery over the store and evidence ports | +| `pkg/treatment/controller/store` | controller | repository interfaces (`Agents`, `Experiments`, `Evidence`, `Holds`, `Audit`, `Metrics`) and `Store.Tx` | +| `pkg/treatment/controller/evidence` | controller | warehouse ports: `Source` (measure a `Window`), `CandidateSource` (scan a location), `Warehouse` (both); `WindowFor` is the controller's window policy | +| `pkg/treatment/controller/evidence/clickhouse` | `xtcp2-controller` | the one warehouse adapter: `analysis.sql` and `discovery.sql` over the ClickHouse HTTP interface, parameterized, 8 MiB response cap | +| `pkg/treatment/controller/store/postgres` | `xtcp2-controller` | the only package with SQL: relational schema, pgx through `database/sql`, advisory-lock transactions | +| `pkg/treatment/controller/store/memory` | handler tests | map-backed store that passes the same conformance suite (`store/storetest`) | + +The generated protobuf types are wire-only. The controller works on the Go +domain types and converts at the gRPC boundary; PostgreSQL holds a relational +schema (one column per field, `cidr` destinations, evidence stored once and +referenced by ID), so a proto field rename can never break SQL or an index. The +only JSON column is the append-only audit payload. + +`pkg/treatment/boundaries_test.go` enforces the layering: `xtcp2` and the agent +never link the controller, a SQL driver or the ClickHouse client; the domain +and experiment packages never import the proto or gRPC; the reconcile package +never imports the RPC proto or gRPC; the watchdog never links TLS identity, the +agent or the RPC proto; SQL lives only in the postgres store; the controller +never links the host-side reconcile, local or attribution packages or goip. +The binaries are: + +| Binary | Responsibility | +| --- | --- | +| `xtcp2-controller` | PostgreSQL state, discovery, analysis, review gates, leases, gRPC, status and metrics | +| `xtcp2-controllerctl` | Authenticated `propose`, `analyze`, `review`, `control`, and `inspect` requests | +| `xtcp2` | Telemetry attribution from the journal (always); the embedded agent with `-treatmentConfig` when built with the `treatment` tag | +| `xtcp2-treatment-agent` | The same agent as a standalone process: controller connection, journal and kernel reconciliation; pairs with `-treatmentAttribution` | +| `xtcp2-treatmentctl` | Local status, suspension, resume, reconciliation, independent watchdog | + +ClickHouse is an evidence source; PostgreSQL is the authority for desired state. +Every control mutation commits the experiment, affected assignments and audit +events in one transaction. A transaction-level advisory lock fences replicas. +Request IDs make operator retries idempotent; reusing an ID with a different +request is rejected. Reviews also require the expected experiment revision. +Agents consume complete revisioned snapshots, so missed notifications are safe. +A shared two-second notification scan coalesces updates; jittered check-ins run +approximately every thirty seconds. No message broker is required. + +The scan is incremental. Every desired-state write stamps the agent row with +the database clock (`clock_timestamp()`, taken after the advisory lock, so +stamps commit in lock order), and each scan reads only rows stamped at or +after the previous scan's newest stamp less a one-second margin, through the +`desired_updated_at` index. The first scan after a restart reads every row so +late subscribers learn the current revision; the hub drops repeated revisions. +A check-in writes one agent row: the record and algorithm rows are rewritten +only when a digest of the report's content changes, so a steady fleet costs +one single-row update per heartbeat. Maintenance and candidate discovery run +under a session-level advisory lease (`pg_try_advisory_lock` on a dedicated +connection) that one replica holds for the pass; the others log that they are +skipping. The lease is about cost, not correctness: every write is still fenced +by the transaction-level mutation lock. + +## Trust boundaries and threat model + +The control plane has four kinds of principal. What each can do is decided by +the certificate it presents or the host it runs on, never by a request field. + +| Principal | Credential | Can | Cannot | +| --- | --- | --- | --- | +| Operator | mTLS certificate with `spiffe://xtcp/operator/` | propose, analyze, review, control, inspect; every action is audited under that ID | act as an agent; reuse a request ID with a different body | +| Agent | mTLS certificate with `spiffe://xtcp/agent//` | check in, fetch and watch its own desired state | speak for another agent, call an operator RPC, move to another location, or receive a route no operator reviewed | +| Controller replica | PostgreSQL and ClickHouse credentials | everything above on the operators' behalf | nothing is withheld; replicas are peers and fully trusted | +| Host root | the journal directory and the netlink socket | run the agent, the watchdog and `xtcp2-treatmentctl`; suspend locally | change another host; the actuator only touches its own table, rule priority and route protocol | + +The route itself is defended in depth: the controller cannot install anything +without an operator review, the actuator refuses routes it does not own on +readback, trials carry leases the watchdog enforces without the controller, and +a local suspension or a withdrawn desired state removes routes without any +network dependency. + +Evidence is the weakest boundary and the one to understand. Every telemetry +record carries the agent ID, location, boot ID, collection nonce and exposure +fields that the host itself stamped, and reaches ClickHouse through the +existing telemetry pipeline (Kafka or NSQ, then ClickHouse), which carries no +per-host authentication. The controller therefore trusts the warehouse to tell +it which host produced a record. A compromised or misconfigured host can emit +records that name another enrolled agent in its location and shift that host's +measured goodput, retransmission ratio or RTT. It cannot make the controller +issue a route (that needs an operator), but it can push a running trial into an +automatic rollback by faking harm, or mask real harm on a host it impersonates. + +What limits that today: evidence queries filter by the experiment's location +and the frozen cohort's agent IDs, so records naming hosts outside the cohort +are never read. Within the cohort, evidence is bound to sessions: each agent +process draws a 16-byte collection nonce, writes it into its journal header +(where a telemetry-only daemon reads it) and reports it with its boot ID on +every mTLS check-in. The controller keeps every `(agent_id, boot_id, +collection_id)` it has heard (`xtcp_treatment_agent_sessions`, pruned after +eight days), passes the population's sessions for the window into the +analysis query, and measures only records stamped with one of them. Records +that name a cohort agent under any other boot or nonce are excluded from +every metric and counted per host as `unbound_sockets`, which `Analyze` and +`Inspect` return with the evidence a reviewer approves. Discovery proposes +only cohorts of enrolled agents, because only they have sessions. + +Per-host sample minimums and the two-minute freshness window bound how little +data can swing a verdict; every expansion and completion is a human review of +typed evidence, and completed experiments only ever request review on drift; +evidence rows are immutable once stored, keyed by ID and digest, and every +decision is in the audit log with the operator's identity. + +What binding does not stop: the nonce and boot ID travel in the same +unauthenticated telemetry they protect, so a principal that can read the +topic (or the warehouse) can copy a live session and forge records that bind. +It raises the bar from "know an agent ID" to "read the telemetry stream", and +it turns stale records from a previous boot or agent process into visible +unbound counts instead of evidence. A compromised host can still misreport +its own sockets; nothing short of signing records at the source would stop +that. + +Inside the controller, the advisory mutation lock and the housekeeping lease +order work and bound cost; neither is an authorization mechanism. Request IDs +make an operator's own retries idempotent; they are no defence against a +principal holding an operator certificate, who is an operator. + +## Names and surfaces + +One feature name, `treatment`, is used for everything the host side and the +contract share: the Go packages under `pkg/treatment`, the proto packages +`xtcp_treatment.v1` and `xtcp_treatment_journal.v1`, the journal, the +`treatment` build tag, the daemon flags `-treatmentConfig` and +`-treatmentAttribution`, and the NixOS options under +`services.xtcp2.treatments`. `controller` names the server role, so the server +binary is `xtcp2-controller` and its operator client is `xtcp2-controllerctl`. +`route` is reserved for the kernel object the actuator manages and appears in +`internal/goip/actuate` and in prose, not in a binary or package name. + +`xtcp2-treatmentctl` stays separate from the daemon's `xtcp2ctl` on purpose: +it works on the journal directory as root, has no network path and must keep +working, as the watchdog, when the daemon and the controller are both down. +Folding it into a daemon-side CLI would make the independent withdrawal path +depend on the process it is meant to outlive. + +There are three configuration surfaces, one per audience. Operators configure +`xtcp2-controller` with flags, a DSN file and an optional discovery-template +JSON file, all read at start. Hosts share one `controller-agent.json` between +the agent, the watchdog and `xtcp2-treatmentctl`, so all three agree on the +journal directory and route table. Operator requests are the RPC messages +themselves in protobuf text, which `xtcp2-controllerctl -file` sends without +a schema of its own. + +## Supported routes and TCP semantics + +The first actuator supports IPv4 `/32` and IPv6 `/128` destinations in the host +network namespace, with ordinary local/main/default routing and a unique simple +unicast baseline route. It refuses policy-routing configurations, VRFs, ECMP, +nexthop objects and unsupported forwarding attributes. Run it on the host, not +inside a private PID/network namespace. Its `/proc/1/ns/net` check detects an +ordinary namespace mismatch; it cannot prove that a container's PID 1 is the +physical host's PID 1. + +The default reserved resources are table **10002**, rule priority **30000**, and +route/rule protocol **242**. The actuator copies the baseline gateway, interface, +preferred source and supported metrics into a destination override. TCP rules +with `iif lo` select locally originated traffic. The rule is built from fields +with `xtcpnl.RuleWrite`, not from `ip rule` keywords; `TestRuleWriteTypedMatchesArgv` +in `internal/goip` keeps it byte for byte what `ip rule add table 10002 priority +30000 ipproto tcp iif lo protocol 242` sends. Unmatched traffic falls through +to the normal tables. Main-table routes are never rewritten. These reserved +resources must have one owner; every mutation checks ownership and readback, +and refuses to overwrite or delete a changed/foreign route. Link, address, route +and rule notifications trigger replanning, with periodic reconciliation as a +fallback. A changed forwarding path invalidates the old override. + +Settings include congestion algorithm and optional lock, minimum RTO in ms, +initial send/receive windows in segments, quick ACK and ECN. Bounds are enforced +in [validate.go](../pkg/treatment/validate.go). Algorithms must already be loaded. +DCTCP requires explicit ECN and an operator assertion that the fabric has been +independently verified; a low RTT alone does not establish that requirement. +There is no setting to disable TCP slow start. + +The nearby-traffic template in +[controller-discovery.json](examples/controller-discovery.json) requests CUBIC, +`rto_min=5ms`, `quickack=1`, `initcwnd=100`, and `initrwnd=100`. These are explicit +route overrides for the discovered destination, including nearby NFS traffic; +they do not depend on matching an application port. The initial windows are in +segments. Discovery preserves these settings in the proposal, and the daemon +persists them in its protobuf-text journal before applying them through goip. +Omitting an optional metric preserves the baseline route's setting. The short +and soak VM tests verify all five installed metrics, including after journal +replay in the short test. + +A route treatment is destination-scoped, not socket-scoped, even though socket +data discovers it. Established connections may retain previous TCP settings. +The controller does not call `setsockopt` on application sockets or restart +applications. Withdrawing a route does not immediately undo an algorithm already +selected by a live socket. Long-lived NFS connections can therefore delay an +experiment or make it inconclusive. Initial-window exposure is not inferable +from an established socket's current congestion window. First-release experiments +require a congestion algorithm so the evaluator can observe actual algorithm +exposure; other settings may accompany it, but separate changes are easier to +interpret. + +## Experiments and evidence + +Candidate templates search per data center, using RTT, retransmission ratio and +optional destination prefixes/ASN filters. RTT/ASN conditions propose a +hypothesis; they do not prove that CUBIC or BBR will help. Existing ASN enrichment +identifies provider mappings, not verified BGP origins. Discovery runs every +thirty minutes with a one-hour lookback and never approves its own proposals. +`-discoveryInterval` (1m..24h) and `-discoveryWindow` (1m..168h) configure these; +discovery is checked on one-minute maintenance ticks. Short windows are useful +for integration testing but change the population and stability of the evidence. +Templates may set `maximum_rtt_increase` as a fractional increase in the range +0..1; omission uses the production default of 0.1 (10%). This policy value is +frozen in each proposal for operator review. The VM soak fixture uses 1.0 to +tolerate small timing variations at 5 ms while testing a jump to 180 ms. +Initially only one proposed, +running or held experiment is allowed per data center. + +Each proposal freezes a host population and baseline. Allocation is deterministic +from the experiment ID and interleaved across kernel-version strata. The operator +reviews that population before approving the first host. Eligibility and algorithm +availability are checked again before a newly selected host is assigned. + +The default sequence doubles `1, 2, 4, 8, ...`, retains at least two untreated +hosts before the last phase, and then reaches 100% of the **frozen eligible +population**. For eight hosts it is `1, 2, 4, 6, 8`. Newly enrolled hosts do not +silently join an approved experiment. Every expansion and final completion needs +another human review. Minimum observation defaults to thirty minutes **after +verified application**, not merely thirty minutes after sending a command. + +| Default policy | Value | +| --- | --- | +| Minimum observation | 30 minutes | +| Maximum phase lifetime | 24 hours | +| Maximum evidence age | 2 minutes | +| Minimum samples per host | 30 sockets and 1 MiB acknowledged | +| Minimum treated hosts for benefit inference | 4 | +| Required lower-bound improvement | 5% | +| Retransmission guardrail | increase of 0.005 in retransmitted/sent byte ratio | +| RTT guardrail | 10% increase in per-host p95 socket RTT | +| Trial lease / renewal interval | 1 hour / 5 minutes | + +The first seven values are configurable in the experiment policy. Leases are +currently controller constants. Maintenance runs each minute and may renew the +current cohort with fresh healthy evidence, or roll it back for harm/expiry; +maintenance cannot promote it. A pause stops renewal and promotion, so existing +trial leases eventually expire. Stable assignments have no lease. Completed +experiments receive hourly drift analysis; regressions request operator review +instead of automatically changing approved stable routes. + +### Lifecycle + +An experiment's status only changes through the transition table in +[`experiment.Transition`](../pkg/treatment/experiment/statemachine.go); Review, +Control and maintenance all apply a named event to the current status, and any +pair outside the table fails with `FailedPrecondition`. `TestTransitionExhaustive` +pins every status and event pair. + +| From | Event | To | +| --- | --- | --- | +| PROPOSED | approve | RUNNING | +| RUNNING | approve (cohorts remain) | RUNNING, next phase issued | +| RUNNING | approve_final (100% phase) | COMPLETE | +| RUNNING | pause | PAUSED (routes stay, leases run down) | +| PROPOSED, RUNNING, PAUSED, COMPLETE | suspend | SUSPENDED (routes withdrawn) | +| PAUSED, SUSPENDED | resume | RUNNING with a fresh phase of the same size | +| PAUSED, SUSPENDED | resume_stable (last phase was FINAL_SAFETY) | COMPLETE | +| RUNNING, PAUSED | expire | ROLLED_BACK | +| RUNNING | harm | ROLLED_BACK | +| any non-terminal | reject, retire | RETIRED | +| any non-terminal | rollback | ROLLED_BACK | + +RETIRED and ROLLED_BACK are terminal; propose a new experiment instead. + +Evaluation results are the `Outcome` enum in `treatment.proto`, mirrored by +`experiment.Outcome`. Only `BENEFICIAL`, `SAFETY_ONLY` and `FINAL_SAFETY` can +promote a phase, and only through a review; `HARMFUL` and `EXPIRED` withdraw +automatically; `STALE` and `INSUFFICIENT_DATA` cannot renew a lease. `OBSERVING` +means every treated host has verified the assignment and the window is open. +An assignment is identified by its `experiment_id`; one experiment never issues +two concurrent assignments to the same host. + +[analysis.sql](../pkg/treatment/controller/evidence/clickhouse/analysis.sql) computes whole-window +counter deltas per boot, host, namespace and socket cookie, deduplicates poll +timestamps, then aggregates per host. It rejects negative endpoint deltas and +collection gaps over thirty seconds. Require normal collection at ten seconds +or faster. This is not a complete exporter-health detector: lost short flows, +resets followed by recovery within the window, and traffic missing altogether +still require external collector-health monitoring. + +The controller never names ClickHouse. `Maintain` and `Analyze` take an +`evidence.Source` and ask for `evidence.WindowFor(experiment, now)`; candidate +discovery takes an `evidence.Warehouse`, asks for `Candidates` within the +template's RTT and retransmission bounds, applies the template's ASN and prefix +allow-lists, then takes a baseline `Evidence` for each candidate before +proposing. `Evidence.artifact_sha256` is the digest of the raw response bytes +the summary was decoded from; the response is not archived, so reproducing a +measurement means re-running `query_version` over the same window. Handler +tests use in-memory fakes of both ports; the adapter has its own contract +tests plus a real-SQL test under `clickhouse local`. + +The host is the experimental unit. Evaluation compares each host's log goodput +change with contemporaneous controls and uses a conservative Welch interval +budgeted over planned phases and minute-level looks. Tiny cohorts are safety +canaries, not evidence of causal benefit. The final 100% phase checks safety after +benefit has been established with controls. RTT/retransmission guardrails protect +both treated and control hosts; insufficient, stale or unexposed data blocks +promotion. Arbitrary repeated operator analyses, adaptive populations, workload +shifts and shared bottlenecks limit statistical interpretation. This is a review +aid, not a guarantee of causality or application-level benefit. Validate NFS/RPC +latency, errors and throughput alongside socket measurements before approval. + +Evidence includes analysis/window times, query version, a result digest and +per-host measurements, stored immutably in PostgreSQL. The digest identifies the +query result; the raw ClickHouse response is not archived as an external artifact. +Reviewed phases retain their evidence, reviewer, reason, issue time, observation +start and decision time. New maintenance evidence never overwrites the approved +phase record. + +This release uses scheduled whole-window queries against `xtcp_flat_records_v2`. +The existing ingestion materialized view carries the additive attribution fields. +It deliberately does not compute counter deltas in an insert-triggered MV: socket +samples cross insert blocks. A future aggregating-state MV must preserve boundary +samples and deduplication before replacing this query. Benchmark query cost and +end-to-end delivery latency on representative data before enabling many data +centers or approaching 5–10k hosts. The 10k-host notification/cohort tests are not +a production fleet load test. + +## PostgreSQL lookup costs and discovery reservations + +Discovery first checks the one-active-experiment budget for the data center. +If it is occupied, that template's ClickHouse scan is skipped. Otherwise each +candidate is checked in PostgreSQL by `(location, destination)` before fetching +baseline evidence. PROPOSED, RUNNING, PAUSED, SUSPENDED and COMPLETE experiments +reserve their destinations. RETIRED and ROLLED_BACK experiments reserve them until +24 hours after `updated_at`; at exactly 24 hours they become eligible again. +COMPLETE represents a stable treatment, so it does not expire out of this check. + +These checks use experiment state, not a fresh read of every machine's kernel +routes. Desired assignments describe the controller's intent, agent reports +describe verified application, and reconciliation repairs divergence. Drift +monitoring of a completed treatment can request operator review; automatic +discovery does not replace it. An explicit operator proposal may replace a stable +treatment using the existing reviewed predecessor/rollback mechanism. + +The early lookup is an optimization. The proposal transaction repeats the +destination check under the existing advisory lock, and repeats the DC budget +check, so concurrent controllers or changes during ClickHouse analysis cannot +insert competing automatic proposals. A database lookup failure stops discovery. + +Two B-tree indexes on plain columns support these paths: + +| Index | Keys | Purpose | +| --- | --- | --- | +| `xtcp_treatment_experiments_destination` | location, treatment destination (`cidr`), updated_at | Existing-treatment and cooldown lookup without scanning unrelated history. | +| `xtcp_treatment_experiments_location_status` | location, experiment status | DC budget lookup and status-based maintenance selection. | + +The budget query uses `EXISTS` rather than counting every match. Evidence host +rows live in `xtcp_treatment_evidence_hosts`, keyed by evidence ID, so an +experiment row stays small no matter how many hosts were measured. Agent +primary-key and location indexes cover their lookups; the notification scan +reads through `xtcp_treatment_agents_desired_updated` with a watermark, so it +touches the rows that changed since the last scan rather than the fleet. +`TestPostgresObserveRewritesOnlyChangedReports` checks, through row `xmin` +values, that an unchanged report leaves the record and algorithm rows alone. + +`TestPostgresExperimentQueryIndexes` (in `store/postgres`) loads 100,000 retired +experiments and five active experiments, runs `ANALYZE`, and compares +`EXPLAIN (ANALYZE, BUFFERS)` with and without these indexes. It checks that +PostgreSQL chooses an appropriate index without disabling sequential scans; +execution times are logged, not used as brittle pass/fail thresholds. The store +conformance suite (`store/storetest`, run against both PostgreSQL and the +in-memory store) covers all lifecycle states, cooldown boundaries and +location/destination isolation. Concurrent proposal tests verify that only one +automatic proposal is persisted. + +On the Nix PostgreSQL 18.6 fixture (`nix build .#bench-tcp-controller-postgres-indexes`), +three repeated runs measured a median 22.27 ms without indexes versus 0.023 ms +with them for an old destination's cooldown lookup. These are synthetic query +execution times, not end-to-end production latency. [Raw query-plan timing results](benchmarks/tcp-controller/postgres-indexes.txt) +also include missing destinations and active/idle data-center budget checks. + +Startup migration creates missing indexes idempotently. For an existing busy +database, prebuild these indexes before restarting controllers: + +```sql +-- Run outside a transaction, using the controller database/schema. +CREATE INDEX CONCURRENTLY IF NOT EXISTS xtcp_treatment_experiments_destination + ON xtcp_treatment_experiments (location, treatment_destination, updated_at); +CREATE INDEX CONCURRENTLY IF NOT EXISTS xtcp_treatment_experiments_location_status + ON xtcp_treatment_experiments (location, status); +``` + +Normal index creation blocks writes while building; PostgreSQL's +[concurrent index creation](https://www.postgresql.org/docs/current/sql-createindex.html#SQL-CREATEINDEX-CONCURRENTLY) +avoids that write-blocking build. If a concurrent build fails, inspect and remove +its invalid index before retrying: `IF NOT EXISTS` does not repair an invalid +index. The startup migration uses ordinary index creation, not concurrent DDL. + +Further scaling work should measure per-host SQL round trips during review and +lease renewal, large experiment-document rewrites, and evidence/audit +retention. Those need batching or data-layout changes, not blanket indexes on +every field. Discovery currently considers the ten busiest candidate +destinations per template before the PostgreSQL destination filter; pagination +or earlier exclusion would be needed to avoid already-treated destinations +occupying all ten slots. + +## Persistence, restart and withdrawal + +`/var/lib/xtcp2/routes/state.textproto` is the authoritative atomic snapshot: +prototext of `xtcp_treatment_journal.v1.Journal`, a file format of its own with +a header naming the writing agent, location and boot. It is converted to and +from the domain types on every pass and validated on every load; a snapshot in +any other shape (including the pre-rework `LocalState` text) fails closed. +`assignment-.textproto` files are readable projections containing receipt, +attempt, application, verification and removal times. Projection files are never +replayed independently. A private directory, file lock, temp-file rename and file +and directory fsync serialize the daemon, watchdog and local commands. The lock +waits rather than fails: each pass is bounded by its caller's context (15 s for +the agent's check-in, 25 s for a watchdog pass, 30 s for `treatmentctl +suspend`/`resume`), and at the deadline the caller gets "treatment journal busy" +without having read or written anything. A holder that dies releases the lock, +and the next holder sweeps the half-written temporary file it left. +`treatmentctl status` reads the snapshot without the lock and never waits. +Intent is persisted before kernel mutation; kernel readback precedes success +reporting. Do not hand-edit projections to change desired state. + +Startup, periodic work and SIGHUP reconcile the snapshot. Boot IDs prevent stale +kernel fingerprints from being treated as current installations after reboot. +Stable assignments are restored without a controller round trip. Trial expiry is +latched locally: a delayed renewal of the same generation cannot resurrect it. +An explicit approved reactivation increments the generation. A trial replacing a +stable treatment stores a predecessor; expiry/rollback restores that predecessor +when it can be safely replanned. Permanent retirement removes the override. + +Run the independent watchdog even when xtcp2 itself stops. It checks every thirty +seconds and withdraws expired trials or persistent holds; it cannot accept new +desired state. Local time synchronization and monitoring of both processes are +required. If both processes are stopped, userspace cannot enforce the lease. +Corrupt journals fail closed for new application and require operator recovery; +they cannot prove ownership of routes already installed. + +| Operation | Result | +| --- | --- | +| Experiment `PAUSE` | Freeze promotion and renewal; existing leases run out | +| Experiment/host/DC/fleet `SUSPEND` | Persist a hold and withdraw owned overrides | +| Experiment `RESUME` | Explicitly reactivate the same cohort with a new generation and observation window | +| Host/DC/fleet `RESUME` | Remove that scope's hold; broader and local holds still win | +| Experiment `ROLLBACK` | End the experiment; restore a saved stable predecessor when present | +| Experiment `RETIRE` | End the experiment and remove its overrides | +| Local `suspend` | Offline persistent hold that controller requests cannot clear | + +Broad holds are inherited by new enrollments. A narrower resume cannot clear a +broader hold. Expired trials remain latched after a broad hold is lifted; pause +then explicitly resume the experiment, or retire it and propose a new one. +Suspending a completed experiment and resuming it preserves its stable approval. +Withdrawals affect future route/connection behavior; allow existing connections +to turn over before interpreting a temporary baseline test. Disconnected agents +cannot receive an immediate remote hold; use the local command or wait for trial +expiry. Stable routes intentionally persist during controller outages. + +Before disabling `enable_apply`, removing `-treatmentConfig`, stopping a +standalone agent for good, or uninstalling the watchdog, suspend the treatments +and verify withdrawal. Disabling the +actuator prevents further writes; it does not itself delete existing kernel +routes. Keep the journal through cleanup so ownership can be checked. + +## Agent deployment + +The agent is a library (`pkg/treatment/agent`) with two front ends. Pick one per +host; xtcp2 refuses both flags together. + +| Arrangement | xtcp2 flag | Who owns the journal and routes | When | +| --- | --- | --- | --- | +| Embedded | `-treatmentConfig=/etc/xtcp2/controller-agent.json` | xtcp2 itself | the fat `xtcp2` build (Nix: every attribute with the full destination set carries the `treatment` tag); one process to run and one journal writer | +| Standalone | `-treatmentAttribution=/var/lib/xtcp2/routes` | `xtcp2-treatment-agent -config=/etc/xtcp2/controller-agent.json` | slim xtcp2 flavors (`xtcp2-min`, `xtcp2-kafka`, ...), which do not embed the agent, or wherever the controller connection and kernel writes should restart independently of collection | + +In both arrangements the daemon stamps every record from the same exposure +index (`pkg/treatment/attribution`): agent, boot, collection nonce, desired +revision and, for sockets whose destination has a verified route in the host +namespace, the experiment, generation, application time and whether the +observed congestion algorithm matches. Embedded, the index is rebuilt after +every reconcile pass. Standalone, xtcp2 watches the journal directory +(inotify on the atomic rename of `state.textproto`, a 30 s poll as fallback, +SIGHUP to re-read now) and rebuilds it from the snapshot; a missing or invalid +snapshot clears attribution rather than stamping stale state. The collection +nonce is the agent's in both arrangements: the agent writes it into the +journal header on its first pass after starting, the watchdog preserves it, +and a journal without one (written by an older agent) is stamped without a +nonce, which the controller counts as unbound, and logged once. + +Location follows one rule in both arrangements, because the agent's location +is certificate-bound and evidence queries filter by it. A daemon started +without `-location`/`LOCATION` adopts the agent's location for its records and +logs that once. A daemon with its own label keeps it: embedded, an agent whose +location differs refuses to start with a message naming both labels (socket +telemetry continues without the agent); standalone, the watcher keeps the +daemon's label and logs the disagreement once. No label is rewritten silently. +`agent.New` likewise refuses a config whose `location`/`agent_id` differ from +the certificate's URI SAN, naming both. + +SIGHUP means "reconcile now" on the host side, and nothing else. In `xtcp2` +it wakes the embedded agent (check in, then reconcile) or the journal watcher +(re-read the snapshot); it never rebaselines link state, which is SIGUSR1, and +never reloads configuration or restarts collection. The standalone agent +handles SIGHUP the same way. The daemon has no admin RPC surface today, so a +signal is the only in-process nudge; the +[network-control gRPC design](design-network-control-grpc.md) describes a +future admin API, and when it lands "reconcile now" becomes a method there with +SIGHUP kept as its signal equivalent. `xtcp2-treatmentctl -mode=reconcile` +is different: it runs one full reconcile pass from the journal through the +actuator in its own process, without the controller, and prints the resulting +snapshot, which is the tool for a host whose agent is stopped. + +A build without the `treatment` tag rejects `-treatmentConfig` at startup with +a message naming both remedies, the same way a slim build rejects an enricher +it lacks: a missing build tag is a property of the artifact and must not +degrade silently. `go test ./cmd/xtcp2` covers the untagged daemon; +`nix build .#test-focused-xtcp-treatment` (or +`go test -tags treatment ./cmd/xtcp2 ./cmd/xtcp2-treatment-agent`) covers the +embedded path. The watchdog, `xtcp2-treatmentctl -mode=watchdog`, is a +separate process in both arrangements and builds on `pkg/treatment/local` and +`pkg/treatment/reconcile` only. + +## Deployment + +1. Build the controller, client, treatmentctl, the standalone agent if you + use it, and your normal xtcp2 build flavor. Nix exposes + `.#xtcp2-controller`, `.#xtcp2-controllerctl`, `.#xtcp2-treatment-agent` + and `.#xtcp2-treatmentctl`; all of them also build with ordinary `go build`. +2. Provision PostgreSQL with backups and a restricted database identity. The + controller's `-migrate` applies the additive schema; use it during controlled + deployment, then remove it from the long-running command. Back up audit and + evidence tables together. Restoring an older database can yield revisions + older than daemon journals: stop mutations and reconcile state explicitly; + do not reset daemon revisions to make the errors disappear. +3. Update the ClickHouse protobuf format schema and apply + [xtcp_treatment_migration.sql](../build/containers/clickhouse/initdb.d/sql/xtcp_treatment_migration.sql) + to an existing deployment before enabling agents. Fresh-install DDL already + contains the new columns. Preserve the telemetry tables and Kafka offsets. +4. Provision mutually authenticated TLS. The controller needs a server DNS SAN; + agents have exactly one URI SAN `spiffe://xtcp/agent//`; + operators have exactly one URI SAN `spiffe://xtcp/operator/`. + Agent IDs are globally unique and location is certificate-bound. Agent + certificates cannot invoke operator RPCs or fetch another agent's state. + Use protected key files; restart processes to load rotated certificates. + There is no online certificate revocation service in this release. + + Authorization is declared, not hand-rolled. Every RPC in `agent.proto` and + `operator.proto` carries an `(xtcp_treatment.v1.role)` option; the + controller builds an `identity.Policy` from those options at startup and + installs unary and stream interceptors that resolve the peer certificate + once, refuse the wrong role, refuse any method without a declaration + (fail closed), and for agent RPCs refuse a request whose `agent_id` or + `location` is not the certificate's. Handlers read the resolved identity + from the context; the same `identity.Agent`/`identity.Operator` checks + remain in the handlers so a direct call behaves identically. A test in + `pkg/treatment/controller` tries every served method with an agent + certificate, an operator certificate and none, and fails if a method has + no declaration. +5. Configure explicit protected prefixes for management, DNS, telemetry, + controller dependencies and any infrastructure that must not be experimented + on. The agent also protects controller addresses resolved at startup. DNS + changes are why configured management prefixes remain necessary. +6. Start the controller near ClickHouse/PostgreSQL, enable agents with application + disabled first, validate identity/telemetry, then enable the actuator on a + small test population and deploy the independent watchdog. + +Example controller invocation (secrets remain outside the command line): + +```sh +xtcp2-controller -listen=:9443 -statusListen=127.0.0.1:9444 \ + -cert=/etc/xtcp2/controller.crt -key=/etc/xtcp2/controller.key \ + -ca=/etc/xtcp2/clients-ca.crt -databaseDSNFile=/etc/xtcp2/postgres.dsn \ + -clickhouse=https://clickhouse.example.net:8443 \ + -discoveryTemplates=/etc/xtcp2/discovery.json +``` + +ClickHouse credentials use `XTCP_CLICKHOUSE_USER` and +`XTCP_CLICKHOUSE_PASSWORD`. Without `-clickhouse`, analysis and lease renewal are +disabled; manual safety controls remain available. The example +[agent configuration](examples/controller-agent.json) is intentionally disabled; +replace its documentation addresses and protected prefixes before use. The +[discovery templates](examples/controller-discovery.json) are examples of +hypotheses, not recommended network-wide tuning defaults. + +On NixOS, set `services.xtcp2.treatments.enable = true`, its `configFile`, and +`watchdogPackage`. `treatments.mode` selects the arrangement: `embedded` (the +default; `package` must be a build with the `treatment` tag) passes +`-treatmentConfig`, `standalone` runs `agentPackage`'s +`xtcp2-treatment-agent` as its own service and passes +`-treatmentAttribution=` to xtcp2. The module creates an +independent watchdog service in both modes; the example +[standalone agent unit](examples/xtcp2-treatment-agent.service) is the +non-NixOS equivalent. A runtime +JSON file and private keys should remain outside the Nix store. The existing +`systemctl reload xtcp2` sends SIGUSR1 for link-monitor baseline relearning; +use `kill -HUP ` for route reconciliation. Other systems can use the +[example watchdog unit](examples/xtcp2-treatment-watchdog.service). + +## Operator workflow + +Every CLI request is protobuf text, following the messages in the contract. +Supply `-controller`, `-serverName`, `-cert`, `-key` and `-ca` on each invocation. +Use `-method=inspect` to find proposals and their revisions. Discovery creates +proposals automatically when configured; `-method=propose` accepts a manually +constructed `ProposeRequest` with a complete baseline and policy. + +Before approval, refresh and inspect evidence with `-method=analyze`: + +```protobuf +experiment_id: "hyp-example" +expected_revision: 1 +``` + +The result is an `AnalyzeResponse` containing `evidence { ... }` and `outcome`. +Copy the evidence block into a `ReviewRequest`, retaining its exact ID and values: + +```protobuf +experiment_id: "hyp-example" +expected_revision: 1 +approve: true +reason: "Reviewed baseline, eligible hosts and route scope" +request_id: "review-hyp-example-1" +# evidence { ...exact evidence returned by Analyze... } +``` + +Invoke `-method=review -file=review.textproto`. Subsequent reviews require fresh +evidence covering the observation window. Reuse the same request ID and exact +body after a network timeout; use a new ID for a new decision. Stale revision, +evidence, missing exposure, incomplete host reports or failed guards block review. +An operator may reject a proposal or stop a trial with `approve: false`. + +For an emergency fleet hold, use `-method=control` with: + +```protobuf +fleet: true +action: CONTROL_ACTION_SUSPEND +reason: "Temporary baseline comparison for incident 123" +request_id: "incident-123-fleet-hold" +``` + +The same message with a **new** ID and `CONTROL_ACTION_RESUME` lifts that fleet +hold. Substitute exactly one of `location`, `agent_id` or `experiment_id` for +`fleet` to narrow the scope. Offline local withdrawal: + +```sh +xtcp2-treatmentctl -config=/etc/xtcp2/controller-agent.json \ + -mode=suspend -reason='Local baseline comparison for incident 123' +xtcp2-treatmentctl -config=/etc/xtcp2/controller-agent.json -mode=status +xtcp2-treatmentctl -config=/etc/xtcp2/controller-agent.json \ + -mode=resume -reason='Comparison finished' +``` + +The optional status listener provides operator-mTLS-protected `/readyz`, `/status` +and `/metrics`. Monitor controller/agent availability, failed and expired route +records, holds, growing pending experiments, evidence freshness and watchdog +logs. `/status` is a JSON dashboard feed, not a graphical UI. A stopped controller +does not disable the ordinary xtcp2 collection service. + +## Validation and remaining extensions + +See the [test and benchmark audit](tcp-controller-testing.md) for table-driven +contracts, race coverage, measured performance, coverage limits, and reproducible +Nix unit/race/benchmark targets with isolated PostgreSQL and ClickHouse fixtures. + +Tests cover durable intent/crash recovery, stale generations, predecessor expiry, +local/broad holds, concurrent controller reviews, full human-reviewed rollout, +early safety withdrawal, actual algorithm attribution, 10k-host cohort and +notification behavior, the incremental notification watermark, the heartbeat +split and the housekeeping lease. Optional tests exercise real PostgreSQL, ClickHouse SQL, +and IPv4/IPv6 netlink mutation in a disposable namespace: + +```sh +go test ./pkg/treatment/... ./internal/goip/... +XTCP_CONTROLLER_TEST_DSN='host=... dbname=... user=... sslmode=...' \ + go test ./pkg/treatment/controller/... +PATH=/path/to/clickhouse/bin:$PATH \ + go test ./pkg/treatment/controller/evidence/clickhouse -run ClickHouse +XTCP_TREATMENT_LIVE_TEST=1 go test ./internal/goip/actuate -run '^TestTreatmentLiveNamespace$' +``` + +Every controller handler test runs twice, as `/memory` and +`/postgres`; without the DSN the PostgreSQL half skips. The store +conformance suite runs the same way from `store/memory` and `store/postgres`. +The PostgreSQL tests create and drop only unique test schemas. The route test +creates its own user/network namespace and verifies that it differs from the +parent namespace before any write. It requires `ip`, `unshare` and a kernel that +permits unprivileged user namespaces. Existing daemon tests need this repository's +`-ldflags=-checklinkname=0` flag for giouring. + +The [Go-driven controller VM integration test](integration-testing.md#tcp-controller-integration) +uses the existing TCP load tools, six agent guests, real PostgreSQL/ClickHouse, +and `tc netem` latency bands. Run `nix run path:.#test-tcp-controller-vm`; +the cached target is `checks.x86_64-linux.vm-tcp-controller`. It checks reviewed +1→2 canaries, actual socket algorithm exposure, restart persistence, holds, +automatic rollback after injected harm, and independent watchdog lease expiry. +The longer `test-tcp-controller-soak-vm` target varies RTT every three minutes, +checks repeated scheduled discovery and automatic rollback, and verifies the +destination cooldown. Its test operator explicitly approves each new canary. + +Future work includes application SLO inputs, richer workload/fabric stratification, +aggregated analytical storage, provider-feed provenance, enrollment reconciliation +for new hosts, multi-experiment scheduling, automated withdrawal experiments, +and a graphical review dashboard. A future automated/LLM reviewer can consume the +same typed evidence and decision interface, but the deterministic authorization, +ownership, budget, freshness and guardrail checks must remain mandatory. This +release does not autonomously promote treatments or claim that a successful +small test has optimized an entire production fleet. diff --git a/flake.nix b/flake.nix index 018dffdba..2ae77da5e 100644 --- a/flake.nix +++ b/flake.nix @@ -33,6 +33,15 @@ # See ./nix/README.md for individual targets, logs and Nix policy checks. # # Quick references: +# nix run path:.#test-tcp-controller-vm -- --accel=auto +# nix run path:.#test-tcp-controller-soak-vm -- --cycles=3 --interval=3m +# nix build path:.#test-tcp-controller-unit path:.#test-tcp-controller-race +# nix build path:.#bench-tcp-controller +# Repeated RTT changes, automatic discovery, test-operator approval, +# automatic rollback and cooldown checks (~30 minutes by default). +# Seven guests: TCP load, netem RTT bands, ClickHouse/PostgreSQL, reviewed +# canary, withdrawal and independent expiry. Also checks.vm-tcp-controller, +# checks.vm-all, and integration-all (nix/tests/tcp-controller). # nix develop # dev shell # nix build .#xtcp2 # main binary # nix build .#xtcp2-all # every cmd/* binary diff --git a/gen/cpp/xtcp_treatment/v1/agent.grpc.pb.cc b/gen/cpp/xtcp_treatment/v1/agent.grpc.pb.cc new file mode 100644 index 000000000..75c16bd26 --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/agent.grpc.pb.cc @@ -0,0 +1,167 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment/v1/agent.proto + +#include "xtcp_treatment/v1/agent.pb.h" +#include "xtcp_treatment/v1/agent.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace xtcp_treatment { +namespace v1 { + +static const char* AgentControlService_method_names[] = { + "/xtcp_treatment.v1.AgentControlService/CheckIn", + "/xtcp_treatment.v1.AgentControlService/GetDesiredState", + "/xtcp_treatment.v1.AgentControlService/WatchDesiredState", +}; + +std::unique_ptr< AgentControlService::Stub> AgentControlService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + (void)options; + std::unique_ptr< AgentControlService::Stub> stub(new AgentControlService::Stub(channel, options)); + return stub; +} + +AgentControlService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) + : channel_(channel), rpcmethod_CheckIn_(AgentControlService_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_GetDesiredState_(AgentControlService_method_names[1], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_WatchDesiredState_(AgentControlService_method_names[2], options.suffix_for_stats(),::grpc::internal::RpcMethod::SERVER_STREAMING, channel) + {} + +::grpc::Status AgentControlService::Stub::CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::xtcp_treatment::v1::CheckInResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_CheckIn_, context, request, response); +} + +void AgentControlService::Stub::async::CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_CheckIn_, context, request, response, std::move(f)); +} + +void AgentControlService::Stub::async::CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_CheckIn_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>* AgentControlService::Stub::PrepareAsyncCheckInRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::xtcp_treatment::v1::CheckInResponse, ::xtcp_treatment::v1::CheckInRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_CheckIn_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>* AgentControlService::Stub::AsyncCheckInRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncCheckInRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status AgentControlService::Stub::GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::xtcp_treatment::v1::GetDesiredStateResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GetDesiredState_, context, request, response); +} + +void AgentControlService::Stub::async::GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetDesiredState_, context, request, response, std::move(f)); +} + +void AgentControlService::Stub::async::GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetDesiredState_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>* AgentControlService::Stub::PrepareAsyncGetDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::xtcp_treatment::v1::GetDesiredStateResponse, ::xtcp_treatment::v1::GetDesiredStateRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GetDesiredState_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>* AgentControlService::Stub::AsyncGetDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncGetDesiredStateRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::ClientReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>* AgentControlService::Stub::WatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request) { + return ::grpc::internal::ClientReaderFactory< ::xtcp_treatment::v1::WatchDesiredStateResponse>::Create(channel_.get(), rpcmethod_WatchDesiredState_, context, request); +} + +void AgentControlService::Stub::async::WatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest* request, ::grpc::ClientReadReactor< ::xtcp_treatment::v1::WatchDesiredStateResponse>* reactor) { + ::grpc::internal::ClientCallbackReaderFactory< ::xtcp_treatment::v1::WatchDesiredStateResponse>::Create(stub_->channel_.get(), stub_->rpcmethod_WatchDesiredState_, context, request, reactor); +} + +::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>* AgentControlService::Stub::AsyncWatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq, void* tag) { + return ::grpc::internal::ClientAsyncReaderFactory< ::xtcp_treatment::v1::WatchDesiredStateResponse>::Create(channel_.get(), cq, rpcmethod_WatchDesiredState_, context, request, true, tag); +} + +::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>* AgentControlService::Stub::PrepareAsyncWatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncReaderFactory< ::xtcp_treatment::v1::WatchDesiredStateResponse>::Create(channel_.get(), cq, rpcmethod_WatchDesiredState_, context, request, false, nullptr); +} + +AgentControlService::Service::Service() { + AddMethod(new ::grpc::internal::RpcServiceMethod( + AgentControlService_method_names[0], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< AgentControlService::Service, ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](AgentControlService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::CheckInRequest* req, + ::xtcp_treatment::v1::CheckInResponse* resp) { + return service->CheckIn(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + AgentControlService_method_names[1], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< AgentControlService::Service, ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](AgentControlService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::GetDesiredStateRequest* req, + ::xtcp_treatment::v1::GetDesiredStateResponse* resp) { + return service->GetDesiredState(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + AgentControlService_method_names[2], + ::grpc::internal::RpcMethod::SERVER_STREAMING, + new ::grpc::internal::ServerStreamingHandler< AgentControlService::Service, ::xtcp_treatment::v1::WatchDesiredStateRequest, ::xtcp_treatment::v1::WatchDesiredStateResponse>( + [](AgentControlService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::WatchDesiredStateRequest* req, + ::grpc::ServerWriter<::xtcp_treatment::v1::WatchDesiredStateResponse>* writer) { + return service->WatchDesiredState(ctx, req, writer); + }, this))); +} + +AgentControlService::Service::~Service() { +} + +::grpc::Status AgentControlService::Service::CheckIn(::grpc::ServerContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status AgentControlService::Service::GetDesiredState(::grpc::ServerContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status AgentControlService::Service::WatchDesiredState(::grpc::ServerContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest* request, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* writer) { + (void) context; + (void) request; + (void) writer; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +} // namespace xtcp_treatment +} // namespace v1 +#include + diff --git a/gen/cpp/xtcp_treatment/v1/agent.grpc.pb.h b/gen/cpp/xtcp_treatment/v1/agent.grpc.pb.h new file mode 100644 index 000000000..6a60c3880 --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/agent.grpc.pb.h @@ -0,0 +1,566 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment/v1/agent.proto +// Original file comments: +// +// xTCP - treatment agent service +// +// The outbound-only RPC surface an agent uses: check in with observed state, +// fetch the authoritative desired state, and watch for revision hints. Every +// method requires an agent certificate whose SPIFFE id matches agent_id and +// whose location matches the request; see pkg/treatment/identity. +// +#ifndef GRPC_xtcp_5ftreatment_2fv1_2fagent_2eproto__INCLUDED +#define GRPC_xtcp_5ftreatment_2fv1_2fagent_2eproto__INCLUDED + +#include "xtcp_treatment/v1/agent.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xtcp_treatment { +namespace v1 { + +class AgentControlService final { + public: + static constexpr char const* service_full_name() { + return "xtcp_treatment.v1.AgentControlService"; + } + class StubInterface { + public: + virtual ~StubInterface() {} + virtual ::grpc::Status CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::xtcp_treatment::v1::CheckInResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::CheckInResponse>> AsyncCheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::CheckInResponse>>(AsyncCheckInRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::CheckInResponse>> PrepareAsyncCheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::CheckInResponse>>(PrepareAsyncCheckInRaw(context, request, cq)); + } + virtual ::grpc::Status GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::xtcp_treatment::v1::GetDesiredStateResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::GetDesiredStateResponse>> AsyncGetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::GetDesiredStateResponse>>(AsyncGetDesiredStateRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::GetDesiredStateResponse>> PrepareAsyncGetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::GetDesiredStateResponse>>(PrepareAsyncGetDesiredStateRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>> WatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request) { + return std::unique_ptr< ::grpc::ClientReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>>(WatchDesiredStateRaw(context, request)); + } + std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>> AsyncWatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq, void* tag) { + return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>>(AsyncWatchDesiredStateRaw(context, request, cq, tag)); + } + std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>> PrepareAsyncWatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>>(PrepareAsyncWatchDesiredStateRaw(context, request, cq)); + } + class async_interface { + public: + virtual ~async_interface() {} + virtual void CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response, std::function) = 0; + virtual void CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + virtual void GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response, std::function) = 0; + virtual void GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + virtual void WatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest* request, ::grpc::ClientReadReactor< ::xtcp_treatment::v1::WatchDesiredStateResponse>* reactor) = 0; + }; + typedef class async_interface experimental_async_interface; + virtual class async_interface* async() { return nullptr; } + class async_interface* experimental_async() { return async(); } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::CheckInResponse>* AsyncCheckInRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::CheckInResponse>* PrepareAsyncCheckInRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::GetDesiredStateResponse>* AsyncGetDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::GetDesiredStateResponse>* PrepareAsyncGetDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>* WatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request) = 0; + virtual ::grpc::ClientAsyncReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>* AsyncWatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq, void* tag) = 0; + virtual ::grpc::ClientAsyncReaderInterface< ::xtcp_treatment::v1::WatchDesiredStateResponse>* PrepareAsyncWatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub final : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + ::grpc::Status CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::xtcp_treatment::v1::CheckInResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>> AsyncCheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>>(AsyncCheckInRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>> PrepareAsyncCheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>>(PrepareAsyncCheckInRaw(context, request, cq)); + } + ::grpc::Status GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::xtcp_treatment::v1::GetDesiredStateResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>> AsyncGetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>>(AsyncGetDesiredStateRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>> PrepareAsyncGetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>>(PrepareAsyncGetDesiredStateRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>> WatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request) { + return std::unique_ptr< ::grpc::ClientReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>>(WatchDesiredStateRaw(context, request)); + } + std::unique_ptr< ::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>> AsyncWatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq, void* tag) { + return std::unique_ptr< ::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>>(AsyncWatchDesiredStateRaw(context, request, cq, tag)); + } + std::unique_ptr< ::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>> PrepareAsyncWatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>>(PrepareAsyncWatchDesiredStateRaw(context, request, cq)); + } + class async final : + public StubInterface::async_interface { + public: + void CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response, std::function) override; + void CheckIn(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + void GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response, std::function) override; + void GetDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + void WatchDesiredState(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest* request, ::grpc::ClientReadReactor< ::xtcp_treatment::v1::WatchDesiredStateResponse>* reactor) override; + private: + friend class Stub; + explicit async(Stub* stub): stub_(stub) { } + Stub* stub() { return stub_; } + Stub* stub_; + }; + class async* async() override { return &async_stub_; } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + class async async_stub_{this}; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>* AsyncCheckInRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::CheckInResponse>* PrepareAsyncCheckInRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::CheckInRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>* AsyncGetDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::GetDesiredStateResponse>* PrepareAsyncGetDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>* WatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request) override; + ::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>* AsyncWatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq, void* tag) override; + ::grpc::ClientAsyncReader< ::xtcp_treatment::v1::WatchDesiredStateResponse>* PrepareAsyncWatchDesiredStateRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest& request, ::grpc::CompletionQueue* cq) override; + const ::grpc::internal::RpcMethod rpcmethod_CheckIn_; + const ::grpc::internal::RpcMethod rpcmethod_GetDesiredState_; + const ::grpc::internal::RpcMethod rpcmethod_WatchDesiredState_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + virtual ::grpc::Status CheckIn(::grpc::ServerContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response); + virtual ::grpc::Status GetDesiredState(::grpc::ServerContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response); + virtual ::grpc::Status WatchDesiredState(::grpc::ServerContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest* request, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* writer); + }; + template + class WithAsyncMethod_CheckIn : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_CheckIn() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_CheckIn() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status CheckIn(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::CheckInRequest* /*request*/, ::xtcp_treatment::v1::CheckInResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestCheckIn(::grpc::ServerContext* context, ::xtcp_treatment::v1::CheckInRequest* request, ::grpc::ServerAsyncResponseWriter< ::xtcp_treatment::v1::CheckInResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_GetDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_GetDesiredState() { + ::grpc::Service::MarkMethodAsync(1); + } + ~WithAsyncMethod_GetDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::GetDesiredStateRequest* /*request*/, ::xtcp_treatment::v1::GetDesiredStateResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGetDesiredState(::grpc::ServerContext* context, ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::grpc::ServerAsyncResponseWriter< ::xtcp_treatment::v1::GetDesiredStateResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_WatchDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_WatchDesiredState() { + ::grpc::Service::MarkMethodAsync(2); + } + ~WithAsyncMethod_WatchDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status WatchDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::WatchDesiredStateRequest* /*request*/, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* /*writer*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestWatchDesiredState(::grpc::ServerContext* context, ::xtcp_treatment::v1::WatchDesiredStateRequest* request, ::grpc::ServerAsyncWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncServerStreaming(2, context, request, writer, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_CheckIn > > AsyncService; + template + class WithCallbackMethod_CheckIn : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_CheckIn() { + ::grpc::Service::MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::CheckInRequest* request, ::xtcp_treatment::v1::CheckInResponse* response) { return this->CheckIn(context, request, response); }));} + void SetMessageAllocatorFor_CheckIn( + ::grpc::MessageAllocator< ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0); + static_cast<::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_CheckIn() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status CheckIn(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::CheckInRequest* /*request*/, ::xtcp_treatment::v1::CheckInResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* CheckIn( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::CheckInRequest* /*request*/, ::xtcp_treatment::v1::CheckInResponse* /*response*/) { return nullptr; } + }; + template + class WithCallbackMethod_GetDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_GetDesiredState() { + ::grpc::Service::MarkMethodCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::GetDesiredStateRequest* request, ::xtcp_treatment::v1::GetDesiredStateResponse* response) { return this->GetDesiredState(context, request, response); }));} + void SetMessageAllocatorFor_GetDesiredState( + ::grpc::MessageAllocator< ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(1); + static_cast<::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_GetDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::GetDesiredStateRequest* /*request*/, ::xtcp_treatment::v1::GetDesiredStateResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* GetDesiredState( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::GetDesiredStateRequest* /*request*/, ::xtcp_treatment::v1::GetDesiredStateResponse* /*response*/) { return nullptr; } + }; + template + class WithCallbackMethod_WatchDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_WatchDesiredState() { + ::grpc::Service::MarkMethodCallback(2, + new ::grpc::internal::CallbackServerStreamingHandler< ::xtcp_treatment::v1::WatchDesiredStateRequest, ::xtcp_treatment::v1::WatchDesiredStateResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::WatchDesiredStateRequest* request) { return this->WatchDesiredState(context, request); })); + } + ~WithCallbackMethod_WatchDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status WatchDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::WatchDesiredStateRequest* /*request*/, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* /*writer*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerWriteReactor< ::xtcp_treatment::v1::WatchDesiredStateResponse>* WatchDesiredState( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::WatchDesiredStateRequest* /*request*/) { return nullptr; } + }; + typedef WithCallbackMethod_CheckIn > > CallbackService; + typedef CallbackService ExperimentalCallbackService; + template + class WithGenericMethod_CheckIn : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_CheckIn() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_CheckIn() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status CheckIn(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::CheckInRequest* /*request*/, ::xtcp_treatment::v1::CheckInResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_GetDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_GetDesiredState() { + ::grpc::Service::MarkMethodGeneric(1); + } + ~WithGenericMethod_GetDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::GetDesiredStateRequest* /*request*/, ::xtcp_treatment::v1::GetDesiredStateResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_WatchDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_WatchDesiredState() { + ::grpc::Service::MarkMethodGeneric(2); + } + ~WithGenericMethod_WatchDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status WatchDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::WatchDesiredStateRequest* /*request*/, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* /*writer*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithRawMethod_CheckIn : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_CheckIn() { + ::grpc::Service::MarkMethodRaw(0); + } + ~WithRawMethod_CheckIn() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status CheckIn(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::CheckInRequest* /*request*/, ::xtcp_treatment::v1::CheckInResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestCheckIn(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_GetDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_GetDesiredState() { + ::grpc::Service::MarkMethodRaw(1); + } + ~WithRawMethod_GetDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::GetDesiredStateRequest* /*request*/, ::xtcp_treatment::v1::GetDesiredStateResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGetDesiredState(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_WatchDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_WatchDesiredState() { + ::grpc::Service::MarkMethodRaw(2); + } + ~WithRawMethod_WatchDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status WatchDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::WatchDesiredStateRequest* /*request*/, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* /*writer*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestWatchDesiredState(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncWriter< ::grpc::ByteBuffer>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncServerStreaming(2, context, request, writer, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawCallbackMethod_CheckIn : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_CheckIn() { + ::grpc::Service::MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->CheckIn(context, request, response); })); + } + ~WithRawCallbackMethod_CheckIn() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status CheckIn(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::CheckInRequest* /*request*/, ::xtcp_treatment::v1::CheckInResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* CheckIn( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithRawCallbackMethod_GetDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_GetDesiredState() { + ::grpc::Service::MarkMethodRawCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GetDesiredState(context, request, response); })); + } + ~WithRawCallbackMethod_GetDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::GetDesiredStateRequest* /*request*/, ::xtcp_treatment::v1::GetDesiredStateResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* GetDesiredState( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithRawCallbackMethod_WatchDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_WatchDesiredState() { + ::grpc::Service::MarkMethodRawCallback(2, + new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const::grpc::ByteBuffer* request) { return this->WatchDesiredState(context, request); })); + } + ~WithRawCallbackMethod_WatchDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status WatchDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::WatchDesiredStateRequest* /*request*/, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* /*writer*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerWriteReactor< ::grpc::ByteBuffer>* WatchDesiredState( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/) { return nullptr; } + }; + template + class WithStreamedUnaryMethod_CheckIn : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_CheckIn() { + ::grpc::Service::MarkMethodStreamed(0, + new ::grpc::internal::StreamedUnaryHandler< + ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::xtcp_treatment::v1::CheckInRequest, ::xtcp_treatment::v1::CheckInResponse>* streamer) { + return this->StreamedCheckIn(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_CheckIn() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status CheckIn(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::CheckInRequest* /*request*/, ::xtcp_treatment::v1::CheckInResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedCheckIn(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::xtcp_treatment::v1::CheckInRequest,::xtcp_treatment::v1::CheckInResponse>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_GetDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_GetDesiredState() { + ::grpc::Service::MarkMethodStreamed(1, + new ::grpc::internal::StreamedUnaryHandler< + ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::xtcp_treatment::v1::GetDesiredStateRequest, ::xtcp_treatment::v1::GetDesiredStateResponse>* streamer) { + return this->StreamedGetDesiredState(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_GetDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status GetDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::GetDesiredStateRequest* /*request*/, ::xtcp_treatment::v1::GetDesiredStateResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedGetDesiredState(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::xtcp_treatment::v1::GetDesiredStateRequest,::xtcp_treatment::v1::GetDesiredStateResponse>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_CheckIn > StreamedUnaryService; + template + class WithSplitStreamingMethod_WatchDesiredState : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithSplitStreamingMethod_WatchDesiredState() { + ::grpc::Service::MarkMethodStreamed(2, + new ::grpc::internal::SplitServerStreamingHandler< + ::xtcp_treatment::v1::WatchDesiredStateRequest, ::xtcp_treatment::v1::WatchDesiredStateResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerSplitStreamer< + ::xtcp_treatment::v1::WatchDesiredStateRequest, ::xtcp_treatment::v1::WatchDesiredStateResponse>* streamer) { + return this->StreamedWatchDesiredState(context, + streamer); + })); + } + ~WithSplitStreamingMethod_WatchDesiredState() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status WatchDesiredState(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::WatchDesiredStateRequest* /*request*/, ::grpc::ServerWriter< ::xtcp_treatment::v1::WatchDesiredStateResponse>* /*writer*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with split streamed + virtual ::grpc::Status StreamedWatchDesiredState(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::xtcp_treatment::v1::WatchDesiredStateRequest,::xtcp_treatment::v1::WatchDesiredStateResponse>* server_split_streamer) = 0; + }; + typedef WithSplitStreamingMethod_WatchDesiredState SplitStreamedService; + typedef WithStreamedUnaryMethod_CheckIn > > StreamedService; +}; + +} // namespace v1 +} // namespace xtcp_treatment + + +#include +#endif // GRPC_xtcp_5ftreatment_2fv1_2fagent_2eproto__INCLUDED diff --git a/gen/cpp/xtcp_treatment/v1/agent.pb.cc b/gen/cpp/xtcp_treatment/v1/agent.pb.cc new file mode 100644 index 000000000..61f3a1def --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/agent.pb.cc @@ -0,0 +1,2576 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment/v1/agent.proto +// Protobuf C++ Version: 7.36.2 + +#include "xtcp_treatment/v1/agent.pb.h" + +#include +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/internal_visibility.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; +#ifdef PROTOBUF_MESSAGE_GLOBALS +namespace { +PROTOBUF_CONSTINIT ::google::protobuf::internal::ReflectionData + file_reflection_data[] = { + // ::xtcp_treatment::v1::CheckInRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::CheckInResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::GetDesiredStateRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::GetDesiredStateResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::WatchDesiredStateRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::WatchDesiredStateResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, /* tracker*/ nullptr,}, +}; +} // namespace +#endif +namespace xtcp_treatment { +namespace v1 { +class WatchDesiredStateResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(WatchDesiredStateResponse, _impl_._has_bits_); +}; + +constexpr WatchDesiredStateResponse::ParseTableT_ WatchDesiredStateResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(WatchDesiredStateResponse, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967294, // skipmap + offsetof(ParseTableT_, field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::WatchDesiredStateResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint64 revision = 1 [json_name = "revision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(WatchDesiredStateResponse, _impl_.revision_), 0>(), + {8, 0, 0, + PROTOBUF_FIELD_OFFSET(WatchDesiredStateResponse, _impl_.revision_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint64 revision = 1 [json_name = "revision"]; + {PROTOBUF_FIELD_OFFSET(WatchDesiredStateResponse, _impl_.revision_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + }}, + // no aux_entries + {{ + }}, + }; +} + + +inline constexpr WatchDesiredStateResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : revision_{::uint64_t{0u}} {} + +template +constexpr WatchDesiredStateResponse::WatchDesiredStateResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL WatchDesiredStateResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) WatchDesiredStateResponse(arena); +} +constexpr auto WatchDesiredStateResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(WatchDesiredStateResponse), alignof(WatchDesiredStateResponse)); +} +constexpr auto WatchDesiredStateResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &WatchDesiredStateResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &WatchDesiredStateResponse::SharedDtor, + Super_::GetClearImpl(), &WatchDesiredStateResponse::ByteSizeLong, + &WatchDesiredStateResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(WatchDesiredStateResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[5], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct WatchDesiredStateResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr WatchDesiredStateResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + WatchDesiredStateResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(WatchDesiredStateResponse::InternalGenerateClassData_( + _default, &WatchDesiredStateResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~WatchDesiredStateResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) WatchDesiredStateResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(WatchDesiredStateResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST WatchDesiredStateResponseGlobalsTypeInternal WatchDesiredStateResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* WatchDesiredStateResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return WatchDesiredStateResponse_globals_.GetClassData(); +#else + return WatchDesiredStateResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class WatchDesiredStateRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequest, _impl_._has_bits_); +}; + +constexpr WatchDesiredStateRequest::ParseTableT_ WatchDesiredStateRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequest, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967292, // skipmap + offsetof(ParseTableT_, field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::WatchDesiredStateRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint64 after_revision = 2 [json_name = "afterRevision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(WatchDesiredStateRequest, _impl_.after_revision_), 1>(), + {16, 1, 0, + PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequest, _impl_.after_revision_)}}, + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequest, _impl_.agent_id_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequest, _impl_.agent_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint64 after_revision = 2 [json_name = "afterRevision"]; + {PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequest, _impl_.after_revision_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + }}, + // no aux_entries + {{ + "\52\10\0\0\0\0\0\0" + "xtcp_treatment.v1.WatchDesiredStateRequest" + "agent_id" + }}, + }; +} + + +inline constexpr WatchDesiredStateRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + after_revision_{::uint64_t{0u}} {} + +template +constexpr WatchDesiredStateRequest::WatchDesiredStateRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL WatchDesiredStateRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) WatchDesiredStateRequest(arena); +} +constexpr auto WatchDesiredStateRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(WatchDesiredStateRequest), alignof(WatchDesiredStateRequest)); +} +constexpr auto WatchDesiredStateRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &WatchDesiredStateRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &WatchDesiredStateRequest::SharedDtor, + Super_::GetClearImpl(), &WatchDesiredStateRequest::ByteSizeLong, + &WatchDesiredStateRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[4], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct WatchDesiredStateRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr WatchDesiredStateRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + WatchDesiredStateRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(WatchDesiredStateRequest::InternalGenerateClassData_( + _default, &WatchDesiredStateRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~WatchDesiredStateRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) WatchDesiredStateRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(WatchDesiredStateRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST WatchDesiredStateRequestGlobalsTypeInternal WatchDesiredStateRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* WatchDesiredStateRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return WatchDesiredStateRequest_globals_.GetClassData(); +#else + return WatchDesiredStateRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class GetDesiredStateRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(GetDesiredStateRequest, _impl_._has_bits_); +}; + +constexpr GetDesiredStateRequest::ParseTableT_ GetDesiredStateRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(GetDesiredStateRequest, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967294, // skipmap + offsetof(ParseTableT_, field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::GetDesiredStateRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(GetDesiredStateRequest, _impl_.agent_id_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(GetDesiredStateRequest, _impl_.agent_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + "\50\10\0\0\0\0\0\0" + "xtcp_treatment.v1.GetDesiredStateRequest" + "agent_id" + }}, + }; +} + + +inline constexpr GetDesiredStateRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()) {} + +template +constexpr GetDesiredStateRequest::GetDesiredStateRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL GetDesiredStateRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) GetDesiredStateRequest(arena); +} +constexpr auto GetDesiredStateRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(GetDesiredStateRequest), alignof(GetDesiredStateRequest)); +} +constexpr auto GetDesiredStateRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &GetDesiredStateRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &GetDesiredStateRequest::SharedDtor, + Super_::GetClearImpl(), &GetDesiredStateRequest::ByteSizeLong, + &GetDesiredStateRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(GetDesiredStateRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[2], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct GetDesiredStateRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr GetDesiredStateRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + GetDesiredStateRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(GetDesiredStateRequest::InternalGenerateClassData_( + _default, &GetDesiredStateRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~GetDesiredStateRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) GetDesiredStateRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(GetDesiredStateRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST GetDesiredStateRequestGlobalsTypeInternal GetDesiredStateRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* GetDesiredStateRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return GetDesiredStateRequest_globals_.GetClassData(); +#else + return GetDesiredStateRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class GetDesiredStateResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(GetDesiredStateResponse, _impl_._has_bits_); +}; + +constexpr GetDesiredStateResponse::ParseTableT_ GetDesiredStateResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(GetDesiredStateResponse, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967294, // skipmap + offsetof(ParseTableT_, field_entries), + 1, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::GetDesiredStateResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(GetDesiredStateResponse, _impl_.desired_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + {PROTOBUF_FIELD_OFFSET(GetDesiredStateResponse, _impl_.desired_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::DesiredState>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::DesiredState_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr GetDesiredStateResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : desired_{nullptr} {} + +template +constexpr GetDesiredStateResponse::GetDesiredStateResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL GetDesiredStateResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) GetDesiredStateResponse(arena); +} +constexpr auto GetDesiredStateResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(GetDesiredStateResponse), alignof(GetDesiredStateResponse)); +} +constexpr auto GetDesiredStateResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &GetDesiredStateResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &GetDesiredStateResponse::SharedDtor, + Super_::GetClearImpl(), &GetDesiredStateResponse::ByteSizeLong, + &GetDesiredStateResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(GetDesiredStateResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[3], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct GetDesiredStateResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr GetDesiredStateResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + GetDesiredStateResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(GetDesiredStateResponse::InternalGenerateClassData_( + _default, &GetDesiredStateResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~GetDesiredStateResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) GetDesiredStateResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(GetDesiredStateResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST GetDesiredStateResponseGlobalsTypeInternal GetDesiredStateResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* GetDesiredStateResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return GetDesiredStateResponse_globals_.GetClassData(); +#else + return GetDesiredStateResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class CheckInResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(CheckInResponse, _impl_._has_bits_); +}; + +constexpr CheckInResponse::ParseTableT_ CheckInResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(CheckInResponse, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967294, // skipmap + offsetof(ParseTableT_, field_entries), + 1, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::CheckInResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(CheckInResponse, _impl_.desired_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + {PROTOBUF_FIELD_OFFSET(CheckInResponse, _impl_.desired_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::DesiredState>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::DesiredState_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr CheckInResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : desired_{nullptr} {} + +template +constexpr CheckInResponse::CheckInResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL CheckInResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) CheckInResponse(arena); +} +constexpr auto CheckInResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(CheckInResponse), alignof(CheckInResponse)); +} +constexpr auto CheckInResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &CheckInResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &CheckInResponse::SharedDtor, + Super_::GetClearImpl(), &CheckInResponse::ByteSizeLong, + &CheckInResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(CheckInResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[1], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct CheckInResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr CheckInResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + CheckInResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(CheckInResponse::InternalGenerateClassData_( + _default, &CheckInResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~CheckInResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) CheckInResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(CheckInResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST CheckInResponseGlobalsTypeInternal CheckInResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* CheckInResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return CheckInResponse_globals_.GetClassData(); +#else + return CheckInResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class CheckInRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_._has_bits_); +}; + +constexpr CheckInRequest::ParseTableT_ CheckInRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_._has_bits_), + 0, // no _extensions_ + 6, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967232, // skipmap + offsetof(ParseTableT_, field_entries), + 6, // num_field_entries + 2, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::CheckInRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 1, 0, + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.agent_id_)}}, + // string location = 2 [json_name = "location", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {18, 2, 0, + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.location_)}}, + // .xtcp_treatment.v1.Capabilities capabilities = 3 [json_name = "capabilities", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {26, 3, 0, + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.capabilities_)}}, + // uint64 desired_revision = 4 [json_name = "desiredRevision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(CheckInRequest, _impl_.desired_revision_), 4>(), + {32, 4, 0, + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.desired_revision_)}}, + // repeated .xtcp_treatment.v1.ApplicationRecord records = 5 [json_name = "records", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtR1, + {42, 0, 1, + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.records_)}}, + // bool locally_suspended = 6 [json_name = "locallySuspended"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {48, 5, 0, + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.locally_suspended_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.agent_id_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string location = 2 [json_name = "location", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.location_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment.v1.Capabilities capabilities = 3 [json_name = "capabilities", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.capabilities_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint64 desired_revision = 4 [json_name = "desiredRevision"]; + {PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.desired_revision_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // repeated .xtcp_treatment.v1.ApplicationRecord records = 5 [json_name = "records", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.records_), _Internal::kHasBitsOffset + 0, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool locally_suspended = 6 [json_name = "locallySuspended"]; + {PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.locally_suspended_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Capabilities>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Capabilities_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ApplicationRecord>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::ApplicationRecord_globals_}, + #endif + }}, + {{ + "\40\10\10\0\0\0\0\0" + "xtcp_treatment.v1.CheckInRequest" + "agent_id" + "location" + }}, + }; +} + + +inline constexpr CheckInRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : records_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::CheckInRequest, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.records_)>() + } + , + agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + location_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + capabilities_{nullptr}, + desired_revision_{::uint64_t{0u}}, + locally_suspended_{false} {} + +template +constexpr CheckInRequest::CheckInRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL CheckInRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) CheckInRequest(arena); +} +constexpr auto CheckInRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(CheckInRequest), alignof(CheckInRequest)); +} +constexpr auto CheckInRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &CheckInRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &CheckInRequest::SharedDtor, + Super_::GetClearImpl(), &CheckInRequest::ByteSizeLong, + &CheckInRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[0], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct CheckInRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr CheckInRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + CheckInRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(CheckInRequest::InternalGenerateClassData_( + _default, &CheckInRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~CheckInRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) CheckInRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(CheckInRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST CheckInRequestGlobalsTypeInternal CheckInRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* CheckInRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return CheckInRequest_globals_.GetClassData(); +#else + return CheckInRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +} // namespace v1 +} // namespace xtcp_treatment +static constexpr const ::_pb::EnumDescriptor* PROTOBUF_NONNULL* PROTOBUF_NULLABLE + file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2fagent_2eproto = nullptr; +static constexpr const ::_pb::ServiceDescriptor* PROTOBUF_NONNULL* PROTOBUF_NULLABLE + file_level_service_descriptors_xtcp_5ftreatment_2fv1_2fagent_2eproto = nullptr; +const ::uint32_t + TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.agent_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.capabilities_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.desired_revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.records_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.locally_suspended_), + 1, + 2, + 3, + 4, + 0, + 5, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInResponse, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInResponse, _impl_.desired_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::GetDesiredStateRequest, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::GetDesiredStateRequest, _impl_.agent_id_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::GetDesiredStateResponse, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::GetDesiredStateResponse, _impl_.desired_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::WatchDesiredStateRequest, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::WatchDesiredStateRequest, _impl_.agent_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::WatchDesiredStateRequest, _impl_.after_revision_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::WatchDesiredStateResponse, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::WatchDesiredStateResponse, _impl_.revision_), + 0, +}; + +static const ::_pbi::MigrationSchema + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + {0, sizeof(::xtcp_treatment::v1::CheckInRequest)}, + {15, sizeof(::xtcp_treatment::v1::CheckInResponse)}, + {20, sizeof(::xtcp_treatment::v1::GetDesiredStateRequest)}, + {25, sizeof(::xtcp_treatment::v1::GetDesiredStateResponse)}, + {30, sizeof(::xtcp_treatment::v1::WatchDesiredStateRequest)}, + {37, sizeof(::xtcp_treatment::v1::WatchDesiredStateResponse)}, +}; +static const ::_pbi::MessageGlobalsBase* PROTOBUF_NONNULL const + file_message_globals[] = { + &::xtcp_treatment::v1::CheckInRequest_globals_, + &::xtcp_treatment::v1::CheckInResponse_globals_, + &::xtcp_treatment::v1::GetDesiredStateRequest_globals_, + &::xtcp_treatment::v1::GetDesiredStateResponse_globals_, + &::xtcp_treatment::v1::WatchDesiredStateRequest_globals_, + &::xtcp_treatment::v1::WatchDesiredStateResponse_globals_, +}; +const char descriptor_table_protodef_xtcp_5ftreatment_2fv1_2fagent_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + "\n\035xtcp_treatment/v1/agent.proto\022\021xtcp_tr" + "eatment.v1\032\033buf/validate/validate.proto\032" + "!xtcp_treatment/v1/treatment.proto\"\215\003\n\016C" + "heckInRequest\022D\n\010agent_id\030\001 \001(\tB)\272H&r$2\"" + "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\007agen" + "tId\022E\n\010location\030\002 \001(\tB)\272H&r$2\"^[a-zA-Z0-" + "9][a-zA-Z0-9_.-]{0,127}$R\010location\022K\n\014ca" + "pabilities\030\003 \001(\0132\037.xtcp_treatment.v1.Cap" + "abilitiesB\006\272H\003\310\001\001R\014capabilities\022)\n\020desir" + "ed_revision\030\004 \001(\004R\017desiredRevision\022I\n\007re" + "cords\030\005 \003(\0132$.xtcp_treatment.v1.Applicat" + "ionRecordB\t\272H\006\222\001\003\020\200@R\007records\022+\n\021locally" + "_suspended\030\006 \001(\010R\020locallySuspended\"L\n\017Ch" + "eckInResponse\0229\n\007desired\030\001 \001(\0132\037.xtcp_tr" + "eatment.v1.DesiredStateR\007desired\"^\n\026GetD" + "esiredStateRequest\022D\n\010agent_id\030\001 \001(\tB)\272H" + "&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R" + "\007agentId\"T\n\027GetDesiredStateResponse\0229\n\007d" + "esired\030\001 \001(\0132\037.xtcp_treatment.v1.Desired" + "StateR\007desired\"\207\001\n\030WatchDesiredStateRequ" + "est\022D\n\010agent_id\030\001 \001(\tB)\272H&r$2\"^[a-zA-Z0-" + "9][a-zA-Z0-9_.-]{0,127}$R\007agentId\022%\n\016aft" + "er_revision\030\002 \001(\004R\rafterRevision\"7\n\031Watc" + "hDesiredStateResponse\022\032\n\010revision\030\001 \001(\004R" + "\010revision2\325\002\n\023AgentControlService\022V\n\007Che" + "ckIn\022!.xtcp_treatment.v1.CheckInRequest\032" + "\".xtcp_treatment.v1.CheckInResponse\"\004\320\363\030" + "\001\022n\n\017GetDesiredState\022).xtcp_treatment.v1" + ".GetDesiredStateRequest\032*.xtcp_treatment" + ".v1.GetDesiredStateResponse\"\004\320\363\030\001\022v\n\021Wat" + "chDesiredState\022+.xtcp_treatment.v1.Watch" + "DesiredStateRequest\032,.xtcp_treatment.v1." + "WatchDesiredStateResponse\"\004\320\363\030\0010\001B\274\001\n\025co" + "m.xtcp_treatment.v1B\nAgentProtoP\001Z6githu" + "b.com/randomizedcoder/xtcp2/gen/go/xtcp_" + "treatment\242\002\003XXX\252\002\020XtcpTreatment.V1\312\002\020Xtc" + "pTreatment\\V1\342\002\034XtcpTreatment\\V1\\GPBMeta" + "data\352\002\021XtcpTreatment::V1b\006proto3" +}; +static const ::_pbi::DescriptorTable* PROTOBUF_NONNULL const + descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto_deps[2] = { + &::descriptor_table_buf_2fvalidate_2fvalidate_2eproto, + &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, +}; +static ::absl::once_flag descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto_once; +PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto = { + false, + false, + 1512, + descriptor_table_protodef_xtcp_5ftreatment_2fv1_2fagent_2eproto, + "xtcp_treatment/v1/agent.proto", + &descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto_once, + descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto_deps, + 2, + 6, + schemas, + file_message_globals, + TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto::offsets, + file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2fagent_2eproto, + file_level_service_descriptors_xtcp_5ftreatment_2fv1_2fagent_2eproto, +}; +namespace xtcp_treatment { +namespace v1 { +// =================================================================== + +void CheckInRequest::clear_capabilities() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.capabilities_ != nullptr) _impl_.capabilities_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +void CheckInRequest::clear_records() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.records_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +CheckInRequest::CheckInRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, CheckInRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.CheckInRequest) +} +PROTOBUF_NDEBUG_INLINE CheckInRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::CheckInRequest& from_msg) + : _has_bits_{from._has_bits_}, + records_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::CheckInRequest, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.records_)>() + , arena, from.records_ + } + , + agent_id_(arena, from.agent_id_), + location_(arena, from.location_) {} + +CheckInRequest::CheckInRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const CheckInRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, CheckInRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + CheckInRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.capabilities_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.capabilities_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, desired_revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, desired_revision_), + offsetof(Impl_, locally_suspended_) - + offsetof(Impl_, desired_revision_) + + sizeof(Impl_::locally_suspended_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.CheckInRequest) +} +PROTOBUF_NDEBUG_INLINE CheckInRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : records_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::CheckInRequest, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::CheckInRequest, _impl_.records_)>() + } + , + agent_id_(arena), + location_(arena) {} + +inline void CheckInRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, capabilities_), + 0, + offsetof(Impl_, locally_suspended_) - + offsetof(Impl_, capabilities_) + + sizeof(Impl_::locally_suspended_)); +} +CheckInRequest::~CheckInRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.CheckInRequest) + SharedDtor(*this); +} +inline void CheckInRequest::SharedDtor(MessageLite& self) { + CheckInRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.agent_id_.Destroy(); + this_._impl_.location_.Destroy(); + delete this_._impl_.capabilities_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull CheckInRequest_class_data_ = + CheckInRequest::InternalGenerateClassData_(CheckInRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +CheckInRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CheckInRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(CheckInRequest_class_data_.tc_table); + return CheckInRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +CheckInRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CheckInRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&CheckInRequest_globals_)); + return CheckInRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const CheckInRequest::ParseTableT_ + CheckInRequest::_table_ = + CheckInRequest::InternalGenerateParseTable_(CheckInRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void CheckInRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.CheckInRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.records_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.location_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.capabilities_ != nullptr); + this_._impl_.capabilities_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000030U)) { + ::memset(&this_._impl_.desired_revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.locally_suspended_) - + reinterpret_cast(&this_._impl_.desired_revision_)) + + sizeof(_impl_.locally_suspended_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL CheckInRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const CheckInRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL CheckInRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const CheckInRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.CheckInRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.CheckInRequest.agent_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string location = 2 [json_name = "location", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_location().empty()) { + const ::std::string& _s = this_._internal_location(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.CheckInRequest.location"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + // .xtcp_treatment.v1.Capabilities capabilities = 3 [json_name = "capabilities", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.capabilities_, this_._impl_.capabilities_->GetCachedSize(), target, + stream); + } + + // uint64 desired_revision = 4 [json_name = "desiredRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_desired_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 4, this_._internal_desired_revision(), target); + } + } + + // repeated .xtcp_treatment.v1.ApplicationRecord records = 5 [json_name = "records", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_records_size()); + i < n; i++) { + const auto& repfield = this_._internal_records().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // bool locally_suspended = 6 [json_name = "locallySuspended"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_locally_suspended() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_locally_suspended(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.CheckInRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t CheckInRequest::ByteSizeLong(const MessageLite& base) { + const CheckInRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t CheckInRequest::ByteSizeLong() const { + const CheckInRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.CheckInRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + // repeated .xtcp_treatment.v1.ApplicationRecord records = 5 [json_name = "records", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_records_size(); + for (const auto& msg : this_._internal_records()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + // string location = 2 [json_name = "location", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_location().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_location()); + } + } + // .xtcp_treatment.v1.Capabilities capabilities = 3 [json_name = "capabilities", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.capabilities_); + } + // uint64 desired_revision = 4 [json_name = "desiredRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_desired_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_desired_revision()); + } + } + // bool locally_suspended = 6 [json_name = "locallySuspended"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_locally_suspended() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void CheckInRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.CheckInRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_records()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_records()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_location().empty()) { + _this->_internal_set_location(from._internal_location()); + } else { + if (_this->_impl_.location_.IsDefault()) { + _this->_internal_set_location(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.capabilities_ != nullptr); + if (_this->_impl_.capabilities_ == nullptr) { + _this->_impl_.capabilities_ = Super_::CopyConstruct(arena, *from._impl_.capabilities_); + } else { + _this->_impl_.capabilities_->MergeFrom(*from._impl_.capabilities_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_desired_revision() != 0) { + _this->_impl_.desired_revision_ = from._impl_.desired_revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (from._internal_locally_suspended() != 0) { + _this->_impl_.locally_suspended_ = from._impl_.locally_suspended_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void CheckInRequest::CopyFrom(const CheckInRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.CheckInRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void CheckInRequest::InternalSwap(CheckInRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.records_.InternalSwap(&other->_impl_.records_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.location_, &other->_impl_.location_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.locally_suspended_) + + sizeof(CheckInRequest::_impl_.locally_suspended_) + - PROTOBUF_FIELD_OFFSET(CheckInRequest, _impl_.capabilities_)>( + reinterpret_cast(&_impl_.capabilities_), + reinterpret_cast(&other->_impl_.capabilities_)); +} + +::google::protobuf::Metadata CheckInRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void CheckInResponse::clear_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ != nullptr) _impl_.desired_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +CheckInResponse::CheckInResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, CheckInResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.CheckInResponse) +} +PROTOBUF_NDEBUG_INLINE CheckInResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::CheckInResponse& from_msg) + : _has_bits_{from._has_bits_} {} + +CheckInResponse::CheckInResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const CheckInResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, CheckInResponse_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + CheckInResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.desired_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? Super_::CopyConstruct(arena, *from._impl_.desired_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.CheckInResponse) +} +PROTOBUF_NDEBUG_INLINE CheckInResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void CheckInResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.desired_ = {}; +} +CheckInResponse::~CheckInResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.CheckInResponse) + SharedDtor(*this); +} +inline void CheckInResponse::SharedDtor(MessageLite& self) { + CheckInResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.desired_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull CheckInResponse_class_data_ = + CheckInResponse::InternalGenerateClassData_(CheckInResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +CheckInResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CheckInResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(CheckInResponse_class_data_.tc_table); + return CheckInResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +CheckInResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CheckInResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&CheckInResponse_globals_)); + return CheckInResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const CheckInResponse::ParseTableT_ + CheckInResponse::_table_ = + CheckInResponse::InternalGenerateParseTable_(CheckInResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void CheckInResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.CheckInResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(this_._impl_.desired_ != nullptr); + this_._impl_.desired_->Clear(); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL CheckInResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const CheckInResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL CheckInResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const CheckInResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.CheckInResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.desired_, this_._impl_.desired_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.CheckInResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t CheckInResponse::ByteSizeLong(const MessageLite& base) { + const CheckInResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t CheckInResponse::ByteSizeLong() const { + const CheckInResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.CheckInResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + { + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.desired_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void CheckInResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.CheckInResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.desired_ != nullptr); + if (_this->_impl_.desired_ == nullptr) { + _this->_impl_.desired_ = Super_::CopyConstruct(arena, *from._impl_.desired_); + } else { + _this->_impl_.desired_->MergeFrom(*from._impl_.desired_); + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void CheckInResponse::CopyFrom(const CheckInResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.CheckInResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void CheckInResponse::InternalSwap(CheckInResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.desired_, other->_impl_.desired_); +} + +::google::protobuf::Metadata CheckInResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +GetDesiredStateRequest::GetDesiredStateRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, GetDesiredStateRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.GetDesiredStateRequest) +} +PROTOBUF_NDEBUG_INLINE GetDesiredStateRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::GetDesiredStateRequest& from_msg) + : _has_bits_{from._has_bits_}, + agent_id_(arena, from.agent_id_) {} + +GetDesiredStateRequest::GetDesiredStateRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const GetDesiredStateRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, GetDesiredStateRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + GetDesiredStateRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.GetDesiredStateRequest) +} +PROTOBUF_NDEBUG_INLINE GetDesiredStateRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : agent_id_(arena) {} + +inline void GetDesiredStateRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +GetDesiredStateRequest::~GetDesiredStateRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.GetDesiredStateRequest) + SharedDtor(*this); +} +inline void GetDesiredStateRequest::SharedDtor(MessageLite& self) { + GetDesiredStateRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.agent_id_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull GetDesiredStateRequest_class_data_ = + GetDesiredStateRequest::InternalGenerateClassData_(GetDesiredStateRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +GetDesiredStateRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&GetDesiredStateRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(GetDesiredStateRequest_class_data_.tc_table); + return GetDesiredStateRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +GetDesiredStateRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&GetDesiredStateRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&GetDesiredStateRequest_globals_)); + return GetDesiredStateRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const GetDesiredStateRequest::ParseTableT_ + GetDesiredStateRequest::_table_ = + GetDesiredStateRequest::InternalGenerateParseTable_(GetDesiredStateRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void GetDesiredStateRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.GetDesiredStateRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL GetDesiredStateRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const GetDesiredStateRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL GetDesiredStateRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const GetDesiredStateRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.GetDesiredStateRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.GetDesiredStateRequest.agent_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.GetDesiredStateRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t GetDesiredStateRequest::ByteSizeLong(const MessageLite& base) { + const GetDesiredStateRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t GetDesiredStateRequest::ByteSizeLong() const { + const GetDesiredStateRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.GetDesiredStateRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + { + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void GetDesiredStateRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.GetDesiredStateRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void GetDesiredStateRequest::CopyFrom(const GetDesiredStateRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.GetDesiredStateRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void GetDesiredStateRequest::InternalSwap(GetDesiredStateRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); +} + +::google::protobuf::Metadata GetDesiredStateRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void GetDesiredStateResponse::clear_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ != nullptr) _impl_.desired_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +GetDesiredStateResponse::GetDesiredStateResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, GetDesiredStateResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.GetDesiredStateResponse) +} +PROTOBUF_NDEBUG_INLINE GetDesiredStateResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::GetDesiredStateResponse& from_msg) + : _has_bits_{from._has_bits_} {} + +GetDesiredStateResponse::GetDesiredStateResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const GetDesiredStateResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, GetDesiredStateResponse_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + GetDesiredStateResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.desired_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? Super_::CopyConstruct(arena, *from._impl_.desired_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.GetDesiredStateResponse) +} +PROTOBUF_NDEBUG_INLINE GetDesiredStateResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void GetDesiredStateResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.desired_ = {}; +} +GetDesiredStateResponse::~GetDesiredStateResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.GetDesiredStateResponse) + SharedDtor(*this); +} +inline void GetDesiredStateResponse::SharedDtor(MessageLite& self) { + GetDesiredStateResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.desired_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull GetDesiredStateResponse_class_data_ = + GetDesiredStateResponse::InternalGenerateClassData_(GetDesiredStateResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +GetDesiredStateResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&GetDesiredStateResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(GetDesiredStateResponse_class_data_.tc_table); + return GetDesiredStateResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +GetDesiredStateResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&GetDesiredStateResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&GetDesiredStateResponse_globals_)); + return GetDesiredStateResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const GetDesiredStateResponse::ParseTableT_ + GetDesiredStateResponse::_table_ = + GetDesiredStateResponse::InternalGenerateParseTable_(GetDesiredStateResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void GetDesiredStateResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.GetDesiredStateResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(this_._impl_.desired_ != nullptr); + this_._impl_.desired_->Clear(); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL GetDesiredStateResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const GetDesiredStateResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL GetDesiredStateResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const GetDesiredStateResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.GetDesiredStateResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.desired_, this_._impl_.desired_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.GetDesiredStateResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t GetDesiredStateResponse::ByteSizeLong(const MessageLite& base) { + const GetDesiredStateResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t GetDesiredStateResponse::ByteSizeLong() const { + const GetDesiredStateResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.GetDesiredStateResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + { + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.desired_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void GetDesiredStateResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.GetDesiredStateResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.desired_ != nullptr); + if (_this->_impl_.desired_ == nullptr) { + _this->_impl_.desired_ = Super_::CopyConstruct(arena, *from._impl_.desired_); + } else { + _this->_impl_.desired_->MergeFrom(*from._impl_.desired_); + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void GetDesiredStateResponse::CopyFrom(const GetDesiredStateResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.GetDesiredStateResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void GetDesiredStateResponse::InternalSwap(GetDesiredStateResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.desired_, other->_impl_.desired_); +} + +::google::protobuf::Metadata GetDesiredStateResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +WatchDesiredStateRequest::WatchDesiredStateRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, WatchDesiredStateRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.WatchDesiredStateRequest) +} +PROTOBUF_NDEBUG_INLINE WatchDesiredStateRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::WatchDesiredStateRequest& from_msg) + : _has_bits_{from._has_bits_}, + agent_id_(arena, from.agent_id_) {} + +WatchDesiredStateRequest::WatchDesiredStateRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const WatchDesiredStateRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, WatchDesiredStateRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + WatchDesiredStateRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.after_revision_ = from._impl_.after_revision_; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.WatchDesiredStateRequest) +} +PROTOBUF_NDEBUG_INLINE WatchDesiredStateRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : agent_id_(arena) {} + +inline void WatchDesiredStateRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.after_revision_ = {}; +} +WatchDesiredStateRequest::~WatchDesiredStateRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.WatchDesiredStateRequest) + SharedDtor(*this); +} +inline void WatchDesiredStateRequest::SharedDtor(MessageLite& self) { + WatchDesiredStateRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.agent_id_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull WatchDesiredStateRequest_class_data_ = + WatchDesiredStateRequest::InternalGenerateClassData_(WatchDesiredStateRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +WatchDesiredStateRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&WatchDesiredStateRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(WatchDesiredStateRequest_class_data_.tc_table); + return WatchDesiredStateRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +WatchDesiredStateRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&WatchDesiredStateRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&WatchDesiredStateRequest_globals_)); + return WatchDesiredStateRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const WatchDesiredStateRequest::ParseTableT_ + WatchDesiredStateRequest::_table_ = + WatchDesiredStateRequest::InternalGenerateParseTable_(WatchDesiredStateRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void WatchDesiredStateRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.WatchDesiredStateRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + this_._impl_.after_revision_ = ::uint64_t{0u}; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL WatchDesiredStateRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const WatchDesiredStateRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL WatchDesiredStateRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const WatchDesiredStateRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.WatchDesiredStateRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.WatchDesiredStateRequest.agent_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint64 after_revision = 2 [json_name = "afterRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_after_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_after_revision(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.WatchDesiredStateRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t WatchDesiredStateRequest::ByteSizeLong(const MessageLite& base) { + const WatchDesiredStateRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t WatchDesiredStateRequest::ByteSizeLong() const { + const WatchDesiredStateRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.WatchDesiredStateRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + // uint64 after_revision = 2 [json_name = "afterRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_after_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_after_revision()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void WatchDesiredStateRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.WatchDesiredStateRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (from._internal_after_revision() != 0) { + _this->_impl_.after_revision_ = from._impl_.after_revision_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void WatchDesiredStateRequest::CopyFrom(const WatchDesiredStateRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.WatchDesiredStateRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void WatchDesiredStateRequest::InternalSwap(WatchDesiredStateRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); + swap(_impl_.after_revision_, other->_impl_.after_revision_); +} + +::google::protobuf::Metadata WatchDesiredStateRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +WatchDesiredStateResponse::WatchDesiredStateResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, WatchDesiredStateResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.WatchDesiredStateResponse) +} +WatchDesiredStateResponse::WatchDesiredStateResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const WatchDesiredStateResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, WatchDesiredStateResponse_get_class_data()), +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE WatchDesiredStateResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void WatchDesiredStateResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.revision_ = {}; +} +WatchDesiredStateResponse::~WatchDesiredStateResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.WatchDesiredStateResponse) + SharedDtor(*this); +} +inline void WatchDesiredStateResponse::SharedDtor(MessageLite& self) { + WatchDesiredStateResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull WatchDesiredStateResponse_class_data_ = + WatchDesiredStateResponse::InternalGenerateClassData_(WatchDesiredStateResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +WatchDesiredStateResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&WatchDesiredStateResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(WatchDesiredStateResponse_class_data_.tc_table); + return WatchDesiredStateResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +WatchDesiredStateResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&WatchDesiredStateResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&WatchDesiredStateResponse_globals_)); + return WatchDesiredStateResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const WatchDesiredStateResponse::ParseTableT_ + WatchDesiredStateResponse::_table_ = + WatchDesiredStateResponse::InternalGenerateParseTable_(WatchDesiredStateResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void WatchDesiredStateResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.WatchDesiredStateResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + this_._impl_.revision_ = ::uint64_t{0u}; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL WatchDesiredStateResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const WatchDesiredStateResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL WatchDesiredStateResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const WatchDesiredStateResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.WatchDesiredStateResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // uint64 revision = 1 [json_name = "revision"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (this_._internal_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 1, this_._internal_revision(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.WatchDesiredStateResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t WatchDesiredStateResponse::ByteSizeLong(const MessageLite& base) { + const WatchDesiredStateResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t WatchDesiredStateResponse::ByteSizeLong() const { + const WatchDesiredStateResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.WatchDesiredStateResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + { + // uint64 revision = 1 [json_name = "revision"]; + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (this_._internal_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_revision()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void WatchDesiredStateResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.WatchDesiredStateResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (from._internal_revision() != 0) { + _this->_impl_.revision_ = from._impl_.revision_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void WatchDesiredStateResponse::CopyFrom(const WatchDesiredStateResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.WatchDesiredStateResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void WatchDesiredStateResponse::InternalSwap(WatchDesiredStateResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.revision_, other->_impl_.revision_); +} + +::google::protobuf::Metadata WatchDesiredStateResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ [[maybe_unused]] = + (::_pbi::AddDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto), + ::std::false_type{}); +#include "google/protobuf/port_undef.inc" diff --git a/gen/cpp/xtcp_treatment/v1/agent.pb.h b/gen/cpp/xtcp_treatment/v1/agent.pb.h new file mode 100644 index 000000000..0bdc0ce88 --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/agent.pb.h @@ -0,0 +1,2167 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment/v1/agent.proto +// Protobuf C++ Version: 7.36.2 + +#ifndef xtcp_5ftreatment_2fv1_2fagent_2eproto_2epb_2eh +#define xtcp_5ftreatment_2fv1_2fagent_2eproto_2epb_2eh + +#include +#include +#include +#include + +// clang-format off +#include "google/protobuf/runtime_version.h" +#if PROTOBUF_VERSION != 7036002 +#error "Protobuf C++ gencode is built with an incompatible version of" +#error "Protobuf C++ headers/runtime. See" +#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" +#endif +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/unknown_field_set.h" +#include "buf/validate/validate.pb.h" +#include "xtcp_treatment/v1/treatment.pb.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_xtcp_5ftreatment_2fv1_2fagent_2eproto + +// Internal implementation detail -- do not use these members. +struct TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto { + static const ::uint32_t offsets[]; +}; +extern "C" { +extern const ::google::protobuf::internal::DescriptorTable descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto; +} // extern "C" +namespace xtcp_treatment { +namespace v1 { +class CheckInRequest; +struct CheckInRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern CheckInRequestGlobalsTypeInternal CheckInRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull CheckInRequest_class_data_; +#else +extern const CheckInRequestGlobalsTypeInternal CheckInRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class CheckInResponse; +struct CheckInResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern CheckInResponseGlobalsTypeInternal CheckInResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull CheckInResponse_class_data_; +#else +extern const CheckInResponseGlobalsTypeInternal CheckInResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class GetDesiredStateRequest; +struct GetDesiredStateRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern GetDesiredStateRequestGlobalsTypeInternal GetDesiredStateRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull GetDesiredStateRequest_class_data_; +#else +extern const GetDesiredStateRequestGlobalsTypeInternal GetDesiredStateRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class GetDesiredStateResponse; +struct GetDesiredStateResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern GetDesiredStateResponseGlobalsTypeInternal GetDesiredStateResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull GetDesiredStateResponse_class_data_; +#else +extern const GetDesiredStateResponseGlobalsTypeInternal GetDesiredStateResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class WatchDesiredStateRequest; +struct WatchDesiredStateRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern WatchDesiredStateRequestGlobalsTypeInternal WatchDesiredStateRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull WatchDesiredStateRequest_class_data_; +#else +extern const WatchDesiredStateRequestGlobalsTypeInternal WatchDesiredStateRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class WatchDesiredStateResponse; +struct WatchDesiredStateResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern WatchDesiredStateResponseGlobalsTypeInternal WatchDesiredStateResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull WatchDesiredStateResponse_class_data_; +#else +extern const WatchDesiredStateResponseGlobalsTypeInternal WatchDesiredStateResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +} // namespace v1 +} // namespace xtcp_treatment +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google + +namespace xtcp_treatment { +namespace v1 { + +// =================================================================== + + +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED WatchDesiredStateResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.WatchDesiredStateResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline WatchDesiredStateResponse() : WatchDesiredStateResponse(nullptr) {} + ~WatchDesiredStateResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(WatchDesiredStateResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(WatchDesiredStateResponse)); + } +#endif + + template + explicit constexpr WatchDesiredStateResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline WatchDesiredStateResponse(const WatchDesiredStateResponse& from) : WatchDesiredStateResponse(nullptr, from) {} + inline WatchDesiredStateResponse(WatchDesiredStateResponse&& from) noexcept : WatchDesiredStateResponse(nullptr, ::std::move(from)) {} + inline WatchDesiredStateResponse& operator=(const WatchDesiredStateResponse& from) { + CopyFrom(from); + return *this; + } + inline WatchDesiredStateResponse& operator=(WatchDesiredStateResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const WatchDesiredStateResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&WatchDesiredStateResponse_globals_); + } + static constexpr int kIndexInFileMessages = 5; + friend void swap(WatchDesiredStateResponse& a, WatchDesiredStateResponse& b) { a.Swap(&b); } + inline void Swap(WatchDesiredStateResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(WatchDesiredStateResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] WatchDesiredStateResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const WatchDesiredStateResponse& from); + using Super_::MergeFrom; + void MergeFrom(const WatchDesiredStateResponse& from) { WatchDesiredStateResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(WatchDesiredStateResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.WatchDesiredStateResponse"; } + + explicit WatchDesiredStateResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + WatchDesiredStateResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const WatchDesiredStateResponse& from); + WatchDesiredStateResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, WatchDesiredStateResponse&& from) noexcept + : WatchDesiredStateResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kRevisionFieldNumber = 1, + }; + // uint64 revision = 1 [json_name = "revision"]; + void clear_revision() ; + [[nodiscard]] ::uint64_t revision() const; + void set_revision(::uint64_t value); + + private: + ::uint64_t _internal_revision() const; + void _internal_set_revision(::uint64_t value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.WatchDesiredStateResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const WatchDesiredStateResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint64_t revision_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED WatchDesiredStateRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.WatchDesiredStateRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline WatchDesiredStateRequest() : WatchDesiredStateRequest(nullptr) {} + ~WatchDesiredStateRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(WatchDesiredStateRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(WatchDesiredStateRequest)); + } +#endif + + template + explicit constexpr WatchDesiredStateRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline WatchDesiredStateRequest(const WatchDesiredStateRequest& from) : WatchDesiredStateRequest(nullptr, from) {} + inline WatchDesiredStateRequest(WatchDesiredStateRequest&& from) noexcept : WatchDesiredStateRequest(nullptr, ::std::move(from)) {} + inline WatchDesiredStateRequest& operator=(const WatchDesiredStateRequest& from) { + CopyFrom(from); + return *this; + } + inline WatchDesiredStateRequest& operator=(WatchDesiredStateRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const WatchDesiredStateRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&WatchDesiredStateRequest_globals_); + } + static constexpr int kIndexInFileMessages = 4; + friend void swap(WatchDesiredStateRequest& a, WatchDesiredStateRequest& b) { a.Swap(&b); } + inline void Swap(WatchDesiredStateRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(WatchDesiredStateRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] WatchDesiredStateRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const WatchDesiredStateRequest& from); + using Super_::MergeFrom; + void MergeFrom(const WatchDesiredStateRequest& from) { WatchDesiredStateRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(WatchDesiredStateRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.WatchDesiredStateRequest"; } + + explicit WatchDesiredStateRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + WatchDesiredStateRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const WatchDesiredStateRequest& from); + WatchDesiredStateRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, WatchDesiredStateRequest&& from) noexcept + : WatchDesiredStateRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kAgentIdFieldNumber = 1, + kAfterRevisionFieldNumber = 2, + }; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // uint64 after_revision = 2 [json_name = "afterRevision"]; + void clear_after_revision() ; + [[nodiscard]] ::uint64_t after_revision() const; + void set_after_revision(::uint64_t value); + + private: + ::uint64_t _internal_after_revision() const; + void _internal_set_after_revision(::uint64_t value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.WatchDesiredStateRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<1, 2, + 0, 59, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const WatchDesiredStateRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + ::uint64_t after_revision_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED GetDesiredStateRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.GetDesiredStateRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline GetDesiredStateRequest() : GetDesiredStateRequest(nullptr) {} + ~GetDesiredStateRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(GetDesiredStateRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(GetDesiredStateRequest)); + } +#endif + + template + explicit constexpr GetDesiredStateRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline GetDesiredStateRequest(const GetDesiredStateRequest& from) : GetDesiredStateRequest(nullptr, from) {} + inline GetDesiredStateRequest(GetDesiredStateRequest&& from) noexcept : GetDesiredStateRequest(nullptr, ::std::move(from)) {} + inline GetDesiredStateRequest& operator=(const GetDesiredStateRequest& from) { + CopyFrom(from); + return *this; + } + inline GetDesiredStateRequest& operator=(GetDesiredStateRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const GetDesiredStateRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&GetDesiredStateRequest_globals_); + } + static constexpr int kIndexInFileMessages = 2; + friend void swap(GetDesiredStateRequest& a, GetDesiredStateRequest& b) { a.Swap(&b); } + inline void Swap(GetDesiredStateRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GetDesiredStateRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] GetDesiredStateRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const GetDesiredStateRequest& from); + using Super_::MergeFrom; + void MergeFrom(const GetDesiredStateRequest& from) { GetDesiredStateRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(GetDesiredStateRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.GetDesiredStateRequest"; } + + explicit GetDesiredStateRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + GetDesiredStateRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const GetDesiredStateRequest& from); + GetDesiredStateRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, GetDesiredStateRequest&& from) noexcept + : GetDesiredStateRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kAgentIdFieldNumber = 1, + }; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.GetDesiredStateRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<0, 1, + 0, 57, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const GetDesiredStateRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED GetDesiredStateResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.GetDesiredStateResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline GetDesiredStateResponse() : GetDesiredStateResponse(nullptr) {} + ~GetDesiredStateResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(GetDesiredStateResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(GetDesiredStateResponse)); + } +#endif + + template + explicit constexpr GetDesiredStateResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline GetDesiredStateResponse(const GetDesiredStateResponse& from) : GetDesiredStateResponse(nullptr, from) {} + inline GetDesiredStateResponse(GetDesiredStateResponse&& from) noexcept : GetDesiredStateResponse(nullptr, ::std::move(from)) {} + inline GetDesiredStateResponse& operator=(const GetDesiredStateResponse& from) { + CopyFrom(from); + return *this; + } + inline GetDesiredStateResponse& operator=(GetDesiredStateResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const GetDesiredStateResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&GetDesiredStateResponse_globals_); + } + static constexpr int kIndexInFileMessages = 3; + friend void swap(GetDesiredStateResponse& a, GetDesiredStateResponse& b) { a.Swap(&b); } + inline void Swap(GetDesiredStateResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GetDesiredStateResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] GetDesiredStateResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const GetDesiredStateResponse& from); + using Super_::MergeFrom; + void MergeFrom(const GetDesiredStateResponse& from) { GetDesiredStateResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(GetDesiredStateResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.GetDesiredStateResponse"; } + + explicit GetDesiredStateResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + GetDesiredStateResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const GetDesiredStateResponse& from); + GetDesiredStateResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, GetDesiredStateResponse&& from) noexcept + : GetDesiredStateResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kDesiredFieldNumber = 1, + }; + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + [[nodiscard]] bool has_desired() const; + void clear_desired() ; + [[nodiscard]] const ::xtcp_treatment::v1::DesiredState& desired() const; + [[nodiscard]] ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE release_desired(); + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL mutable_desired(); + void set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE unsafe_arena_release_desired(); + + private: + const ::xtcp_treatment::v1::DesiredState& _internal_desired() const; + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL _internal_mutable_desired(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.GetDesiredStateResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<0, 1, + 1, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const GetDesiredStateResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE desired_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED CheckInResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.CheckInResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline CheckInResponse() : CheckInResponse(nullptr) {} + ~CheckInResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(CheckInResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(CheckInResponse)); + } +#endif + + template + explicit constexpr CheckInResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline CheckInResponse(const CheckInResponse& from) : CheckInResponse(nullptr, from) {} + inline CheckInResponse(CheckInResponse&& from) noexcept : CheckInResponse(nullptr, ::std::move(from)) {} + inline CheckInResponse& operator=(const CheckInResponse& from) { + CopyFrom(from); + return *this; + } + inline CheckInResponse& operator=(CheckInResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const CheckInResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&CheckInResponse_globals_); + } + static constexpr int kIndexInFileMessages = 1; + friend void swap(CheckInResponse& a, CheckInResponse& b) { a.Swap(&b); } + inline void Swap(CheckInResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(CheckInResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] CheckInResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const CheckInResponse& from); + using Super_::MergeFrom; + void MergeFrom(const CheckInResponse& from) { CheckInResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(CheckInResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.CheckInResponse"; } + + explicit CheckInResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + CheckInResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const CheckInResponse& from); + CheckInResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, CheckInResponse&& from) noexcept + : CheckInResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kDesiredFieldNumber = 1, + }; + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + [[nodiscard]] bool has_desired() const; + void clear_desired() ; + [[nodiscard]] const ::xtcp_treatment::v1::DesiredState& desired() const; + [[nodiscard]] ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE release_desired(); + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL mutable_desired(); + void set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE unsafe_arena_release_desired(); + + private: + const ::xtcp_treatment::v1::DesiredState& _internal_desired() const; + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL _internal_mutable_desired(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.CheckInResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<0, 1, + 1, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const CheckInResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE desired_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED CheckInRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.CheckInRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline CheckInRequest() : CheckInRequest(nullptr) {} + ~CheckInRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(CheckInRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(CheckInRequest)); + } +#endif + + template + explicit constexpr CheckInRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline CheckInRequest(const CheckInRequest& from) : CheckInRequest(nullptr, from) {} + inline CheckInRequest(CheckInRequest&& from) noexcept : CheckInRequest(nullptr, ::std::move(from)) {} + inline CheckInRequest& operator=(const CheckInRequest& from) { + CopyFrom(from); + return *this; + } + inline CheckInRequest& operator=(CheckInRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const CheckInRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&CheckInRequest_globals_); + } + static constexpr int kIndexInFileMessages = 0; + friend void swap(CheckInRequest& a, CheckInRequest& b) { a.Swap(&b); } + inline void Swap(CheckInRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(CheckInRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] CheckInRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const CheckInRequest& from); + using Super_::MergeFrom; + void MergeFrom(const CheckInRequest& from) { CheckInRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(CheckInRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.CheckInRequest"; } + + explicit CheckInRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + CheckInRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const CheckInRequest& from); + CheckInRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, CheckInRequest&& from) noexcept + : CheckInRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kRecordsFieldNumber = 5, + kAgentIdFieldNumber = 1, + kLocationFieldNumber = 2, + kCapabilitiesFieldNumber = 3, + kDesiredRevisionFieldNumber = 4, + kLocallySuspendedFieldNumber = 6, + }; + // repeated .xtcp_treatment.v1.ApplicationRecord records = 5 [json_name = "records", (.buf.validate.field) = { + [[nodiscard]] int records_size() const; + private: + int _internal_records_size() const; + + public: + void clear_records() ; + [[nodiscard]] const ::xtcp_treatment::v1::ApplicationRecord& records(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL mutable_records(int index); + ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL add_records(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& + records() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL + mutable_records(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& _internal_records() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL _internal_mutable_records(); + + public: + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // string location = 2 [json_name = "location", (.buf.validate.field) = { + void clear_location() ; + [[nodiscard]] const ::std::string& location() const; + template + void set_location(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_location(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_location(); + void set_allocated_location(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_location() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_location(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_location(); + + public: + // .xtcp_treatment.v1.Capabilities capabilities = 3 [json_name = "capabilities", (.buf.validate.field) = { + [[nodiscard]] bool has_capabilities() const; + void clear_capabilities() ; + [[nodiscard]] const ::xtcp_treatment::v1::Capabilities& capabilities() const; + [[nodiscard]] ::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE release_capabilities(); + ::xtcp_treatment::v1::Capabilities* PROTOBUF_NONNULL mutable_capabilities(); + void set_allocated_capabilities(::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_capabilities(::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE unsafe_arena_release_capabilities(); + + private: + const ::xtcp_treatment::v1::Capabilities& _internal_capabilities() const; + ::xtcp_treatment::v1::Capabilities* PROTOBUF_NONNULL _internal_mutable_capabilities(); + + public: + // uint64 desired_revision = 4 [json_name = "desiredRevision"]; + void clear_desired_revision() ; + [[nodiscard]] ::uint64_t desired_revision() const; + void set_desired_revision(::uint64_t value); + + private: + ::uint64_t _internal_desired_revision() const; + void _internal_set_desired_revision(::uint64_t value); + + public: + // bool locally_suspended = 6 [json_name = "locallySuspended"]; + void clear_locally_suspended() ; + [[nodiscard]] bool locally_suspended() const; + void set_locally_suspended(bool value); + + private: + bool _internal_locally_suspended() const; + void _internal_set_locally_suspended(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.CheckInRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 6, + 2, 57, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const CheckInRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::ApplicationRecord > records_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + ::google::protobuf::internal::ArenaStringPtr location_; + ::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE capabilities_; + ::uint64_t desired_revision_; + bool locally_suspended_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2fagent_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// CheckInRequest + +// string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { +inline void CheckInRequest::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& CheckInRequest::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.CheckInRequest.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void CheckInRequest::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.CheckInRequest.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL CheckInRequest::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.CheckInRequest.agent_id) + return _s; +} +inline const ::std::string& CheckInRequest::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void CheckInRequest::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL CheckInRequest::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE CheckInRequest::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.CheckInRequest.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void CheckInRequest::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.CheckInRequest.agent_id) +} + +// string location = 2 [json_name = "location", (.buf.validate.field) = { +inline void CheckInRequest::clear_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& CheckInRequest::location() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.CheckInRequest.location) + return _internal_location(); +} +template +PROTOBUF_ALWAYS_INLINE void CheckInRequest::set_location(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.location_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.CheckInRequest.location) +} +inline ::std::string* PROTOBUF_NONNULL CheckInRequest::mutable_location() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_location(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.CheckInRequest.location) + return _s; +} +inline const ::std::string& CheckInRequest::_internal_location() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.location_.Get(); +} +inline void CheckInRequest::_internal_set_location(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL CheckInRequest::_internal_mutable_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.location_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE CheckInRequest::release_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.CheckInRequest.location) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.location_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.location_.Set("", GetArena()); + } + return released; +} +inline void CheckInRequest::set_allocated_location(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.location_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.location_.IsDefault()) { + _impl_.location_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.CheckInRequest.location) +} + +// .xtcp_treatment.v1.Capabilities capabilities = 3 [json_name = "capabilities", (.buf.validate.field) = { +inline bool CheckInRequest::has_capabilities() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.capabilities_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::Capabilities& CheckInRequest::_internal_capabilities() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Capabilities* p = _impl_.capabilities_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Capabilities>(&::xtcp_treatment::v1::Capabilities_globals_); +} +inline const ::xtcp_treatment::v1::Capabilities& CheckInRequest::capabilities() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.CheckInRequest.capabilities) + return _internal_capabilities(); +} +inline void CheckInRequest::unsafe_arena_set_allocated_capabilities( + ::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.capabilities_); + } + _impl_.capabilities_ = reinterpret_cast<::xtcp_treatment::v1::Capabilities*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.CheckInRequest.capabilities) +} +inline ::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE CheckInRequest::release_capabilities() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Capabilities* released = _impl_.capabilities_; + _impl_.capabilities_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE CheckInRequest::unsafe_arena_release_capabilities() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.CheckInRequest.capabilities) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Capabilities* temp = _impl_.capabilities_; + _impl_.capabilities_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Capabilities* PROTOBUF_NONNULL CheckInRequest::_internal_mutable_capabilities() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.capabilities_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Capabilities>(GetArena()); + _impl_.capabilities_ = reinterpret_cast<::xtcp_treatment::v1::Capabilities*>(p); + } + return _impl_.capabilities_; +} +inline ::xtcp_treatment::v1::Capabilities* PROTOBUF_NONNULL CheckInRequest::mutable_capabilities() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Capabilities* _msg = _internal_mutable_capabilities(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.CheckInRequest.capabilities) + return _msg; +} +inline void CheckInRequest::set_allocated_capabilities(::xtcp_treatment::v1::Capabilities* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.capabilities_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.capabilities_ = reinterpret_cast<::xtcp_treatment::v1::Capabilities*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.CheckInRequest.capabilities) +} + +// uint64 desired_revision = 4 [json_name = "desiredRevision"]; +inline void CheckInRequest::clear_desired_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.desired_revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline ::uint64_t CheckInRequest::desired_revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.CheckInRequest.desired_revision) + return _internal_desired_revision(); +} +inline void CheckInRequest::set_desired_revision(::uint64_t value) { + _internal_set_desired_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.CheckInRequest.desired_revision) +} +inline ::uint64_t CheckInRequest::_internal_desired_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.desired_revision_; +} +inline void CheckInRequest::_internal_set_desired_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.desired_revision_ = value; +} + +// repeated .xtcp_treatment.v1.ApplicationRecord records = 5 [json_name = "records", (.buf.validate.field) = { +inline int CheckInRequest::_internal_records_size() const { + return _internal_records().size(); +} +inline int CheckInRequest::records_size() const { + return _internal_records_size(); +} +inline const ::xtcp_treatment::v1::ApplicationRecord& CheckInRequest::records(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.CheckInRequest.records) + return _internal_records().Get(index); +} +inline ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL CheckInRequest::mutable_records(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.CheckInRequest.records) + return _internal_mutable_records()->Mutable(index); +} +inline ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL CheckInRequest::add_records() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::ApplicationRecord* _add = + _internal_mutable_records()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.CheckInRequest.records) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& CheckInRequest::records() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.CheckInRequest.records) + return _internal_records(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL +CheckInRequest::mutable_records() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.CheckInRequest.records) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_records(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& +CheckInRequest::_internal_records() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.records_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL +CheckInRequest::_internal_mutable_records() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.records_; +} + +// bool locally_suspended = 6 [json_name = "locallySuspended"]; +inline void CheckInRequest::clear_locally_suspended() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.locally_suspended_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline bool CheckInRequest::locally_suspended() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.CheckInRequest.locally_suspended) + return _internal_locally_suspended(); +} +inline void CheckInRequest::set_locally_suspended(bool value) { + _internal_set_locally_suspended(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.CheckInRequest.locally_suspended) +} +inline bool CheckInRequest::_internal_locally_suspended() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.locally_suspended_; +} +inline void CheckInRequest::_internal_set_locally_suspended(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.locally_suspended_ = value; +} + +// ------------------------------------------------------------------- + +// CheckInResponse + +// .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; +inline bool CheckInResponse::has_desired() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.desired_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::DesiredState& CheckInResponse::_internal_desired() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::DesiredState* p = _impl_.desired_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::DesiredState>(&::xtcp_treatment::v1::DesiredState_globals_); +} +inline const ::xtcp_treatment::v1::DesiredState& CheckInResponse::desired() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.CheckInResponse.desired) + return _internal_desired(); +} +inline void CheckInResponse::unsafe_arena_set_allocated_desired( + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.CheckInResponse.desired) +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE CheckInResponse::release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::DesiredState* released = _impl_.desired_; + _impl_.desired_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE CheckInResponse::unsafe_arena_release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.CheckInResponse.desired) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::DesiredState* temp = _impl_.desired_; + _impl_.desired_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL CheckInResponse::_internal_mutable_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::DesiredState>(GetArena()); + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(p); + } + return _impl_.desired_; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL CheckInResponse::mutable_desired() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::DesiredState* _msg = _internal_mutable_desired(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.CheckInResponse.desired) + return _msg; +} +inline void CheckInResponse::set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.CheckInResponse.desired) +} + +// ------------------------------------------------------------------- + +// GetDesiredStateRequest + +// string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { +inline void GetDesiredStateRequest::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& GetDesiredStateRequest::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.GetDesiredStateRequest.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void GetDesiredStateRequest::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.GetDesiredStateRequest.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL GetDesiredStateRequest::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.GetDesiredStateRequest.agent_id) + return _s; +} +inline const ::std::string& GetDesiredStateRequest::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void GetDesiredStateRequest::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL GetDesiredStateRequest::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE GetDesiredStateRequest::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.GetDesiredStateRequest.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void GetDesiredStateRequest::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.GetDesiredStateRequest.agent_id) +} + +// ------------------------------------------------------------------- + +// GetDesiredStateResponse + +// .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; +inline bool GetDesiredStateResponse::has_desired() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.desired_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::DesiredState& GetDesiredStateResponse::_internal_desired() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::DesiredState* p = _impl_.desired_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::DesiredState>(&::xtcp_treatment::v1::DesiredState_globals_); +} +inline const ::xtcp_treatment::v1::DesiredState& GetDesiredStateResponse::desired() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.GetDesiredStateResponse.desired) + return _internal_desired(); +} +inline void GetDesiredStateResponse::unsafe_arena_set_allocated_desired( + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.GetDesiredStateResponse.desired) +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE GetDesiredStateResponse::release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::DesiredState* released = _impl_.desired_; + _impl_.desired_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE GetDesiredStateResponse::unsafe_arena_release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.GetDesiredStateResponse.desired) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::DesiredState* temp = _impl_.desired_; + _impl_.desired_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL GetDesiredStateResponse::_internal_mutable_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::DesiredState>(GetArena()); + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(p); + } + return _impl_.desired_; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL GetDesiredStateResponse::mutable_desired() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::DesiredState* _msg = _internal_mutable_desired(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.GetDesiredStateResponse.desired) + return _msg; +} +inline void GetDesiredStateResponse::set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.GetDesiredStateResponse.desired) +} + +// ------------------------------------------------------------------- + +// WatchDesiredStateRequest + +// string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { +inline void WatchDesiredStateRequest::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& WatchDesiredStateRequest::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.WatchDesiredStateRequest.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void WatchDesiredStateRequest::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.WatchDesiredStateRequest.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL WatchDesiredStateRequest::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.WatchDesiredStateRequest.agent_id) + return _s; +} +inline const ::std::string& WatchDesiredStateRequest::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void WatchDesiredStateRequest::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL WatchDesiredStateRequest::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE WatchDesiredStateRequest::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.WatchDesiredStateRequest.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void WatchDesiredStateRequest::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.WatchDesiredStateRequest.agent_id) +} + +// uint64 after_revision = 2 [json_name = "afterRevision"]; +inline void WatchDesiredStateRequest::clear_after_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.after_revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline ::uint64_t WatchDesiredStateRequest::after_revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.WatchDesiredStateRequest.after_revision) + return _internal_after_revision(); +} +inline void WatchDesiredStateRequest::set_after_revision(::uint64_t value) { + _internal_set_after_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.WatchDesiredStateRequest.after_revision) +} +inline ::uint64_t WatchDesiredStateRequest::_internal_after_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.after_revision_; +} +inline void WatchDesiredStateRequest::_internal_set_after_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.after_revision_ = value; +} + +// ------------------------------------------------------------------- + +// WatchDesiredStateResponse + +// uint64 revision = 1 [json_name = "revision"]; +inline void WatchDesiredStateResponse::clear_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline ::uint64_t WatchDesiredStateResponse::revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.WatchDesiredStateResponse.revision) + return _internal_revision(); +} +inline void WatchDesiredStateResponse::set_revision(::uint64_t value) { + _internal_set_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.WatchDesiredStateResponse.revision) +} +inline ::uint64_t WatchDesiredStateResponse::_internal_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.revision_; +} +inline void WatchDesiredStateResponse::_internal_set_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = value; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment + + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" +// clang-format on + +#endif // xtcp_5ftreatment_2fv1_2fagent_2eproto_2epb_2eh diff --git a/gen/cpp/xtcp_treatment/v1/operator.grpc.pb.cc b/gen/cpp/xtcp_treatment/v1/operator.grpc.pb.cc new file mode 100644 index 000000000..8d58c1a0a --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/operator.grpc.pb.cc @@ -0,0 +1,258 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment/v1/operator.proto + +#include "xtcp_treatment/v1/operator.pb.h" +#include "xtcp_treatment/v1/operator.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace xtcp_treatment { +namespace v1 { + +static const char* OperatorService_method_names[] = { + "/xtcp_treatment.v1.OperatorService/Propose", + "/xtcp_treatment.v1.OperatorService/Analyze", + "/xtcp_treatment.v1.OperatorService/Review", + "/xtcp_treatment.v1.OperatorService/Control", + "/xtcp_treatment.v1.OperatorService/Inspect", +}; + +std::unique_ptr< OperatorService::Stub> OperatorService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + (void)options; + std::unique_ptr< OperatorService::Stub> stub(new OperatorService::Stub(channel, options)); + return stub; +} + +OperatorService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) + : channel_(channel), rpcmethod_Propose_(OperatorService_method_names[0], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Analyze_(OperatorService_method_names[1], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Review_(OperatorService_method_names[2], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Control_(OperatorService_method_names[3], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Inspect_(OperatorService_method_names[4], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + {} + +::grpc::Status OperatorService::Stub::Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::xtcp_treatment::v1::ProposeResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Propose_, context, request, response); +} + +void OperatorService::Stub::async::Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Propose_, context, request, response, std::move(f)); +} + +void OperatorService::Stub::async::Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Propose_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>* OperatorService::Stub::PrepareAsyncProposeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::xtcp_treatment::v1::ProposeResponse, ::xtcp_treatment::v1::ProposeRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Propose_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>* OperatorService::Stub::AsyncProposeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncProposeRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status OperatorService::Stub::Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::xtcp_treatment::v1::AnalyzeResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Analyze_, context, request, response); +} + +void OperatorService::Stub::async::Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Analyze_, context, request, response, std::move(f)); +} + +void OperatorService::Stub::async::Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Analyze_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>* OperatorService::Stub::PrepareAsyncAnalyzeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::xtcp_treatment::v1::AnalyzeResponse, ::xtcp_treatment::v1::AnalyzeRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Analyze_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>* OperatorService::Stub::AsyncAnalyzeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncAnalyzeRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status OperatorService::Stub::Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::xtcp_treatment::v1::ReviewResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Review_, context, request, response); +} + +void OperatorService::Stub::async::Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Review_, context, request, response, std::move(f)); +} + +void OperatorService::Stub::async::Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Review_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>* OperatorService::Stub::PrepareAsyncReviewRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::xtcp_treatment::v1::ReviewResponse, ::xtcp_treatment::v1::ReviewRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Review_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>* OperatorService::Stub::AsyncReviewRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncReviewRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status OperatorService::Stub::Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::xtcp_treatment::v1::ControlResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Control_, context, request, response); +} + +void OperatorService::Stub::async::Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Control_, context, request, response, std::move(f)); +} + +void OperatorService::Stub::async::Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Control_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>* OperatorService::Stub::PrepareAsyncControlRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::xtcp_treatment::v1::ControlResponse, ::xtcp_treatment::v1::ControlRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Control_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>* OperatorService::Stub::AsyncControlRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncControlRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status OperatorService::Stub::Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::xtcp_treatment::v1::InspectResponse* response) { + return ::grpc::internal::BlockingUnaryCall< ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Inspect_, context, request, response); +} + +void OperatorService::Stub::async::Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Inspect_, context, request, response, std::move(f)); +} + +void OperatorService::Stub::async::Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Inspect_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>* OperatorService::Stub::PrepareAsyncInspectRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::xtcp_treatment::v1::InspectResponse, ::xtcp_treatment::v1::InspectRequest, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Inspect_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>* OperatorService::Stub::AsyncInspectRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncInspectRaw(context, request, cq); + result->StartCall(); + return result; +} + +OperatorService::Service::Service() { + AddMethod(new ::grpc::internal::RpcServiceMethod( + OperatorService_method_names[0], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< OperatorService::Service, ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](OperatorService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::ProposeRequest* req, + ::xtcp_treatment::v1::ProposeResponse* resp) { + return service->Propose(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + OperatorService_method_names[1], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< OperatorService::Service, ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](OperatorService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::AnalyzeRequest* req, + ::xtcp_treatment::v1::AnalyzeResponse* resp) { + return service->Analyze(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + OperatorService_method_names[2], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< OperatorService::Service, ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](OperatorService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::ReviewRequest* req, + ::xtcp_treatment::v1::ReviewResponse* resp) { + return service->Review(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + OperatorService_method_names[3], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< OperatorService::Service, ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](OperatorService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::ControlRequest* req, + ::xtcp_treatment::v1::ControlResponse* resp) { + return service->Control(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + OperatorService_method_names[4], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< OperatorService::Service, ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](OperatorService::Service* service, + ::grpc::ServerContext* ctx, + const ::xtcp_treatment::v1::InspectRequest* req, + ::xtcp_treatment::v1::InspectResponse* resp) { + return service->Inspect(ctx, req, resp); + }, this))); +} + +OperatorService::Service::~Service() { +} + +::grpc::Status OperatorService::Service::Propose(::grpc::ServerContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status OperatorService::Service::Analyze(::grpc::ServerContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status OperatorService::Service::Review(::grpc::ServerContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status OperatorService::Service::Control(::grpc::ServerContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status OperatorService::Service::Inspect(::grpc::ServerContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +} // namespace xtcp_treatment +} // namespace v1 +#include + diff --git a/gen/cpp/xtcp_treatment/v1/operator.grpc.pb.h b/gen/cpp/xtcp_treatment/v1/operator.grpc.pb.h new file mode 100644 index 000000000..72df21c03 --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/operator.grpc.pb.h @@ -0,0 +1,881 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment/v1/operator.proto +// Original file comments: +// +// xTCP - treatment operator service +// +// The authenticated review surface. Every mutation carries a request_id; +// repeating one with the same body replays the original response, repeating +// it with a different body is refused. Reviews also fence on the experiment +// revision the operator last saw. +// +#ifndef GRPC_xtcp_5ftreatment_2fv1_2foperator_2eproto__INCLUDED +#define GRPC_xtcp_5ftreatment_2fv1_2foperator_2eproto__INCLUDED + +#include "xtcp_treatment/v1/operator.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xtcp_treatment { +namespace v1 { + +class OperatorService final { + public: + static constexpr char const* service_full_name() { + return "xtcp_treatment.v1.OperatorService"; + } + class StubInterface { + public: + virtual ~StubInterface() {} + virtual ::grpc::Status Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::xtcp_treatment::v1::ProposeResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ProposeResponse>> AsyncPropose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ProposeResponse>>(AsyncProposeRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ProposeResponse>> PrepareAsyncPropose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ProposeResponse>>(PrepareAsyncProposeRaw(context, request, cq)); + } + virtual ::grpc::Status Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::xtcp_treatment::v1::AnalyzeResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::AnalyzeResponse>> AsyncAnalyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::AnalyzeResponse>>(AsyncAnalyzeRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::AnalyzeResponse>> PrepareAsyncAnalyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::AnalyzeResponse>>(PrepareAsyncAnalyzeRaw(context, request, cq)); + } + virtual ::grpc::Status Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::xtcp_treatment::v1::ReviewResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ReviewResponse>> AsyncReview(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ReviewResponse>>(AsyncReviewRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ReviewResponse>> PrepareAsyncReview(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ReviewResponse>>(PrepareAsyncReviewRaw(context, request, cq)); + } + virtual ::grpc::Status Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::xtcp_treatment::v1::ControlResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ControlResponse>> AsyncControl(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ControlResponse>>(AsyncControlRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ControlResponse>> PrepareAsyncControl(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ControlResponse>>(PrepareAsyncControlRaw(context, request, cq)); + } + virtual ::grpc::Status Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::xtcp_treatment::v1::InspectResponse* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::InspectResponse>> AsyncInspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::InspectResponse>>(AsyncInspectRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::InspectResponse>> PrepareAsyncInspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::InspectResponse>>(PrepareAsyncInspectRaw(context, request, cq)); + } + class async_interface { + public: + virtual ~async_interface() {} + virtual void Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response, std::function) = 0; + virtual void Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + virtual void Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response, std::function) = 0; + virtual void Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + virtual void Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response, std::function) = 0; + virtual void Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + virtual void Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response, std::function) = 0; + virtual void Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + virtual void Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response, std::function) = 0; + virtual void Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response, ::grpc::ClientUnaryReactor* reactor) = 0; + }; + typedef class async_interface experimental_async_interface; + virtual class async_interface* async() { return nullptr; } + class async_interface* experimental_async() { return async(); } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ProposeResponse>* AsyncProposeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ProposeResponse>* PrepareAsyncProposeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::AnalyzeResponse>* AsyncAnalyzeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::AnalyzeResponse>* PrepareAsyncAnalyzeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ReviewResponse>* AsyncReviewRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ReviewResponse>* PrepareAsyncReviewRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ControlResponse>* AsyncControlRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::ControlResponse>* PrepareAsyncControlRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::InspectResponse>* AsyncInspectRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::xtcp_treatment::v1::InspectResponse>* PrepareAsyncInspectRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub final : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + ::grpc::Status Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::xtcp_treatment::v1::ProposeResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>> AsyncPropose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>>(AsyncProposeRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>> PrepareAsyncPropose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>>(PrepareAsyncProposeRaw(context, request, cq)); + } + ::grpc::Status Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::xtcp_treatment::v1::AnalyzeResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>> AsyncAnalyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>>(AsyncAnalyzeRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>> PrepareAsyncAnalyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>>(PrepareAsyncAnalyzeRaw(context, request, cq)); + } + ::grpc::Status Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::xtcp_treatment::v1::ReviewResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>> AsyncReview(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>>(AsyncReviewRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>> PrepareAsyncReview(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>>(PrepareAsyncReviewRaw(context, request, cq)); + } + ::grpc::Status Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::xtcp_treatment::v1::ControlResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>> AsyncControl(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>>(AsyncControlRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>> PrepareAsyncControl(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>>(PrepareAsyncControlRaw(context, request, cq)); + } + ::grpc::Status Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::xtcp_treatment::v1::InspectResponse* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>> AsyncInspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>>(AsyncInspectRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>> PrepareAsyncInspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>>(PrepareAsyncInspectRaw(context, request, cq)); + } + class async final : + public StubInterface::async_interface { + public: + void Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response, std::function) override; + void Propose(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + void Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response, std::function) override; + void Analyze(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + void Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response, std::function) override; + void Review(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + void Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response, std::function) override; + void Control(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + void Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response, std::function) override; + void Inspect(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response, ::grpc::ClientUnaryReactor* reactor) override; + private: + friend class Stub; + explicit async(Stub* stub): stub_(stub) { } + Stub* stub() { return stub_; } + Stub* stub_; + }; + class async* async() override { return &async_stub_; } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + class async async_stub_{this}; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>* AsyncProposeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ProposeResponse>* PrepareAsyncProposeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ProposeRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>* AsyncAnalyzeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::AnalyzeResponse>* PrepareAsyncAnalyzeRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::AnalyzeRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>* AsyncReviewRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ReviewResponse>* PrepareAsyncReviewRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ReviewRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>* AsyncControlRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::ControlResponse>* PrepareAsyncControlRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::ControlRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>* AsyncInspectRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::xtcp_treatment::v1::InspectResponse>* PrepareAsyncInspectRaw(::grpc::ClientContext* context, const ::xtcp_treatment::v1::InspectRequest& request, ::grpc::CompletionQueue* cq) override; + const ::grpc::internal::RpcMethod rpcmethod_Propose_; + const ::grpc::internal::RpcMethod rpcmethod_Analyze_; + const ::grpc::internal::RpcMethod rpcmethod_Review_; + const ::grpc::internal::RpcMethod rpcmethod_Control_; + const ::grpc::internal::RpcMethod rpcmethod_Inspect_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + virtual ::grpc::Status Propose(::grpc::ServerContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response); + virtual ::grpc::Status Analyze(::grpc::ServerContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response); + virtual ::grpc::Status Review(::grpc::ServerContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response); + virtual ::grpc::Status Control(::grpc::ServerContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response); + virtual ::grpc::Status Inspect(::grpc::ServerContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response); + }; + template + class WithAsyncMethod_Propose : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_Propose() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_Propose() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Propose(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ProposeRequest* /*request*/, ::xtcp_treatment::v1::ProposeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestPropose(::grpc::ServerContext* context, ::xtcp_treatment::v1::ProposeRequest* request, ::grpc::ServerAsyncResponseWriter< ::xtcp_treatment::v1::ProposeResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Analyze : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_Analyze() { + ::grpc::Service::MarkMethodAsync(1); + } + ~WithAsyncMethod_Analyze() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Analyze(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::AnalyzeRequest* /*request*/, ::xtcp_treatment::v1::AnalyzeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestAnalyze(::grpc::ServerContext* context, ::xtcp_treatment::v1::AnalyzeRequest* request, ::grpc::ServerAsyncResponseWriter< ::xtcp_treatment::v1::AnalyzeResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Review : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_Review() { + ::grpc::Service::MarkMethodAsync(2); + } + ~WithAsyncMethod_Review() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Review(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ReviewRequest* /*request*/, ::xtcp_treatment::v1::ReviewResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestReview(::grpc::ServerContext* context, ::xtcp_treatment::v1::ReviewRequest* request, ::grpc::ServerAsyncResponseWriter< ::xtcp_treatment::v1::ReviewResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Control : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_Control() { + ::grpc::Service::MarkMethodAsync(3); + } + ~WithAsyncMethod_Control() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Control(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ControlRequest* /*request*/, ::xtcp_treatment::v1::ControlResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestControl(::grpc::ServerContext* context, ::xtcp_treatment::v1::ControlRequest* request, ::grpc::ServerAsyncResponseWriter< ::xtcp_treatment::v1::ControlResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(3, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Inspect : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_Inspect() { + ::grpc::Service::MarkMethodAsync(4); + } + ~WithAsyncMethod_Inspect() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Inspect(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::InspectRequest* /*request*/, ::xtcp_treatment::v1::InspectResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestInspect(::grpc::ServerContext* context, ::xtcp_treatment::v1::InspectRequest* request, ::grpc::ServerAsyncResponseWriter< ::xtcp_treatment::v1::InspectResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(4, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_Propose > > > > AsyncService; + template + class WithCallbackMethod_Propose : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_Propose() { + ::grpc::Service::MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::ProposeRequest* request, ::xtcp_treatment::v1::ProposeResponse* response) { return this->Propose(context, request, response); }));} + void SetMessageAllocatorFor_Propose( + ::grpc::MessageAllocator< ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0); + static_cast<::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_Propose() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Propose(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ProposeRequest* /*request*/, ::xtcp_treatment::v1::ProposeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Propose( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::ProposeRequest* /*request*/, ::xtcp_treatment::v1::ProposeResponse* /*response*/) { return nullptr; } + }; + template + class WithCallbackMethod_Analyze : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_Analyze() { + ::grpc::Service::MarkMethodCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::AnalyzeRequest* request, ::xtcp_treatment::v1::AnalyzeResponse* response) { return this->Analyze(context, request, response); }));} + void SetMessageAllocatorFor_Analyze( + ::grpc::MessageAllocator< ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(1); + static_cast<::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_Analyze() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Analyze(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::AnalyzeRequest* /*request*/, ::xtcp_treatment::v1::AnalyzeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Analyze( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::AnalyzeRequest* /*request*/, ::xtcp_treatment::v1::AnalyzeResponse* /*response*/) { return nullptr; } + }; + template + class WithCallbackMethod_Review : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_Review() { + ::grpc::Service::MarkMethodCallback(2, + new ::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::ReviewRequest* request, ::xtcp_treatment::v1::ReviewResponse* response) { return this->Review(context, request, response); }));} + void SetMessageAllocatorFor_Review( + ::grpc::MessageAllocator< ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(2); + static_cast<::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_Review() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Review(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ReviewRequest* /*request*/, ::xtcp_treatment::v1::ReviewResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Review( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::ReviewRequest* /*request*/, ::xtcp_treatment::v1::ReviewResponse* /*response*/) { return nullptr; } + }; + template + class WithCallbackMethod_Control : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_Control() { + ::grpc::Service::MarkMethodCallback(3, + new ::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::ControlRequest* request, ::xtcp_treatment::v1::ControlResponse* response) { return this->Control(context, request, response); }));} + void SetMessageAllocatorFor_Control( + ::grpc::MessageAllocator< ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(3); + static_cast<::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_Control() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Control(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ControlRequest* /*request*/, ::xtcp_treatment::v1::ControlResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Control( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::ControlRequest* /*request*/, ::xtcp_treatment::v1::ControlResponse* /*response*/) { return nullptr; } + }; + template + class WithCallbackMethod_Inspect : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_Inspect() { + ::grpc::Service::MarkMethodCallback(4, + new ::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse>( + [this]( + ::grpc::CallbackServerContext* context, const ::xtcp_treatment::v1::InspectRequest* request, ::xtcp_treatment::v1::InspectResponse* response) { return this->Inspect(context, request, response); }));} + void SetMessageAllocatorFor_Inspect( + ::grpc::MessageAllocator< ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(4); + static_cast<::grpc::internal::CallbackUnaryHandler< ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_Inspect() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Inspect(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::InspectRequest* /*request*/, ::xtcp_treatment::v1::InspectResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Inspect( + ::grpc::CallbackServerContext* /*context*/, const ::xtcp_treatment::v1::InspectRequest* /*request*/, ::xtcp_treatment::v1::InspectResponse* /*response*/) { return nullptr; } + }; + typedef WithCallbackMethod_Propose > > > > CallbackService; + typedef CallbackService ExperimentalCallbackService; + template + class WithGenericMethod_Propose : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_Propose() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_Propose() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Propose(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ProposeRequest* /*request*/, ::xtcp_treatment::v1::ProposeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Analyze : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_Analyze() { + ::grpc::Service::MarkMethodGeneric(1); + } + ~WithGenericMethod_Analyze() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Analyze(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::AnalyzeRequest* /*request*/, ::xtcp_treatment::v1::AnalyzeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Review : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_Review() { + ::grpc::Service::MarkMethodGeneric(2); + } + ~WithGenericMethod_Review() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Review(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ReviewRequest* /*request*/, ::xtcp_treatment::v1::ReviewResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Control : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_Control() { + ::grpc::Service::MarkMethodGeneric(3); + } + ~WithGenericMethod_Control() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Control(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ControlRequest* /*request*/, ::xtcp_treatment::v1::ControlResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Inspect : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_Inspect() { + ::grpc::Service::MarkMethodGeneric(4); + } + ~WithGenericMethod_Inspect() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Inspect(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::InspectRequest* /*request*/, ::xtcp_treatment::v1::InspectResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithRawMethod_Propose : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_Propose() { + ::grpc::Service::MarkMethodRaw(0); + } + ~WithRawMethod_Propose() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Propose(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ProposeRequest* /*request*/, ::xtcp_treatment::v1::ProposeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestPropose(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_Analyze : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_Analyze() { + ::grpc::Service::MarkMethodRaw(1); + } + ~WithRawMethod_Analyze() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Analyze(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::AnalyzeRequest* /*request*/, ::xtcp_treatment::v1::AnalyzeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestAnalyze(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_Review : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_Review() { + ::grpc::Service::MarkMethodRaw(2); + } + ~WithRawMethod_Review() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Review(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ReviewRequest* /*request*/, ::xtcp_treatment::v1::ReviewResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestReview(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_Control : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_Control() { + ::grpc::Service::MarkMethodRaw(3); + } + ~WithRawMethod_Control() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Control(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ControlRequest* /*request*/, ::xtcp_treatment::v1::ControlResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestControl(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(3, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_Inspect : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_Inspect() { + ::grpc::Service::MarkMethodRaw(4); + } + ~WithRawMethod_Inspect() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Inspect(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::InspectRequest* /*request*/, ::xtcp_treatment::v1::InspectResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestInspect(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(4, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawCallbackMethod_Propose : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_Propose() { + ::grpc::Service::MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Propose(context, request, response); })); + } + ~WithRawCallbackMethod_Propose() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Propose(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ProposeRequest* /*request*/, ::xtcp_treatment::v1::ProposeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Propose( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithRawCallbackMethod_Analyze : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_Analyze() { + ::grpc::Service::MarkMethodRawCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Analyze(context, request, response); })); + } + ~WithRawCallbackMethod_Analyze() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Analyze(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::AnalyzeRequest* /*request*/, ::xtcp_treatment::v1::AnalyzeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Analyze( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithRawCallbackMethod_Review : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_Review() { + ::grpc::Service::MarkMethodRawCallback(2, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Review(context, request, response); })); + } + ~WithRawCallbackMethod_Review() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Review(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ReviewRequest* /*request*/, ::xtcp_treatment::v1::ReviewResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Review( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithRawCallbackMethod_Control : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_Control() { + ::grpc::Service::MarkMethodRawCallback(3, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Control(context, request, response); })); + } + ~WithRawCallbackMethod_Control() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Control(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ControlRequest* /*request*/, ::xtcp_treatment::v1::ControlResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Control( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithRawCallbackMethod_Inspect : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_Inspect() { + ::grpc::Service::MarkMethodRawCallback(4, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Inspect(context, request, response); })); + } + ~WithRawCallbackMethod_Inspect() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Inspect(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::InspectRequest* /*request*/, ::xtcp_treatment::v1::InspectResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* Inspect( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template + class WithStreamedUnaryMethod_Propose : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_Propose() { + ::grpc::Service::MarkMethodStreamed(0, + new ::grpc::internal::StreamedUnaryHandler< + ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::xtcp_treatment::v1::ProposeRequest, ::xtcp_treatment::v1::ProposeResponse>* streamer) { + return this->StreamedPropose(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_Propose() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Propose(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ProposeRequest* /*request*/, ::xtcp_treatment::v1::ProposeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedPropose(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::xtcp_treatment::v1::ProposeRequest,::xtcp_treatment::v1::ProposeResponse>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_Analyze : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_Analyze() { + ::grpc::Service::MarkMethodStreamed(1, + new ::grpc::internal::StreamedUnaryHandler< + ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::xtcp_treatment::v1::AnalyzeRequest, ::xtcp_treatment::v1::AnalyzeResponse>* streamer) { + return this->StreamedAnalyze(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_Analyze() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Analyze(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::AnalyzeRequest* /*request*/, ::xtcp_treatment::v1::AnalyzeResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedAnalyze(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::xtcp_treatment::v1::AnalyzeRequest,::xtcp_treatment::v1::AnalyzeResponse>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_Review : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_Review() { + ::grpc::Service::MarkMethodStreamed(2, + new ::grpc::internal::StreamedUnaryHandler< + ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::xtcp_treatment::v1::ReviewRequest, ::xtcp_treatment::v1::ReviewResponse>* streamer) { + return this->StreamedReview(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_Review() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Review(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ReviewRequest* /*request*/, ::xtcp_treatment::v1::ReviewResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedReview(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::xtcp_treatment::v1::ReviewRequest,::xtcp_treatment::v1::ReviewResponse>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_Control : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_Control() { + ::grpc::Service::MarkMethodStreamed(3, + new ::grpc::internal::StreamedUnaryHandler< + ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::xtcp_treatment::v1::ControlRequest, ::xtcp_treatment::v1::ControlResponse>* streamer) { + return this->StreamedControl(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_Control() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Control(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::ControlRequest* /*request*/, ::xtcp_treatment::v1::ControlResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedControl(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::xtcp_treatment::v1::ControlRequest,::xtcp_treatment::v1::ControlResponse>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_Inspect : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_Inspect() { + ::grpc::Service::MarkMethodStreamed(4, + new ::grpc::internal::StreamedUnaryHandler< + ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::xtcp_treatment::v1::InspectRequest, ::xtcp_treatment::v1::InspectResponse>* streamer) { + return this->StreamedInspect(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_Inspect() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Inspect(::grpc::ServerContext* /*context*/, const ::xtcp_treatment::v1::InspectRequest* /*request*/, ::xtcp_treatment::v1::InspectResponse* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedInspect(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::xtcp_treatment::v1::InspectRequest,::xtcp_treatment::v1::InspectResponse>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_Propose > > > > StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_Propose > > > > StreamedService; +}; + +} // namespace v1 +} // namespace xtcp_treatment + + +#include +#endif // GRPC_xtcp_5ftreatment_2fv1_2foperator_2eproto__INCLUDED diff --git a/gen/cpp/xtcp_treatment/v1/operator.pb.cc b/gen/cpp/xtcp_treatment/v1/operator.pb.cc new file mode 100644 index 000000000..bdd43e97f --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/operator.pb.cc @@ -0,0 +1,4643 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment/v1/operator.proto +// Protobuf C++ Version: 7.36.2 + +#include "xtcp_treatment/v1/operator.pb.h" + +#include +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/internal_visibility.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; +#ifdef PROTOBUF_MESSAGE_GLOBALS +namespace { +PROTOBUF_CONSTINIT ::google::protobuf::internal::ReflectionData + file_reflection_data[] = { + // ::xtcp_treatment::v1::ProposeRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::ProposeResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::AnalyzeRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::AnalyzeResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::ReviewRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::ReviewResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::ControlRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::ControlResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::InspectRequest + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::InspectResponse + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, /* tracker*/ nullptr,}, +}; +} // namespace +#endif +namespace xtcp_treatment { +namespace v1 { +class InspectRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InspectRequest, _impl_._has_bits_); +}; + +constexpr InspectRequest::ParseTableT_ InspectRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(InspectRequest, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967292, // skipmap + offsetof(ParseTableT_, field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::InspectRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {18, 1, 0, + PROTOBUF_FIELD_OFFSET(InspectRequest, _impl_.agent_id_)}}, + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(InspectRequest, _impl_.experiment_id_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(InspectRequest, _impl_.experiment_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(InspectRequest, _impl_.agent_id_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + "\40\15\10\0\0\0\0\0" + "xtcp_treatment.v1.InspectRequest" + "experiment_id" + "agent_id" + }}, + }; +} + + +inline constexpr InspectRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()) {} + +template +constexpr InspectRequest::InspectRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL InspectRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InspectRequest(arena); +} +constexpr auto InspectRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(InspectRequest), alignof(InspectRequest)); +} +constexpr auto InspectRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &InspectRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InspectRequest::SharedDtor, + Super_::GetClearImpl(), &InspectRequest::ByteSizeLong, + &InspectRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InspectRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[8], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct InspectRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr InspectRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + InspectRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(InspectRequest::InternalGenerateClassData_( + _default, &InspectRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~InspectRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) InspectRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(InspectRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST InspectRequestGlobalsTypeInternal InspectRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* InspectRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return InspectRequest_globals_.GetClassData(); +#else + return InspectRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ControlResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ControlResponse, _impl_._has_bits_); +}; + +constexpr ControlResponse::ParseTableT_ ControlResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ControlResponse, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967294, // skipmap + offsetof(ParseTableT_, field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ControlResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint32 affected_agents = 1 [json_name = "affectedAgents"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ControlResponse, _impl_.affected_agents_), 0>(), + {8, 0, 0, + PROTOBUF_FIELD_OFFSET(ControlResponse, _impl_.affected_agents_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 affected_agents = 1 [json_name = "affectedAgents"]; + {PROTOBUF_FIELD_OFFSET(ControlResponse, _impl_.affected_agents_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + }}, + // no aux_entries + {{ + }}, + }; +} + + +inline constexpr ControlResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : affected_agents_{0u} {} + +template +constexpr ControlResponse::ControlResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ControlResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ControlResponse(arena); +} +constexpr auto ControlResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(ControlResponse), alignof(ControlResponse)); +} +constexpr auto ControlResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ControlResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ControlResponse::SharedDtor, + Super_::GetClearImpl(), &ControlResponse::ByteSizeLong, + &ControlResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ControlResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[7], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ControlResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ControlResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ControlResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ControlResponse::InternalGenerateClassData_( + _default, &ControlResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ControlResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ControlResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ControlResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ControlResponseGlobalsTypeInternal ControlResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ControlResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ControlResponse_globals_.GetClassData(); +#else + return ControlResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ControlRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_._has_bits_); +}; + +constexpr ControlRequest::ParseTableT_ ControlRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_._has_bits_), + 0, // no _extensions_ + 7, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967168, // skipmap + offsetof(ParseTableT_, field_entries), + 7, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ControlRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.experiment_id_)}}, + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {18, 1, 0, + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.agent_id_)}}, + // string location = 3 [json_name = "location", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {26, 2, 0, + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.location_)}}, + // bool fleet = 4 [json_name = "fleet"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {32, 5, 0, + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.fleet_)}}, + // .xtcp_treatment.v1.ControlAction action = 5 [json_name = "action", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ControlRequest, _impl_.action_), 6>(), + {40, 6, 0, + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.action_)}}, + // string reason = 6 [json_name = "reason", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {50, 3, 0, + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.reason_)}}, + // string request_id = 7 [json_name = "requestId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {58, 4, 0, + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.request_id_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.experiment_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.agent_id_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string location = 3 [json_name = "location", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.location_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bool fleet = 4 [json_name = "fleet"]; + {PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.fleet_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // .xtcp_treatment.v1.ControlAction action = 5 [json_name = "action", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.action_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // string reason = 6 [json_name = "reason", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.reason_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string request_id = 7 [json_name = "requestId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.request_id_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + "\40\15\10\10\0\0\6\12" + "xtcp_treatment.v1.ControlRequest" + "experiment_id" + "agent_id" + "location" + "reason" + "request_id" + }}, + }; +} + + +inline constexpr ControlRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + location_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + reason_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + request_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + fleet_{false}, + action_{static_cast< ::xtcp_treatment::v1::ControlAction >(0)} {} + +template +constexpr ControlRequest::ControlRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ControlRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ControlRequest(arena); +} +constexpr auto ControlRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(ControlRequest), alignof(ControlRequest)); +} +constexpr auto ControlRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ControlRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ControlRequest::SharedDtor, + Super_::GetClearImpl(), &ControlRequest::ByteSizeLong, + &ControlRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[6], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ControlRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ControlRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ControlRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ControlRequest::InternalGenerateClassData_( + _default, &ControlRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ControlRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ControlRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ControlRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ControlRequestGlobalsTypeInternal ControlRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ControlRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ControlRequest_globals_.GetClassData(); +#else + return ControlRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class AnalyzeRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(AnalyzeRequest, _impl_._has_bits_); +}; + +constexpr AnalyzeRequest::ParseTableT_ AnalyzeRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(AnalyzeRequest, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967292, // skipmap + offsetof(ParseTableT_, field_entries), + 2, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::AnalyzeRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(AnalyzeRequest, _impl_.expected_revision_), 1>(), + {16, 1, 0, + PROTOBUF_FIELD_OFFSET(AnalyzeRequest, _impl_.expected_revision_)}}, + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(AnalyzeRequest, _impl_.experiment_id_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(AnalyzeRequest, _impl_.experiment_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + {PROTOBUF_FIELD_OFFSET(AnalyzeRequest, _impl_.expected_revision_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + }}, + // no aux_entries + {{ + "\40\15\0\0\0\0\0\0" + "xtcp_treatment.v1.AnalyzeRequest" + "experiment_id" + }}, + }; +} + + +inline constexpr AnalyzeRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + expected_revision_{::uint64_t{0u}} {} + +template +constexpr AnalyzeRequest::AnalyzeRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL AnalyzeRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) AnalyzeRequest(arena); +} +constexpr auto AnalyzeRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(AnalyzeRequest), alignof(AnalyzeRequest)); +} +constexpr auto AnalyzeRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &AnalyzeRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &AnalyzeRequest::SharedDtor, + Super_::GetClearImpl(), &AnalyzeRequest::ByteSizeLong, + &AnalyzeRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(AnalyzeRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[2], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct AnalyzeRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr AnalyzeRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + AnalyzeRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(AnalyzeRequest::InternalGenerateClassData_( + _default, &AnalyzeRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~AnalyzeRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) AnalyzeRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(AnalyzeRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST AnalyzeRequestGlobalsTypeInternal AnalyzeRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* AnalyzeRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return AnalyzeRequest_globals_.GetClassData(); +#else + return AnalyzeRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ReviewRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_._has_bits_); +}; + +constexpr ReviewRequest::ParseTableT_ ReviewRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_._has_bits_), + 0, // no _extensions_ + 6, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967232, // skipmap + offsetof(ParseTableT_, field_entries), + 6, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ReviewRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.experiment_id_)}}, + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ReviewRequest, _impl_.expected_revision_), 4>(), + {16, 4, 0, + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.expected_revision_)}}, + // bool approve = 3 [json_name = "approve"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 5, 0, + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.approve_)}}, + // string reason = 4 [json_name = "reason", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {34, 1, 0, + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.reason_)}}, + // string request_id = 5 [json_name = "requestId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {42, 2, 0, + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.request_id_)}}, + // .xtcp_treatment.v1.Evidence evidence = 6 [json_name = "evidence"]; + {::_pbi::TcParser::FastMtS1, + {50, 3, 0, + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.evidence_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.experiment_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + {PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.expected_revision_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // bool approve = 3 [json_name = "approve"]; + {PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.approve_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // string reason = 4 [json_name = "reason", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.reason_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string request_id = 5 [json_name = "requestId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.request_id_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment.v1.Evidence evidence = 6 [json_name = "evidence"]; + {PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.evidence_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Evidence>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Evidence_globals_}, + #endif + }}, + {{ + "\37\15\0\0\6\12\0\0" + "xtcp_treatment.v1.ReviewRequest" + "experiment_id" + "reason" + "request_id" + }}, + }; +} + + +inline constexpr ReviewRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + reason_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + request_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + evidence_{nullptr}, + expected_revision_{::uint64_t{0u}}, + approve_{false} {} + +template +constexpr ReviewRequest::ReviewRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ReviewRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ReviewRequest(arena); +} +constexpr auto ReviewRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(ReviewRequest), alignof(ReviewRequest)); +} +constexpr auto ReviewRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ReviewRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ReviewRequest::SharedDtor, + Super_::GetClearImpl(), &ReviewRequest::ByteSizeLong, + &ReviewRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[4], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ReviewRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ReviewRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ReviewRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ReviewRequest::InternalGenerateClassData_( + _default, &ReviewRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ReviewRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ReviewRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ReviewRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ReviewRequestGlobalsTypeInternal ReviewRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ReviewRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ReviewRequest_globals_.GetClassData(); +#else + return ReviewRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class AnalyzeResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_._has_bits_); +}; + +constexpr AnalyzeResponse::ParseTableT_ AnalyzeResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967292, // skipmap + offsetof(ParseTableT_, field_entries), + 2, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::AnalyzeResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .xtcp_treatment.v1.Outcome outcome = 2 [json_name = "outcome"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(AnalyzeResponse, _impl_.outcome_), 1>(), + {16, 1, 0, + PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_.outcome_)}}, + // .xtcp_treatment.v1.Evidence evidence = 1 [json_name = "evidence"]; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_.evidence_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.Evidence evidence = 1 [json_name = "evidence"]; + {PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_.evidence_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.Outcome outcome = 2 [json_name = "outcome"]; + {PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_.outcome_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Evidence>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Evidence_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr AnalyzeResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : evidence_{nullptr}, + outcome_{static_cast< ::xtcp_treatment::v1::Outcome >(0)} {} + +template +constexpr AnalyzeResponse::AnalyzeResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL AnalyzeResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) AnalyzeResponse(arena); +} +constexpr auto AnalyzeResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(AnalyzeResponse), alignof(AnalyzeResponse)); +} +constexpr auto AnalyzeResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &AnalyzeResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &AnalyzeResponse::SharedDtor, + Super_::GetClearImpl(), &AnalyzeResponse::ByteSizeLong, + &AnalyzeResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[3], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct AnalyzeResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr AnalyzeResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + AnalyzeResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(AnalyzeResponse::InternalGenerateClassData_( + _default, &AnalyzeResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~AnalyzeResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) AnalyzeResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(AnalyzeResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST AnalyzeResponseGlobalsTypeInternal AnalyzeResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* AnalyzeResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return AnalyzeResponse_globals_.GetClassData(); +#else + return AnalyzeResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ReviewResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ReviewResponse, _impl_._has_bits_); +}; + +constexpr ReviewResponse::ParseTableT_ ReviewResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ReviewResponse, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967294, // skipmap + offsetof(ParseTableT_, field_entries), + 1, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ReviewResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(ReviewResponse, _impl_.experiment_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + {PROTOBUF_FIELD_OFFSET(ReviewResponse, _impl_.experiment_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Experiment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Experiment_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr ReviewResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_{nullptr} {} + +template +constexpr ReviewResponse::ReviewResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ReviewResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ReviewResponse(arena); +} +constexpr auto ReviewResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(ReviewResponse), alignof(ReviewResponse)); +} +constexpr auto ReviewResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ReviewResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ReviewResponse::SharedDtor, + Super_::GetClearImpl(), &ReviewResponse::ByteSizeLong, + &ReviewResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ReviewResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[5], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ReviewResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ReviewResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ReviewResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ReviewResponse::InternalGenerateClassData_( + _default, &ReviewResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ReviewResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ReviewResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ReviewResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ReviewResponseGlobalsTypeInternal ReviewResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ReviewResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ReviewResponse_globals_.GetClassData(); +#else + return ReviewResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ProposeResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ProposeResponse, _impl_._has_bits_); +}; + +constexpr ProposeResponse::ParseTableT_ ProposeResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ProposeResponse, _impl_._has_bits_), + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967294, // skipmap + offsetof(ParseTableT_, field_entries), + 1, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ProposeResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(ProposeResponse, _impl_.experiment_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + {PROTOBUF_FIELD_OFFSET(ProposeResponse, _impl_.experiment_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Experiment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Experiment_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr ProposeResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_{nullptr} {} + +template +constexpr ProposeResponse::ProposeResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ProposeResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ProposeResponse(arena); +} +constexpr auto ProposeResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(ProposeResponse), alignof(ProposeResponse)); +} +constexpr auto ProposeResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ProposeResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ProposeResponse::SharedDtor, + Super_::GetClearImpl(), &ProposeResponse::ByteSizeLong, + &ProposeResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ProposeResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[1], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ProposeResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ProposeResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ProposeResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ProposeResponse::InternalGenerateClassData_( + _default, &ProposeResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ProposeResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ProposeResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ProposeResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ProposeResponseGlobalsTypeInternal ProposeResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ProposeResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ProposeResponse_globals_.GetClassData(); +#else + return ProposeResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ProposeRequest::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ProposeRequest, _impl_._has_bits_); +}; + +constexpr ProposeRequest::ParseTableT_ ProposeRequest::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ProposeRequest, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967292, // skipmap + offsetof(ParseTableT_, field_entries), + 2, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ProposeRequest>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // string request_id = 2 [json_name = "requestId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {18, 0, 0, + PROTOBUF_FIELD_OFFSET(ProposeRequest, _impl_.request_id_)}}, + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {10, 1, 0, + PROTOBUF_FIELD_OFFSET(ProposeRequest, _impl_.experiment_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ProposeRequest, _impl_.experiment_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // string request_id = 2 [json_name = "requestId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ProposeRequest, _impl_.request_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Experiment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Experiment_globals_}, + #endif + }}, + {{ + "\40\0\12\0\0\0\0\0" + "xtcp_treatment.v1.ProposeRequest" + "request_id" + }}, + }; +} + + +inline constexpr ProposeRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : request_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + experiment_{nullptr} {} + +template +constexpr ProposeRequest::ProposeRequest(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ProposeRequest::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ProposeRequest(arena); +} +constexpr auto ProposeRequest::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(ProposeRequest), alignof(ProposeRequest)); +} +constexpr auto ProposeRequest::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ProposeRequest::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ProposeRequest::SharedDtor, + Super_::GetClearImpl(), &ProposeRequest::ByteSizeLong, + &ProposeRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ProposeRequest, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[0], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ProposeRequestGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ProposeRequestGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ProposeRequest_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ProposeRequest::InternalGenerateClassData_( + _default, &ProposeRequest_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ProposeRequestGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ProposeRequest _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ProposeRequestGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ProposeRequestGlobalsTypeInternal ProposeRequest_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ProposeRequest_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ProposeRequest_globals_.GetClassData(); +#else + return ProposeRequest_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class InspectResponse::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_._has_bits_); +}; + +constexpr InspectResponse::ParseTableT_ InspectResponse::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_._has_bits_), + 0, // no _extensions_ + 3, 24, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967288, // skipmap + offsetof(ParseTableT_, field_entries), + 3, // num_field_entries + 3, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::InspectResponse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // repeated .xtcp_treatment.v1.Experiment experiments = 1 [json_name = "experiments"]; + {::_pbi::TcParser::FastMtR1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_.experiments_)}}, + // repeated .xtcp_treatment.v1.DesiredState desired = 2 [json_name = "desired"]; + {::_pbi::TcParser::FastMtR1, + {18, 1, 1, + PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_.desired_)}}, + // repeated .xtcp_treatment.v1.CheckInRequest observed = 3 [json_name = "observed"]; + {::_pbi::TcParser::FastMtR1, + {26, 2, 2, + PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_.observed_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated .xtcp_treatment.v1.Experiment experiments = 1 [json_name = "experiments"]; + {PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_.experiments_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .xtcp_treatment.v1.DesiredState desired = 2 [json_name = "desired"]; + {PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_.desired_), _Internal::kHasBitsOffset + 1, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .xtcp_treatment.v1.CheckInRequest observed = 3 [json_name = "observed"]; + {PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_.observed_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Experiment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Experiment_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::DesiredState>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::DesiredState_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::CheckInRequest>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::CheckInRequest_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr InspectResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiments_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.experiments_)>() + } + , + desired_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.desired_)>() + } + , + observed_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.observed_)>() + } + {} + +template +constexpr InspectResponse::InspectResponse(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL InspectResponse::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) InspectResponse(arena); +} +constexpr auto InspectResponse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(InspectResponse), alignof(InspectResponse)); +} +constexpr auto InspectResponse::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &InspectResponse::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &InspectResponse::SharedDtor, + Super_::GetClearImpl(), &InspectResponse::ByteSizeLong, + &InspectResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(InspectResponse, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[9], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct InspectResponseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr InspectResponseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + InspectResponse_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(InspectResponse::InternalGenerateClassData_( + _default, &InspectResponse_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~InspectResponseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) InspectResponse _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(InspectResponseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST InspectResponseGlobalsTypeInternal InspectResponse_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* InspectResponse_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return InspectResponse_globals_.GetClassData(); +#else + return InspectResponse_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +} // namespace v1 +} // namespace xtcp_treatment +static const ::_pb::EnumDescriptor* PROTOBUF_NONNULL + file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2foperator_2eproto[1]; +static constexpr const ::_pb::ServiceDescriptor* PROTOBUF_NONNULL* PROTOBUF_NULLABLE + file_level_service_descriptors_xtcp_5ftreatment_2fv1_2foperator_2eproto = nullptr; +const ::uint32_t + TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ProposeRequest, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ProposeRequest, _impl_.experiment_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ProposeRequest, _impl_.request_id_), + 1, + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ProposeResponse, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ProposeResponse, _impl_.experiment_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::AnalyzeRequest, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::AnalyzeRequest, _impl_.experiment_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::AnalyzeRequest, _impl_.expected_revision_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::AnalyzeResponse, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::AnalyzeResponse, _impl_.evidence_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::AnalyzeResponse, _impl_.outcome_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewRequest, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewRequest, _impl_.experiment_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewRequest, _impl_.expected_revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewRequest, _impl_.approve_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewRequest, _impl_.reason_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewRequest, _impl_.request_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewRequest, _impl_.evidence_), + 0, + 4, + 5, + 1, + 2, + 3, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewResponse, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ReviewResponse, _impl_.experiment_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_._has_bits_), + 10, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_.experiment_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_.agent_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_.fleet_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_.action_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_.reason_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlRequest, _impl_.request_id_), + 0, + 1, + 2, + 5, + 6, + 3, + 4, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlResponse, _impl_._has_bits_), + 4, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ControlResponse, _impl_.affected_agents_), + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectRequest, _impl_._has_bits_), + 5, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectRequest, _impl_.experiment_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectRequest, _impl_.agent_id_), + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_._has_bits_), + 6, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.experiments_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.desired_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.observed_), + 0, + 1, + 2, +}; + +static const ::_pbi::MigrationSchema + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + {0, sizeof(::xtcp_treatment::v1::ProposeRequest)}, + {7, sizeof(::xtcp_treatment::v1::ProposeResponse)}, + {12, sizeof(::xtcp_treatment::v1::AnalyzeRequest)}, + {19, sizeof(::xtcp_treatment::v1::AnalyzeResponse)}, + {26, sizeof(::xtcp_treatment::v1::ReviewRequest)}, + {41, sizeof(::xtcp_treatment::v1::ReviewResponse)}, + {46, sizeof(::xtcp_treatment::v1::ControlRequest)}, + {63, sizeof(::xtcp_treatment::v1::ControlResponse)}, + {68, sizeof(::xtcp_treatment::v1::InspectRequest)}, + {75, sizeof(::xtcp_treatment::v1::InspectResponse)}, +}; +static const ::_pbi::MessageGlobalsBase* PROTOBUF_NONNULL const + file_message_globals[] = { + &::xtcp_treatment::v1::ProposeRequest_globals_, + &::xtcp_treatment::v1::ProposeResponse_globals_, + &::xtcp_treatment::v1::AnalyzeRequest_globals_, + &::xtcp_treatment::v1::AnalyzeResponse_globals_, + &::xtcp_treatment::v1::ReviewRequest_globals_, + &::xtcp_treatment::v1::ReviewResponse_globals_, + &::xtcp_treatment::v1::ControlRequest_globals_, + &::xtcp_treatment::v1::ControlResponse_globals_, + &::xtcp_treatment::v1::InspectRequest_globals_, + &::xtcp_treatment::v1::InspectResponse_globals_, +}; +const char descriptor_table_protodef_xtcp_5ftreatment_2fv1_2foperator_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + "\n xtcp_treatment/v1/operator.proto\022\021xtcp" + "_treatment.v1\032\033buf/validate/validate.pro" + "to\032\035xtcp_treatment/v1/agent.proto\032!xtcp_" + "treatment/v1/treatment.proto\"\273\002\n\016Propose" + "Request\022E\n\nexperiment\030\001 \001(\0132\035.xtcp_treat" + "ment.v1.ExperimentB\006\272H\003\310\001\001R\nexperiment\022H" + "\n\nrequest_id\030\002 \001(\tB)\272H&r$2\"^[a-zA-Z0-9][" + "a-zA-Z0-9_.-]{0,127}$R\trequestId:\227\001\272H\223\001\032" + "\220\001\n\031propose.request_id_suffix\022Mrequest_i" + "d must not end with .result (reserved fo" + "r the paired response event)\032$!this.requ" + "est_id.endsWith(\'.result\')\"P\n\017ProposeRes" + "ponse\022=\n\nexperiment\030\001 \001(\0132\035.xtcp_treatme" + "nt.v1.ExperimentR\nexperiment\"\215\001\n\016Analyze" + "Request\022N\n\rexperiment_id\030\001 \001(\tB)\272H&r$2\"^" + "[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\014exper" + "imentId\022+\n\021expected_revision\030\002 \001(\004R\020expe" + "ctedRevision\"\200\001\n\017AnalyzeResponse\0227\n\010evid" + "ence\030\001 \001(\0132\033.xtcp_treatment.v1.EvidenceR" + "\010evidence\0224\n\007outcome\030\002 \001(\0162\032.xtcp_treatm" + "ent.v1.OutcomeR\007outcome\"\346\003\n\rReviewReques" + "t\022N\n\rexperiment_id\030\001 \001(\tB)\272H&r$2\"^[a-zA-" + "Z0-9][a-zA-Z0-9_.-]{0,127}$R\014experimentI" + "d\022+\n\021expected_revision\030\002 \001(\004R\020expectedRe" + "vision\022\030\n\007approve\030\003 \001(\010R\007approve\022\"\n\006reas" + "on\030\004 \001(\tB\n\272H\007r\005\020\001\030\200 R\006reason\022H\n\nrequest_" + "id\030\005 \001(\tB)\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_" + ".-]{0,127}$R\trequestId\0227\n\010evidence\030\006 \001(\013" + "2\033.xtcp_treatment.v1.EvidenceR\010evidence:" + "\226\001\272H\222\001\032\217\001\n\030review.request_id_suffix\022Mreq" + "uest_id must not end with .result (reser" + "ved for the paired response event)\032$!thi" + "s.request_id.endsWith(\'.result\')\"O\n\016Revi" + "ewResponse\022=\n\nexperiment\030\001 \001(\0132\035.xtcp_tr" + "eatment.v1.ExperimentR\nexperiment\"\272\006\n\016Co" + "ntrolRequest\022Q\n\rexperiment_id\030\001 \001(\tB,\272H)" + "r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001" + "\001R\014experimentId\022G\n\010agent_id\030\002 \001(\tB,\272H)r$" + "2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001\001R" + "\007agentId\022H\n\010location\030\003 \001(\tB,\272H)r$2\"^[a-z" + "A-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001\001R\010locati" + "on\022\024\n\005fleet\030\004 \001(\010R\005fleet\022D\n\006action\030\005 \001(\016" + "2 .xtcp_treatment.v1.ControlActionB\n\272H\007\202" + "\001\004\020\001 \000R\006action\022\"\n\006reason\030\006 \001(\tB\n\272H\007r\005\020\001\030" + "\200 R\006reason\022H\n\nrequest_id\030\007 \001(\tB)\272H&r$2\"^" + "[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\treque" + "stId:\367\002\272H\363\002\032\220\001\n\031control.request_id_suffi" + "x\022Mrequest_id must not end with .result " + "(reserved for the paired response event)" + "\032$!this.request_id.endsWith(\'.result\')\032\335" + "\001\n\024control.one_selector\022Eexactly one of " + "experiment_id, agent_id, location or fle" + "et is required\032~(this.fleet \? 1 : 0) + (" + "this.experiment_id != \'\' \? 1 : 0) + (thi" + "s.agent_id != \'\' \? 1 : 0) + (this.locati" + "on != \'\' \? 1 : 0) == 1\":\n\017ControlRespons" + "e\022\'\n\017affected_agents\030\001 \001(\rR\016affectedAgen" + "ts\"\254\001\n\016InspectRequest\022Q\n\rexperiment_id\030\001" + " \001(\tB,\272H)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{" + "0,127}$\330\001\001R\014experimentId\022G\n\010agent_id\030\002 \001" + "(\tB,\272H)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0," + "127}$\330\001\001R\007agentId\"\314\001\n\017InspectResponse\022\?\n" + "\013experiments\030\001 \003(\0132\035.xtcp_treatment.v1.E" + "xperimentR\013experiments\0229\n\007desired\030\002 \003(\0132" + "\037.xtcp_treatment.v1.DesiredStateR\007desire" + "d\022=\n\010observed\030\003 \003(\0132!.xtcp_treatment.v1." + "CheckInRequestR\010observed*\270\001\n\rControlActi" + "on\022\036\n\032CONTROL_ACTION_UNSPECIFIED\020\000\022\030\n\024CO" + "NTROL_ACTION_PAUSE\020\001\022\032\n\026CONTROL_ACTION_S" + "USPEND\020\002\022\031\n\025CONTROL_ACTION_RESUME\020\003\022\033\n\027C" + "ONTROL_ACTION_ROLLBACK\020\004\022\031\n\025CONTROL_ACTI" + "ON_RETIRE\020\0052\306\003\n\017OperatorService\022V\n\007Propo" + "se\022!.xtcp_treatment.v1.ProposeRequest\032\"." + "xtcp_treatment.v1.ProposeResponse\"\004\320\363\030\002\022" + "V\n\007Analyze\022!.xtcp_treatment.v1.AnalyzeRe" + "quest\032\".xtcp_treatment.v1.AnalyzeRespons" + "e\"\004\320\363\030\002\022S\n\006Review\022 .xtcp_treatment.v1.Re" + "viewRequest\032!.xtcp_treatment.v1.ReviewRe" + "sponse\"\004\320\363\030\002\022V\n\007Control\022!.xtcp_treatment" + ".v1.ControlRequest\032\".xtcp_treatment.v1.C" + "ontrolResponse\"\004\320\363\030\002\022V\n\007Inspect\022!.xtcp_t" + "reatment.v1.InspectRequest\032\".xtcp_treatm" + "ent.v1.InspectResponse\"\004\320\363\030\002B\277\001\n\025com.xtc" + "p_treatment.v1B\rOperatorProtoP\001Z6github." + "com/randomizedcoder/xtcp2/gen/go/xtcp_tr" + "eatment\242\002\003XXX\252\002\020XtcpTreatment.V1\312\002\020XtcpT" + "reatment\\V1\342\002\034XtcpTreatment\\V1\\GPBMetada" + "ta\352\002\021XtcpTreatment::V1b\006proto3" +}; +static const ::_pbi::DescriptorTable* PROTOBUF_NONNULL const + descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto_deps[3] = { + &::descriptor_table_buf_2fvalidate_2fvalidate_2eproto, + &::descriptor_table_xtcp_5ftreatment_2fv1_2fagent_2eproto, + &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, +}; +static ::absl::once_flag descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto_once; +PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto = { + false, + false, + 3510, + descriptor_table_protodef_xtcp_5ftreatment_2fv1_2foperator_2eproto, + "xtcp_treatment/v1/operator.proto", + &descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto_once, + descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto_deps, + 3, + 10, + schemas, + file_message_globals, + TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto::offsets, + file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2foperator_2eproto, + file_level_service_descriptors_xtcp_5ftreatment_2fv1_2foperator_2eproto, +}; +namespace xtcp_treatment { +namespace v1 { +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ControlAction_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2foperator_2eproto[0]; +} +PROTOBUF_CONSTINIT const uint32_t ControlAction_internal_data_[] = { + 393216u, 0u, }; +// =================================================================== + +void ProposeRequest::clear_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.experiment_ != nullptr) _impl_.experiment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +ProposeRequest::ProposeRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ProposeRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ProposeRequest) +} +PROTOBUF_NDEBUG_INLINE ProposeRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::ProposeRequest& from_msg) + : _has_bits_{from._has_bits_}, + request_id_(arena, from.request_id_) {} + +ProposeRequest::ProposeRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ProposeRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ProposeRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ProposeRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.experiment_ = (CheckHasBit(cached_has_bits, 0x00000002U)) + ? Super_::CopyConstruct(arena, *from._impl_.experiment_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.ProposeRequest) +} +PROTOBUF_NDEBUG_INLINE ProposeRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : request_id_(arena) {} + +inline void ProposeRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.experiment_ = {}; +} +ProposeRequest::~ProposeRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ProposeRequest) + SharedDtor(*this); +} +inline void ProposeRequest::SharedDtor(MessageLite& self) { + ProposeRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.request_id_.Destroy(); + delete this_._impl_.experiment_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ProposeRequest_class_data_ = + ProposeRequest::InternalGenerateClassData_(ProposeRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ProposeRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ProposeRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ProposeRequest_class_data_.tc_table); + return ProposeRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ProposeRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ProposeRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ProposeRequest_globals_)); + return ProposeRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ProposeRequest::ParseTableT_ + ProposeRequest::_table_ = + ProposeRequest::InternalGenerateParseTable_(ProposeRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ProposeRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ProposeRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.request_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(this_._impl_.experiment_ != nullptr); + this_._impl_.experiment_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ProposeRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ProposeRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ProposeRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ProposeRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ProposeRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.experiment_, this_._impl_.experiment_->GetCachedSize(), target, + stream); + } + + // string request_id = 2 [json_name = "requestId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_request_id().empty()) { + const ::std::string& _s = this_._internal_request_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ProposeRequest.request_id"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ProposeRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ProposeRequest::ByteSizeLong(const MessageLite& base) { + const ProposeRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ProposeRequest::ByteSizeLong() const { + const ProposeRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ProposeRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + // string request_id = 2 [json_name = "requestId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_request_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_request_id()); + } + } + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.experiment_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ProposeRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ProposeRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_request_id().empty()) { + _this->_internal_set_request_id(from._internal_request_id()); + } else { + if (_this->_impl_.request_id_.IsDefault()) { + _this->_internal_set_request_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(from._impl_.experiment_ != nullptr); + if (_this->_impl_.experiment_ == nullptr) { + _this->_impl_.experiment_ = Super_::CopyConstruct(arena, *from._impl_.experiment_); + } else { + _this->_impl_.experiment_->MergeFrom(*from._impl_.experiment_); + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ProposeRequest::CopyFrom(const ProposeRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ProposeRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ProposeRequest::InternalSwap(ProposeRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.request_id_, &other->_impl_.request_id_, arena); + swap(_impl_.experiment_, other->_impl_.experiment_); +} + +::google::protobuf::Metadata ProposeRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void ProposeResponse::clear_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.experiment_ != nullptr) _impl_.experiment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +ProposeResponse::ProposeResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ProposeResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ProposeResponse) +} +PROTOBUF_NDEBUG_INLINE ProposeResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::ProposeResponse& from_msg) + : _has_bits_{from._has_bits_} {} + +ProposeResponse::ProposeResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ProposeResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ProposeResponse_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ProposeResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.experiment_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? Super_::CopyConstruct(arena, *from._impl_.experiment_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.ProposeResponse) +} +PROTOBUF_NDEBUG_INLINE ProposeResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void ProposeResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.experiment_ = {}; +} +ProposeResponse::~ProposeResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ProposeResponse) + SharedDtor(*this); +} +inline void ProposeResponse::SharedDtor(MessageLite& self) { + ProposeResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.experiment_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ProposeResponse_class_data_ = + ProposeResponse::InternalGenerateClassData_(ProposeResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ProposeResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ProposeResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ProposeResponse_class_data_.tc_table); + return ProposeResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ProposeResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ProposeResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ProposeResponse_globals_)); + return ProposeResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ProposeResponse::ParseTableT_ + ProposeResponse::_table_ = + ProposeResponse::InternalGenerateParseTable_(ProposeResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ProposeResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ProposeResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(this_._impl_.experiment_ != nullptr); + this_._impl_.experiment_->Clear(); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ProposeResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ProposeResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ProposeResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ProposeResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ProposeResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.experiment_, this_._impl_.experiment_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ProposeResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ProposeResponse::ByteSizeLong(const MessageLite& base) { + const ProposeResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ProposeResponse::ByteSizeLong() const { + const ProposeResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ProposeResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + { + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.experiment_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ProposeResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ProposeResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.experiment_ != nullptr); + if (_this->_impl_.experiment_ == nullptr) { + _this->_impl_.experiment_ = Super_::CopyConstruct(arena, *from._impl_.experiment_); + } else { + _this->_impl_.experiment_->MergeFrom(*from._impl_.experiment_); + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ProposeResponse::CopyFrom(const ProposeResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ProposeResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ProposeResponse::InternalSwap(ProposeResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.experiment_, other->_impl_.experiment_); +} + +::google::protobuf::Metadata ProposeResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +AnalyzeRequest::AnalyzeRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, AnalyzeRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.AnalyzeRequest) +} +PROTOBUF_NDEBUG_INLINE AnalyzeRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::AnalyzeRequest& from_msg) + : _has_bits_{from._has_bits_}, + experiment_id_(arena, from.experiment_id_) {} + +AnalyzeRequest::AnalyzeRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const AnalyzeRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, AnalyzeRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + AnalyzeRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_.expected_revision_ = from._impl_.expected_revision_; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.AnalyzeRequest) +} +PROTOBUF_NDEBUG_INLINE AnalyzeRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : experiment_id_(arena) {} + +inline void AnalyzeRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.expected_revision_ = {}; +} +AnalyzeRequest::~AnalyzeRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.AnalyzeRequest) + SharedDtor(*this); +} +inline void AnalyzeRequest::SharedDtor(MessageLite& self) { + AnalyzeRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.experiment_id_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull AnalyzeRequest_class_data_ = + AnalyzeRequest::InternalGenerateClassData_(AnalyzeRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +AnalyzeRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&AnalyzeRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(AnalyzeRequest_class_data_.tc_table); + return AnalyzeRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +AnalyzeRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&AnalyzeRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&AnalyzeRequest_globals_)); + return AnalyzeRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const AnalyzeRequest::ParseTableT_ + AnalyzeRequest::_table_ = + AnalyzeRequest::InternalGenerateParseTable_(AnalyzeRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void AnalyzeRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.AnalyzeRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.experiment_id_.ClearNonDefaultToEmpty(); + } + this_._impl_.expected_revision_ = ::uint64_t{0u}; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL AnalyzeRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const AnalyzeRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL AnalyzeRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const AnalyzeRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.AnalyzeRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + const ::std::string& _s = this_._internal_experiment_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.AnalyzeRequest.experiment_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_expected_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_expected_revision(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.AnalyzeRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t AnalyzeRequest::ByteSizeLong(const MessageLite& base) { + const AnalyzeRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t AnalyzeRequest::ByteSizeLong() const { + const AnalyzeRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.AnalyzeRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_experiment_id()); + } + } + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_expected_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_expected_revision()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void AnalyzeRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.AnalyzeRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_experiment_id().empty()) { + _this->_internal_set_experiment_id(from._internal_experiment_id()); + } else { + if (_this->_impl_.experiment_id_.IsDefault()) { + _this->_internal_set_experiment_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (from._internal_expected_revision() != 0) { + _this->_impl_.expected_revision_ = from._impl_.expected_revision_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void AnalyzeRequest::CopyFrom(const AnalyzeRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.AnalyzeRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void AnalyzeRequest::InternalSwap(AnalyzeRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.experiment_id_, &other->_impl_.experiment_id_, arena); + swap(_impl_.expected_revision_, other->_impl_.expected_revision_); +} + +::google::protobuf::Metadata AnalyzeRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void AnalyzeResponse::clear_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evidence_ != nullptr) _impl_.evidence_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +AnalyzeResponse::AnalyzeResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, AnalyzeResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.AnalyzeResponse) +} +PROTOBUF_NDEBUG_INLINE AnalyzeResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::AnalyzeResponse& from_msg) + : _has_bits_{from._has_bits_} {} + +AnalyzeResponse::AnalyzeResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const AnalyzeResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, AnalyzeResponse_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + AnalyzeResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.evidence_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? Super_::CopyConstruct(arena, *from._impl_.evidence_) + : nullptr; + _impl_.outcome_ = from._impl_.outcome_; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.AnalyzeResponse) +} +PROTOBUF_NDEBUG_INLINE AnalyzeResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void AnalyzeResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, evidence_), + 0, + offsetof(Impl_, outcome_) - + offsetof(Impl_, evidence_) + + sizeof(Impl_::outcome_)); +} +AnalyzeResponse::~AnalyzeResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.AnalyzeResponse) + SharedDtor(*this); +} +inline void AnalyzeResponse::SharedDtor(MessageLite& self) { + AnalyzeResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.evidence_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull AnalyzeResponse_class_data_ = + AnalyzeResponse::InternalGenerateClassData_(AnalyzeResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +AnalyzeResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&AnalyzeResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(AnalyzeResponse_class_data_.tc_table); + return AnalyzeResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +AnalyzeResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&AnalyzeResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&AnalyzeResponse_globals_)); + return AnalyzeResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const AnalyzeResponse::ParseTableT_ + AnalyzeResponse::_table_ = + AnalyzeResponse::InternalGenerateParseTable_(AnalyzeResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void AnalyzeResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.AnalyzeResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(this_._impl_.evidence_ != nullptr); + this_._impl_.evidence_->Clear(); + } + this_._impl_.outcome_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL AnalyzeResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const AnalyzeResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL AnalyzeResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const AnalyzeResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.AnalyzeResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.Evidence evidence = 1 [json_name = "evidence"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.evidence_, this_._impl_.evidence_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.Outcome outcome = 2 [json_name = "outcome"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_outcome() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_outcome(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.AnalyzeResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t AnalyzeResponse::ByteSizeLong(const MessageLite& base) { + const AnalyzeResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t AnalyzeResponse::ByteSizeLong() const { + const AnalyzeResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.AnalyzeResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + // .xtcp_treatment.v1.Evidence evidence = 1 [json_name = "evidence"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.evidence_); + } + // .xtcp_treatment.v1.Outcome outcome = 2 [json_name = "outcome"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_outcome() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_outcome()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void AnalyzeResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.AnalyzeResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.evidence_ != nullptr); + if (_this->_impl_.evidence_ == nullptr) { + _this->_impl_.evidence_ = Super_::CopyConstruct(arena, *from._impl_.evidence_); + } else { + _this->_impl_.evidence_->MergeFrom(*from._impl_.evidence_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (from._internal_outcome() != 0) { + _this->_impl_.outcome_ = from._impl_.outcome_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void AnalyzeResponse::CopyFrom(const AnalyzeResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.AnalyzeResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void AnalyzeResponse::InternalSwap(AnalyzeResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_.outcome_) + + sizeof(AnalyzeResponse::_impl_.outcome_) + - PROTOBUF_FIELD_OFFSET(AnalyzeResponse, _impl_.evidence_)>( + reinterpret_cast(&_impl_.evidence_), + reinterpret_cast(&other->_impl_.evidence_)); +} + +::google::protobuf::Metadata AnalyzeResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void ReviewRequest::clear_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evidence_ != nullptr) _impl_.evidence_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +ReviewRequest::ReviewRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ReviewRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ReviewRequest) +} +PROTOBUF_NDEBUG_INLINE ReviewRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::ReviewRequest& from_msg) + : _has_bits_{from._has_bits_}, + experiment_id_(arena, from.experiment_id_), + reason_(arena, from.reason_), + request_id_(arena, from.request_id_) {} + +ReviewRequest::ReviewRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ReviewRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ReviewRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ReviewRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.evidence_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.evidence_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, expected_revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, expected_revision_), + offsetof(Impl_, approve_) - + offsetof(Impl_, expected_revision_) + + sizeof(Impl_::approve_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.ReviewRequest) +} +PROTOBUF_NDEBUG_INLINE ReviewRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : experiment_id_(arena), + reason_(arena), + request_id_(arena) {} + +inline void ReviewRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, evidence_), + 0, + offsetof(Impl_, approve_) - + offsetof(Impl_, evidence_) + + sizeof(Impl_::approve_)); +} +ReviewRequest::~ReviewRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ReviewRequest) + SharedDtor(*this); +} +inline void ReviewRequest::SharedDtor(MessageLite& self) { + ReviewRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.experiment_id_.Destroy(); + this_._impl_.reason_.Destroy(); + this_._impl_.request_id_.Destroy(); + delete this_._impl_.evidence_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ReviewRequest_class_data_ = + ReviewRequest::InternalGenerateClassData_(ReviewRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ReviewRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ReviewRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ReviewRequest_class_data_.tc_table); + return ReviewRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ReviewRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ReviewRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ReviewRequest_globals_)); + return ReviewRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ReviewRequest::ParseTableT_ + ReviewRequest::_table_ = + ReviewRequest::InternalGenerateParseTable_(ReviewRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ReviewRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ReviewRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.experiment_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.reason_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.request_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.evidence_ != nullptr); + this_._impl_.evidence_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000030U)) { + ::memset(&this_._impl_.expected_revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.approve_) - + reinterpret_cast(&this_._impl_.expected_revision_)) + + sizeof(_impl_.approve_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ReviewRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ReviewRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ReviewRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ReviewRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ReviewRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + const ::std::string& _s = this_._internal_experiment_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ReviewRequest.experiment_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_expected_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_expected_revision(), target); + } + } + + // bool approve = 3 [json_name = "approve"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_approve() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_approve(), target); + } + } + + // string reason = 4 [json_name = "reason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_reason().empty()) { + const ::std::string& _s = this_._internal_reason(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ReviewRequest.reason"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + } + + // string request_id = 5 [json_name = "requestId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_request_id().empty()) { + const ::std::string& _s = this_._internal_request_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ReviewRequest.request_id"); + target = stream->WriteStringMaybeAliased(5, _s, target); + } + } + + // .xtcp_treatment.v1.Evidence evidence = 6 [json_name = "evidence"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.evidence_, this_._impl_.evidence_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ReviewRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ReviewRequest::ByteSizeLong(const MessageLite& base) { + const ReviewRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ReviewRequest::ByteSizeLong() const { + const ReviewRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ReviewRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_experiment_id()); + } + } + // string reason = 4 [json_name = "reason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_reason().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_reason()); + } + } + // string request_id = 5 [json_name = "requestId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_request_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_request_id()); + } + } + // .xtcp_treatment.v1.Evidence evidence = 6 [json_name = "evidence"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.evidence_); + } + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_expected_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_expected_revision()); + } + } + // bool approve = 3 [json_name = "approve"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_approve() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ReviewRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ReviewRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_experiment_id().empty()) { + _this->_internal_set_experiment_id(from._internal_experiment_id()); + } else { + if (_this->_impl_.experiment_id_.IsDefault()) { + _this->_internal_set_experiment_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_reason().empty()) { + _this->_internal_set_reason(from._internal_reason()); + } else { + if (_this->_impl_.reason_.IsDefault()) { + _this->_internal_set_reason(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_request_id().empty()) { + _this->_internal_set_request_id(from._internal_request_id()); + } else { + if (_this->_impl_.request_id_.IsDefault()) { + _this->_internal_set_request_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.evidence_ != nullptr); + if (_this->_impl_.evidence_ == nullptr) { + _this->_impl_.evidence_ = Super_::CopyConstruct(arena, *from._impl_.evidence_); + } else { + _this->_impl_.evidence_->MergeFrom(*from._impl_.evidence_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_expected_revision() != 0) { + _this->_impl_.expected_revision_ = from._impl_.expected_revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (from._internal_approve() != 0) { + _this->_impl_.approve_ = from._impl_.approve_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ReviewRequest::CopyFrom(const ReviewRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ReviewRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ReviewRequest::InternalSwap(ReviewRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.experiment_id_, &other->_impl_.experiment_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.reason_, &other->_impl_.reason_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.request_id_, &other->_impl_.request_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.approve_) + + sizeof(ReviewRequest::_impl_.approve_) + - PROTOBUF_FIELD_OFFSET(ReviewRequest, _impl_.evidence_)>( + reinterpret_cast(&_impl_.evidence_), + reinterpret_cast(&other->_impl_.evidence_)); +} + +::google::protobuf::Metadata ReviewRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void ReviewResponse::clear_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.experiment_ != nullptr) _impl_.experiment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +ReviewResponse::ReviewResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ReviewResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ReviewResponse) +} +PROTOBUF_NDEBUG_INLINE ReviewResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::ReviewResponse& from_msg) + : _has_bits_{from._has_bits_} {} + +ReviewResponse::ReviewResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ReviewResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ReviewResponse_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ReviewResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.experiment_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? Super_::CopyConstruct(arena, *from._impl_.experiment_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.ReviewResponse) +} +PROTOBUF_NDEBUG_INLINE ReviewResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void ReviewResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.experiment_ = {}; +} +ReviewResponse::~ReviewResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ReviewResponse) + SharedDtor(*this); +} +inline void ReviewResponse::SharedDtor(MessageLite& self) { + ReviewResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.experiment_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ReviewResponse_class_data_ = + ReviewResponse::InternalGenerateClassData_(ReviewResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ReviewResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ReviewResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ReviewResponse_class_data_.tc_table); + return ReviewResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ReviewResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ReviewResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ReviewResponse_globals_)); + return ReviewResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ReviewResponse::ParseTableT_ + ReviewResponse::_table_ = + ReviewResponse::InternalGenerateParseTable_(ReviewResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ReviewResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ReviewResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(this_._impl_.experiment_ != nullptr); + this_._impl_.experiment_->Clear(); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ReviewResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ReviewResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ReviewResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ReviewResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ReviewResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.experiment_, this_._impl_.experiment_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ReviewResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ReviewResponse::ByteSizeLong(const MessageLite& base) { + const ReviewResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ReviewResponse::ByteSizeLong() const { + const ReviewResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ReviewResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + { + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.experiment_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ReviewResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ReviewResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.experiment_ != nullptr); + if (_this->_impl_.experiment_ == nullptr) { + _this->_impl_.experiment_ = Super_::CopyConstruct(arena, *from._impl_.experiment_); + } else { + _this->_impl_.experiment_->MergeFrom(*from._impl_.experiment_); + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ReviewResponse::CopyFrom(const ReviewResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ReviewResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ReviewResponse::InternalSwap(ReviewResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.experiment_, other->_impl_.experiment_); +} + +::google::protobuf::Metadata ReviewResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +ControlRequest::ControlRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ControlRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ControlRequest) +} +PROTOBUF_NDEBUG_INLINE ControlRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::ControlRequest& from_msg) + : _has_bits_{from._has_bits_}, + experiment_id_(arena, from.experiment_id_), + agent_id_(arena, from.agent_id_), + location_(arena, from.location_), + reason_(arena, from.reason_), + request_id_(arena, from.request_id_) {} + +ControlRequest::ControlRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ControlRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ControlRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ControlRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, fleet_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, fleet_), + offsetof(Impl_, action_) - + offsetof(Impl_, fleet_) + + sizeof(Impl_::action_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.ControlRequest) +} +PROTOBUF_NDEBUG_INLINE ControlRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : experiment_id_(arena), + agent_id_(arena), + location_(arena), + reason_(arena), + request_id_(arena) {} + +inline void ControlRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, fleet_), + 0, + offsetof(Impl_, action_) - + offsetof(Impl_, fleet_) + + sizeof(Impl_::action_)); +} +ControlRequest::~ControlRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ControlRequest) + SharedDtor(*this); +} +inline void ControlRequest::SharedDtor(MessageLite& self) { + ControlRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.experiment_id_.Destroy(); + this_._impl_.agent_id_.Destroy(); + this_._impl_.location_.Destroy(); + this_._impl_.reason_.Destroy(); + this_._impl_.request_id_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ControlRequest_class_data_ = + ControlRequest::InternalGenerateClassData_(ControlRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ControlRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ControlRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ControlRequest_class_data_.tc_table); + return ControlRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ControlRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ControlRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ControlRequest_globals_)); + return ControlRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ControlRequest::ParseTableT_ + ControlRequest::_table_ = + ControlRequest::InternalGenerateParseTable_(ControlRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ControlRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ControlRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.experiment_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.location_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + this_._impl_.reason_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + this_._impl_.request_id_.ClearNonDefaultToEmpty(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000060U)) { + ::memset(&this_._impl_.fleet_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.action_) - + reinterpret_cast(&this_._impl_.fleet_)) + + sizeof(_impl_.action_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ControlRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ControlRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ControlRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ControlRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ControlRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + const ::std::string& _s = this_._internal_experiment_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ControlRequest.experiment_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ControlRequest.agent_id"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + // string location = 3 [json_name = "location", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_location().empty()) { + const ::std::string& _s = this_._internal_location(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ControlRequest.location"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + } + + // bool fleet = 4 [json_name = "fleet"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_fleet() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 4, this_._internal_fleet(), target); + } + } + + // .xtcp_treatment.v1.ControlAction action = 5 [json_name = "action", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (this_._internal_action() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this_._internal_action(), target); + } + } + + // string reason = 6 [json_name = "reason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_reason().empty()) { + const ::std::string& _s = this_._internal_reason(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ControlRequest.reason"); + target = stream->WriteStringMaybeAliased(6, _s, target); + } + } + + // string request_id = 7 [json_name = "requestId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_request_id().empty()) { + const ::std::string& _s = this_._internal_request_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ControlRequest.request_id"); + target = stream->WriteStringMaybeAliased(7, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ControlRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ControlRequest::ByteSizeLong(const MessageLite& base) { + const ControlRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ControlRequest::ByteSizeLong() const { + const ControlRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ControlRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000007fU)) { + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_experiment_id()); + } + } + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + // string location = 3 [json_name = "location", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_location().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_location()); + } + } + // string reason = 6 [json_name = "reason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_reason().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_reason()); + } + } + // string request_id = 7 [json_name = "requestId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_request_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_request_id()); + } + } + // bool fleet = 4 [json_name = "fleet"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_fleet() != 0) { + total_size += 2; + } + } + // .xtcp_treatment.v1.ControlAction action = 5 [json_name = "action", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (this_._internal_action() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_action()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ControlRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ControlRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000007fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_experiment_id().empty()) { + _this->_internal_set_experiment_id(from._internal_experiment_id()); + } else { + if (_this->_impl_.experiment_id_.IsDefault()) { + _this->_internal_set_experiment_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_location().empty()) { + _this->_internal_set_location(from._internal_location()); + } else { + if (_this->_impl_.location_.IsDefault()) { + _this->_internal_set_location(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!from._internal_reason().empty()) { + _this->_internal_set_reason(from._internal_reason()); + } else { + if (_this->_impl_.reason_.IsDefault()) { + _this->_internal_set_reason(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!from._internal_request_id().empty()) { + _this->_internal_set_request_id(from._internal_request_id()); + } else { + if (_this->_impl_.request_id_.IsDefault()) { + _this->_internal_set_request_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (from._internal_fleet() != 0) { + _this->_impl_.fleet_ = from._impl_.fleet_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (from._internal_action() != 0) { + _this->_impl_.action_ = from._impl_.action_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ControlRequest::CopyFrom(const ControlRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ControlRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ControlRequest::InternalSwap(ControlRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.experiment_id_, &other->_impl_.experiment_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.location_, &other->_impl_.location_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.reason_, &other->_impl_.reason_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.request_id_, &other->_impl_.request_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.action_) + + sizeof(ControlRequest::_impl_.action_) + - PROTOBUF_FIELD_OFFSET(ControlRequest, _impl_.fleet_)>( + reinterpret_cast(&_impl_.fleet_), + reinterpret_cast(&other->_impl_.fleet_)); +} + +::google::protobuf::Metadata ControlRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +ControlResponse::ControlResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ControlResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ControlResponse) +} +ControlResponse::ControlResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ControlResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ControlResponse_get_class_data()), +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} +PROTOBUF_NDEBUG_INLINE ControlResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void ControlResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.affected_agents_ = {}; +} +ControlResponse::~ControlResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ControlResponse) + SharedDtor(*this); +} +inline void ControlResponse::SharedDtor(MessageLite& self) { + ControlResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ControlResponse_class_data_ = + ControlResponse::InternalGenerateClassData_(ControlResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ControlResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ControlResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ControlResponse_class_data_.tc_table); + return ControlResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ControlResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ControlResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ControlResponse_globals_)); + return ControlResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ControlResponse::ParseTableT_ + ControlResponse::_table_ = + ControlResponse::InternalGenerateParseTable_(ControlResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ControlResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ControlResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + this_._impl_.affected_agents_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ControlResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ControlResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ControlResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ControlResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ControlResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // uint32 affected_agents = 1 [json_name = "affectedAgents"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (this_._internal_affected_agents() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_affected_agents(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ControlResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ControlResponse::ByteSizeLong(const MessageLite& base) { + const ControlResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ControlResponse::ByteSizeLong() const { + const ControlResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ControlResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + { + // uint32 affected_agents = 1 [json_name = "affectedAgents"]; + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (this_._internal_affected_agents() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_affected_agents()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ControlResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ControlResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (from._internal_affected_agents() != 0) { + _this->_impl_.affected_agents_ = from._impl_.affected_agents_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ControlResponse::CopyFrom(const ControlResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ControlResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ControlResponse::InternalSwap(ControlResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + swap(_impl_.affected_agents_, other->_impl_.affected_agents_); +} + +::google::protobuf::Metadata ControlResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +InspectRequest::InspectRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, InspectRequest_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.InspectRequest) +} +PROTOBUF_NDEBUG_INLINE InspectRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::InspectRequest& from_msg) + : _has_bits_{from._has_bits_}, + experiment_id_(arena, from.experiment_id_), + agent_id_(arena, from.agent_id_) {} + +InspectRequest::InspectRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InspectRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, InspectRequest_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InspectRequest* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.InspectRequest) +} +PROTOBUF_NDEBUG_INLINE InspectRequest::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : experiment_id_(arena), + agent_id_(arena) {} + +inline void InspectRequest::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +InspectRequest::~InspectRequest() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.InspectRequest) + SharedDtor(*this); +} +inline void InspectRequest::SharedDtor(MessageLite& self) { + InspectRequest& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.experiment_id_.Destroy(); + this_._impl_.agent_id_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InspectRequest_class_data_ = + InspectRequest::InternalGenerateClassData_(InspectRequest_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InspectRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InspectRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InspectRequest_class_data_.tc_table); + return InspectRequest_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InspectRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InspectRequest_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&InspectRequest_globals_)); + return InspectRequest_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const InspectRequest::ParseTableT_ + InspectRequest::_table_ = + InspectRequest::InternalGenerateParseTable_(InspectRequest_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void InspectRequest::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.InspectRequest) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.experiment_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InspectRequest::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InspectRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InspectRequest::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InspectRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.InspectRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + const ::std::string& _s = this_._internal_experiment_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.InspectRequest.experiment_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.InspectRequest.agent_id"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.InspectRequest) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InspectRequest::ByteSizeLong(const MessageLite& base) { + const InspectRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InspectRequest::ByteSizeLong() const { + const InspectRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.InspectRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_experiment_id()); + } + } + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InspectRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.InspectRequest) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_experiment_id().empty()) { + _this->_internal_set_experiment_id(from._internal_experiment_id()); + } else { + if (_this->_impl_.experiment_id_.IsDefault()) { + _this->_internal_set_experiment_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void InspectRequest::CopyFrom(const InspectRequest& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.InspectRequest) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InspectRequest::InternalSwap(InspectRequest* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.experiment_id_, &other->_impl_.experiment_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); +} + +::google::protobuf::Metadata InspectRequest::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void InspectResponse::clear_experiments() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiments_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +void InspectResponse::clear_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.desired_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +void InspectResponse::clear_observed() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.observed_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +InspectResponse::InspectResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, InspectResponse_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.InspectResponse) +} +PROTOBUF_NDEBUG_INLINE InspectResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::InspectResponse& from_msg) + : _has_bits_{from._has_bits_}, + experiments_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.experiments_)>() + , arena, from.experiments_ + } + , + desired_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.desired_)>() + , arena, from.desired_ + } + , + observed_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.observed_)>() + , arena, from.observed_ + } + {} + +InspectResponse::InspectResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const InspectResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, InspectResponse_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + InspectResponse* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.InspectResponse) +} +PROTOBUF_NDEBUG_INLINE InspectResponse::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : experiments_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.experiments_)>() + } + , + desired_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.desired_)>() + } + , + observed_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::InspectResponse, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::InspectResponse, _impl_.observed_)>() + } + {} + +inline void InspectResponse::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +InspectResponse::~InspectResponse() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.InspectResponse) + SharedDtor(*this); +} +inline void InspectResponse::SharedDtor(MessageLite& self) { + InspectResponse& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull InspectResponse_class_data_ = + InspectResponse::InternalGenerateClassData_(InspectResponse_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InspectResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InspectResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(InspectResponse_class_data_.tc_table); + return InspectResponse_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +InspectResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&InspectResponse_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&InspectResponse_globals_)); + return InspectResponse_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const InspectResponse::ParseTableT_ + InspectResponse::_table_ = + InspectResponse::InternalGenerateParseTable_(InspectResponse_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void InspectResponse::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.InspectResponse) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.experiments_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + _impl_.desired_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + _impl_.observed_.Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL InspectResponse::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const InspectResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL InspectResponse::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const InspectResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.InspectResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // repeated .xtcp_treatment.v1.Experiment experiments = 1 [json_name = "experiments"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_experiments_size()); + i < n; i++) { + const auto& repfield = this_._internal_experiments().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // repeated .xtcp_treatment.v1.DesiredState desired = 2 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_desired_size()); + i < n; i++) { + const auto& repfield = this_._internal_desired().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // repeated .xtcp_treatment.v1.CheckInRequest observed = 3 [json_name = "observed"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_observed_size()); + i < n; i++) { + const auto& repfield = this_._internal_observed().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.InspectResponse) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t InspectResponse::ByteSizeLong(const MessageLite& base) { + const InspectResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t InspectResponse::ByteSizeLong() const { + const InspectResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.InspectResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + // repeated .xtcp_treatment.v1.Experiment experiments = 1 [json_name = "experiments"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_experiments_size(); + for (const auto& msg : this_._internal_experiments()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .xtcp_treatment.v1.DesiredState desired = 2 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1UL * this_._internal_desired_size(); + for (const auto& msg : this_._internal_desired()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .xtcp_treatment.v1.CheckInRequest observed = 3 [json_name = "observed"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1UL * this_._internal_observed_size(); + for (const auto& msg : this_._internal_observed()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void InspectResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.InspectResponse) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_experiments()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_experiments()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + _this->_internal_mutable_desired()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_desired()); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + _this->_internal_mutable_observed()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_observed()); + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void InspectResponse::CopyFrom(const InspectResponse& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.InspectResponse) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void InspectResponse::InternalSwap(InspectResponse* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.experiments_.InternalSwap(&other->_impl_.experiments_); + _impl_.desired_.InternalSwap(&other->_impl_.desired_); + _impl_.observed_.InternalSwap(&other->_impl_.observed_); +} + +::google::protobuf::Metadata InspectResponse::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ [[maybe_unused]] = + (::_pbi::AddDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto), + ::std::false_type{}); +#include "google/protobuf/port_undef.inc" diff --git a/gen/cpp/xtcp_treatment/v1/operator.pb.h b/gen/cpp/xtcp_treatment/v1/operator.pb.h new file mode 100644 index 000000000..57c204eab --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/operator.pb.h @@ -0,0 +1,4157 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment/v1/operator.proto +// Protobuf C++ Version: 7.36.2 + +#ifndef xtcp_5ftreatment_2fv1_2foperator_2eproto_2epb_2eh +#define xtcp_5ftreatment_2fv1_2foperator_2eproto_2epb_2eh + +#include +#include +#include +#include + +// clang-format off +#include "google/protobuf/runtime_version.h" +#if PROTOBUF_VERSION != 7036002 +#error "Protobuf C++ gencode is built with an incompatible version of" +#error "Protobuf C++ headers/runtime. See" +#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" +#endif +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/generated_enum_reflection.h" +#include "google/protobuf/unknown_field_set.h" +#include "buf/validate/validate.pb.h" +#include "xtcp_treatment/v1/agent.pb.h" +#include "xtcp_treatment/v1/treatment.pb.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_xtcp_5ftreatment_2fv1_2foperator_2eproto + +// Internal implementation detail -- do not use these members. +struct TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto { + static const ::uint32_t offsets[]; +}; +extern "C" { +extern const ::google::protobuf::internal::DescriptorTable descriptor_table_xtcp_5ftreatment_2fv1_2foperator_2eproto; +} // extern "C" +namespace xtcp_treatment { +namespace v1 { +enum ControlAction : int; +extern const uint32_t ControlAction_internal_data_[]; +class AnalyzeRequest; +struct AnalyzeRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern AnalyzeRequestGlobalsTypeInternal AnalyzeRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull AnalyzeRequest_class_data_; +#else +extern const AnalyzeRequestGlobalsTypeInternal AnalyzeRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class AnalyzeResponse; +struct AnalyzeResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern AnalyzeResponseGlobalsTypeInternal AnalyzeResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull AnalyzeResponse_class_data_; +#else +extern const AnalyzeResponseGlobalsTypeInternal AnalyzeResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class ControlRequest; +struct ControlRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ControlRequestGlobalsTypeInternal ControlRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull ControlRequest_class_data_; +#else +extern const ControlRequestGlobalsTypeInternal ControlRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class ControlResponse; +struct ControlResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ControlResponseGlobalsTypeInternal ControlResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull ControlResponse_class_data_; +#else +extern const ControlResponseGlobalsTypeInternal ControlResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class InspectRequest; +struct InspectRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern InspectRequestGlobalsTypeInternal InspectRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull InspectRequest_class_data_; +#else +extern const InspectRequestGlobalsTypeInternal InspectRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class InspectResponse; +struct InspectResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern InspectResponseGlobalsTypeInternal InspectResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull InspectResponse_class_data_; +#else +extern const InspectResponseGlobalsTypeInternal InspectResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class ProposeRequest; +struct ProposeRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ProposeRequestGlobalsTypeInternal ProposeRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull ProposeRequest_class_data_; +#else +extern const ProposeRequestGlobalsTypeInternal ProposeRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class ProposeResponse; +struct ProposeResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ProposeResponseGlobalsTypeInternal ProposeResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull ProposeResponse_class_data_; +#else +extern const ProposeResponseGlobalsTypeInternal ProposeResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class ReviewRequest; +struct ReviewRequestGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ReviewRequestGlobalsTypeInternal ReviewRequest_globals_; +extern const ::google::protobuf::internal::ClassDataFull ReviewRequest_class_data_; +#else +extern const ReviewRequestGlobalsTypeInternal ReviewRequest_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class ReviewResponse; +struct ReviewResponseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ReviewResponseGlobalsTypeInternal ReviewResponse_globals_; +extern const ::google::protobuf::internal::ClassDataFull ReviewResponse_class_data_; +#else +extern const ReviewResponseGlobalsTypeInternal ReviewResponse_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +} // namespace v1 +} // namespace xtcp_treatment +namespace google { +namespace protobuf { +template <> +internal::EnumTraitsT<::xtcp_treatment::v1::ControlAction_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment::v1::ControlAction>; +} // namespace protobuf +} // namespace google + +namespace xtcp_treatment { +namespace v1 { +enum ControlAction : int { + CONTROL_ACTION_UNSPECIFIED = 0, + CONTROL_ACTION_PAUSE = 1, + CONTROL_ACTION_SUSPEND = 2, + CONTROL_ACTION_RESUME = 3, + CONTROL_ACTION_ROLLBACK = 4, + CONTROL_ACTION_RETIRE = 5, + ControlAction_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + ControlAction_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t ControlAction_internal_data_[]; +inline constexpr ControlAction ControlAction_MIN = + static_cast(0); +inline constexpr ControlAction ControlAction_MAX = + static_cast(5); +[[nodiscard]] inline bool ControlAction_IsValid(int value) { + return 0 <= value && value <= 5; +} +inline constexpr int ControlAction_ARRAYSIZE = 5 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ControlAction_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(ControlAction) { + return ControlAction_descriptor(); +} +template +[[nodiscard]] const ::std::string& ControlAction_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to ControlAction_Name()."); + return ControlAction_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& ControlAction_Name(ControlAction value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool ControlAction_Parse( + ::absl::string_view name, ControlAction* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(ControlAction_descriptor(), name, + value); +} +using ::google::protobuf::internal::generated_enum::AbslParseFlag; +using ::google::protobuf::internal::generated_enum::AbslUnparseFlag; + +// =================================================================== + + +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED InspectRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.InspectRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline InspectRequest() : InspectRequest(nullptr) {} + ~InspectRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InspectRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InspectRequest)); + } +#endif + + template + explicit constexpr InspectRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline InspectRequest(const InspectRequest& from) : InspectRequest(nullptr, from) {} + inline InspectRequest(InspectRequest&& from) noexcept : InspectRequest(nullptr, ::std::move(from)) {} + inline InspectRequest& operator=(const InspectRequest& from) { + CopyFrom(from); + return *this; + } + inline InspectRequest& operator=(InspectRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const InspectRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&InspectRequest_globals_); + } + static constexpr int kIndexInFileMessages = 8; + friend void swap(InspectRequest& a, InspectRequest& b) { a.Swap(&b); } + inline void Swap(InspectRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InspectRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] InspectRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const InspectRequest& from); + using Super_::MergeFrom; + void MergeFrom(const InspectRequest& from) { InspectRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InspectRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.InspectRequest"; } + + explicit InspectRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InspectRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InspectRequest& from); + InspectRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InspectRequest&& from) noexcept + : InspectRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentIdFieldNumber = 1, + kAgentIdFieldNumber = 2, + }; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + void clear_experiment_id() ; + [[nodiscard]] const ::std::string& experiment_id() const; + template + void set_experiment_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_experiment_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_experiment_id(); + void set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_experiment_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_experiment_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_experiment_id(); + + public: + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.InspectRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<1, 2, + 0, 62, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InspectRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr experiment_id_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ControlResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ControlResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ControlResponse() : ControlResponse(nullptr) {} + ~ControlResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ControlResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ControlResponse)); + } +#endif + + template + explicit constexpr ControlResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ControlResponse(const ControlResponse& from) : ControlResponse(nullptr, from) {} + inline ControlResponse(ControlResponse&& from) noexcept : ControlResponse(nullptr, ::std::move(from)) {} + inline ControlResponse& operator=(const ControlResponse& from) { + CopyFrom(from); + return *this; + } + inline ControlResponse& operator=(ControlResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ControlResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ControlResponse_globals_); + } + static constexpr int kIndexInFileMessages = 7; + friend void swap(ControlResponse& a, ControlResponse& b) { a.Swap(&b); } + inline void Swap(ControlResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ControlResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ControlResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ControlResponse& from); + using Super_::MergeFrom; + void MergeFrom(const ControlResponse& from) { ControlResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ControlResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ControlResponse"; } + + explicit ControlResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ControlResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ControlResponse& from); + ControlResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ControlResponse&& from) noexcept + : ControlResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kAffectedAgentsFieldNumber = 1, + }; + // uint32 affected_agents = 1 [json_name = "affectedAgents"]; + void clear_affected_agents() ; + [[nodiscard]] ::uint32_t affected_agents() const; + void set_affected_agents(::uint32_t value); + + private: + ::uint32_t _internal_affected_agents() const; + void _internal_set_affected_agents(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ControlResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<0, 1, + 0, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ControlResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::uint32_t affected_agents_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ControlRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ControlRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ControlRequest() : ControlRequest(nullptr) {} + ~ControlRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ControlRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ControlRequest)); + } +#endif + + template + explicit constexpr ControlRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ControlRequest(const ControlRequest& from) : ControlRequest(nullptr, from) {} + inline ControlRequest(ControlRequest&& from) noexcept : ControlRequest(nullptr, ::std::move(from)) {} + inline ControlRequest& operator=(const ControlRequest& from) { + CopyFrom(from); + return *this; + } + inline ControlRequest& operator=(ControlRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ControlRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ControlRequest_globals_); + } + static constexpr int kIndexInFileMessages = 6; + friend void swap(ControlRequest& a, ControlRequest& b) { a.Swap(&b); } + inline void Swap(ControlRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ControlRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ControlRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ControlRequest& from); + using Super_::MergeFrom; + void MergeFrom(const ControlRequest& from) { ControlRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ControlRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ControlRequest"; } + + explicit ControlRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ControlRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ControlRequest& from); + ControlRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ControlRequest&& from) noexcept + : ControlRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentIdFieldNumber = 1, + kAgentIdFieldNumber = 2, + kLocationFieldNumber = 3, + kReasonFieldNumber = 6, + kRequestIdFieldNumber = 7, + kFleetFieldNumber = 4, + kActionFieldNumber = 5, + }; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + void clear_experiment_id() ; + [[nodiscard]] const ::std::string& experiment_id() const; + template + void set_experiment_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_experiment_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_experiment_id(); + void set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_experiment_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_experiment_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_experiment_id(); + + public: + // string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // string location = 3 [json_name = "location", (.buf.validate.field) = { + void clear_location() ; + [[nodiscard]] const ::std::string& location() const; + template + void set_location(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_location(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_location(); + void set_allocated_location(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_location() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_location(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_location(); + + public: + // string reason = 6 [json_name = "reason", (.buf.validate.field) = { + void clear_reason() ; + [[nodiscard]] const ::std::string& reason() const; + template + void set_reason(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_reason(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_reason(); + void set_allocated_reason(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_reason() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_reason(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_reason(); + + public: + // string request_id = 7 [json_name = "requestId", (.buf.validate.field) = { + void clear_request_id() ; + [[nodiscard]] const ::std::string& request_id() const; + template + void set_request_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_request_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_request_id(); + void set_allocated_request_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_request_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_request_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_request_id(); + + public: + // bool fleet = 4 [json_name = "fleet"]; + void clear_fleet() ; + [[nodiscard]] bool fleet() const; + void set_fleet(bool value); + + private: + bool _internal_fleet() const; + void _internal_set_fleet(bool value); + + public: + // .xtcp_treatment.v1.ControlAction action = 5 [json_name = "action", (.buf.validate.field) = { + void clear_action() ; + [[nodiscard]] ::xtcp_treatment::v1::ControlAction action() const; + void set_action(::xtcp_treatment::v1::ControlAction value); + + private: + ::xtcp_treatment::v1::ControlAction _internal_action() const; + void _internal_set_action(::xtcp_treatment::v1::ControlAction value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ControlRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 7, + 0, 86, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ControlRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr experiment_id_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + ::google::protobuf::internal::ArenaStringPtr location_; + ::google::protobuf::internal::ArenaStringPtr reason_; + ::google::protobuf::internal::ArenaStringPtr request_id_; + bool fleet_; + int action_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED AnalyzeRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.AnalyzeRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline AnalyzeRequest() : AnalyzeRequest(nullptr) {} + ~AnalyzeRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(AnalyzeRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(AnalyzeRequest)); + } +#endif + + template + explicit constexpr AnalyzeRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline AnalyzeRequest(const AnalyzeRequest& from) : AnalyzeRequest(nullptr, from) {} + inline AnalyzeRequest(AnalyzeRequest&& from) noexcept : AnalyzeRequest(nullptr, ::std::move(from)) {} + inline AnalyzeRequest& operator=(const AnalyzeRequest& from) { + CopyFrom(from); + return *this; + } + inline AnalyzeRequest& operator=(AnalyzeRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const AnalyzeRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&AnalyzeRequest_globals_); + } + static constexpr int kIndexInFileMessages = 2; + friend void swap(AnalyzeRequest& a, AnalyzeRequest& b) { a.Swap(&b); } + inline void Swap(AnalyzeRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AnalyzeRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] AnalyzeRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const AnalyzeRequest& from); + using Super_::MergeFrom; + void MergeFrom(const AnalyzeRequest& from) { AnalyzeRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(AnalyzeRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.AnalyzeRequest"; } + + explicit AnalyzeRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + AnalyzeRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const AnalyzeRequest& from); + AnalyzeRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, AnalyzeRequest&& from) noexcept + : AnalyzeRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentIdFieldNumber = 1, + kExpectedRevisionFieldNumber = 2, + }; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + void clear_experiment_id() ; + [[nodiscard]] const ::std::string& experiment_id() const; + template + void set_experiment_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_experiment_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_experiment_id(); + void set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_experiment_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_experiment_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_experiment_id(); + + public: + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + void clear_expected_revision() ; + [[nodiscard]] ::uint64_t expected_revision() const; + void set_expected_revision(::uint64_t value); + + private: + ::uint64_t _internal_expected_revision() const; + void _internal_set_expected_revision(::uint64_t value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.AnalyzeRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<1, 2, + 0, 54, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const AnalyzeRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr experiment_id_; + ::uint64_t expected_revision_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ReviewRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ReviewRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ReviewRequest() : ReviewRequest(nullptr) {} + ~ReviewRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ReviewRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ReviewRequest)); + } +#endif + + template + explicit constexpr ReviewRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ReviewRequest(const ReviewRequest& from) : ReviewRequest(nullptr, from) {} + inline ReviewRequest(ReviewRequest&& from) noexcept : ReviewRequest(nullptr, ::std::move(from)) {} + inline ReviewRequest& operator=(const ReviewRequest& from) { + CopyFrom(from); + return *this; + } + inline ReviewRequest& operator=(ReviewRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ReviewRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ReviewRequest_globals_); + } + static constexpr int kIndexInFileMessages = 4; + friend void swap(ReviewRequest& a, ReviewRequest& b) { a.Swap(&b); } + inline void Swap(ReviewRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ReviewRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ReviewRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ReviewRequest& from); + using Super_::MergeFrom; + void MergeFrom(const ReviewRequest& from) { ReviewRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ReviewRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ReviewRequest"; } + + explicit ReviewRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ReviewRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ReviewRequest& from); + ReviewRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ReviewRequest&& from) noexcept + : ReviewRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentIdFieldNumber = 1, + kReasonFieldNumber = 4, + kRequestIdFieldNumber = 5, + kEvidenceFieldNumber = 6, + kExpectedRevisionFieldNumber = 2, + kApproveFieldNumber = 3, + }; + // string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { + void clear_experiment_id() ; + [[nodiscard]] const ::std::string& experiment_id() const; + template + void set_experiment_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_experiment_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_experiment_id(); + void set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_experiment_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_experiment_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_experiment_id(); + + public: + // string reason = 4 [json_name = "reason", (.buf.validate.field) = { + void clear_reason() ; + [[nodiscard]] const ::std::string& reason() const; + template + void set_reason(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_reason(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_reason(); + void set_allocated_reason(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_reason() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_reason(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_reason(); + + public: + // string request_id = 5 [json_name = "requestId", (.buf.validate.field) = { + void clear_request_id() ; + [[nodiscard]] const ::std::string& request_id() const; + template + void set_request_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_request_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_request_id(); + void set_allocated_request_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_request_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_request_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_request_id(); + + public: + // .xtcp_treatment.v1.Evidence evidence = 6 [json_name = "evidence"]; + [[nodiscard]] bool has_evidence() const; + void clear_evidence() ; + [[nodiscard]] const ::xtcp_treatment::v1::Evidence& evidence() const; + [[nodiscard]] ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE release_evidence(); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL mutable_evidence(); + void set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE unsafe_arena_release_evidence(); + + private: + const ::xtcp_treatment::v1::Evidence& _internal_evidence() const; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL _internal_mutable_evidence(); + + public: + // uint64 expected_revision = 2 [json_name = "expectedRevision"]; + void clear_expected_revision() ; + [[nodiscard]] ::uint64_t expected_revision() const; + void set_expected_revision(::uint64_t value); + + private: + ::uint64_t _internal_expected_revision() const; + void _internal_set_expected_revision(::uint64_t value); + + public: + // bool approve = 3 [json_name = "approve"]; + void clear_approve() ; + [[nodiscard]] bool approve() const; + void set_approve(bool value); + + private: + bool _internal_approve() const; + void _internal_set_approve(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ReviewRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 6, + 1, 69, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ReviewRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr experiment_id_; + ::google::protobuf::internal::ArenaStringPtr reason_; + ::google::protobuf::internal::ArenaStringPtr request_id_; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE evidence_; + ::uint64_t expected_revision_; + bool approve_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED AnalyzeResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.AnalyzeResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline AnalyzeResponse() : AnalyzeResponse(nullptr) {} + ~AnalyzeResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(AnalyzeResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(AnalyzeResponse)); + } +#endif + + template + explicit constexpr AnalyzeResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline AnalyzeResponse(const AnalyzeResponse& from) : AnalyzeResponse(nullptr, from) {} + inline AnalyzeResponse(AnalyzeResponse&& from) noexcept : AnalyzeResponse(nullptr, ::std::move(from)) {} + inline AnalyzeResponse& operator=(const AnalyzeResponse& from) { + CopyFrom(from); + return *this; + } + inline AnalyzeResponse& operator=(AnalyzeResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const AnalyzeResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&AnalyzeResponse_globals_); + } + static constexpr int kIndexInFileMessages = 3; + friend void swap(AnalyzeResponse& a, AnalyzeResponse& b) { a.Swap(&b); } + inline void Swap(AnalyzeResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AnalyzeResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] AnalyzeResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const AnalyzeResponse& from); + using Super_::MergeFrom; + void MergeFrom(const AnalyzeResponse& from) { AnalyzeResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(AnalyzeResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.AnalyzeResponse"; } + + explicit AnalyzeResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + AnalyzeResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const AnalyzeResponse& from); + AnalyzeResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, AnalyzeResponse&& from) noexcept + : AnalyzeResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kEvidenceFieldNumber = 1, + kOutcomeFieldNumber = 2, + }; + // .xtcp_treatment.v1.Evidence evidence = 1 [json_name = "evidence"]; + [[nodiscard]] bool has_evidence() const; + void clear_evidence() ; + [[nodiscard]] const ::xtcp_treatment::v1::Evidence& evidence() const; + [[nodiscard]] ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE release_evidence(); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL mutable_evidence(); + void set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE unsafe_arena_release_evidence(); + + private: + const ::xtcp_treatment::v1::Evidence& _internal_evidence() const; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL _internal_mutable_evidence(); + + public: + // .xtcp_treatment.v1.Outcome outcome = 2 [json_name = "outcome"]; + void clear_outcome() ; + [[nodiscard]] ::xtcp_treatment::v1::Outcome outcome() const; + void set_outcome(::xtcp_treatment::v1::Outcome value); + + private: + ::xtcp_treatment::v1::Outcome _internal_outcome() const; + void _internal_set_outcome(::xtcp_treatment::v1::Outcome value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.AnalyzeResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<1, 2, + 1, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const AnalyzeResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE evidence_; + int outcome_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ReviewResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ReviewResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ReviewResponse() : ReviewResponse(nullptr) {} + ~ReviewResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ReviewResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ReviewResponse)); + } +#endif + + template + explicit constexpr ReviewResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ReviewResponse(const ReviewResponse& from) : ReviewResponse(nullptr, from) {} + inline ReviewResponse(ReviewResponse&& from) noexcept : ReviewResponse(nullptr, ::std::move(from)) {} + inline ReviewResponse& operator=(const ReviewResponse& from) { + CopyFrom(from); + return *this; + } + inline ReviewResponse& operator=(ReviewResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ReviewResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ReviewResponse_globals_); + } + static constexpr int kIndexInFileMessages = 5; + friend void swap(ReviewResponse& a, ReviewResponse& b) { a.Swap(&b); } + inline void Swap(ReviewResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ReviewResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ReviewResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ReviewResponse& from); + using Super_::MergeFrom; + void MergeFrom(const ReviewResponse& from) { ReviewResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ReviewResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ReviewResponse"; } + + explicit ReviewResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ReviewResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ReviewResponse& from); + ReviewResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ReviewResponse&& from) noexcept + : ReviewResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentFieldNumber = 1, + }; + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + [[nodiscard]] bool has_experiment() const; + void clear_experiment() ; + [[nodiscard]] const ::xtcp_treatment::v1::Experiment& experiment() const; + [[nodiscard]] ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE release_experiment(); + ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL mutable_experiment(); + void set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE unsafe_arena_release_experiment(); + + private: + const ::xtcp_treatment::v1::Experiment& _internal_experiment() const; + ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL _internal_mutable_experiment(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ReviewResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<0, 1, + 1, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ReviewResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE experiment_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ProposeResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ProposeResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ProposeResponse() : ProposeResponse(nullptr) {} + ~ProposeResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ProposeResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ProposeResponse)); + } +#endif + + template + explicit constexpr ProposeResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ProposeResponse(const ProposeResponse& from) : ProposeResponse(nullptr, from) {} + inline ProposeResponse(ProposeResponse&& from) noexcept : ProposeResponse(nullptr, ::std::move(from)) {} + inline ProposeResponse& operator=(const ProposeResponse& from) { + CopyFrom(from); + return *this; + } + inline ProposeResponse& operator=(ProposeResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ProposeResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ProposeResponse_globals_); + } + static constexpr int kIndexInFileMessages = 1; + friend void swap(ProposeResponse& a, ProposeResponse& b) { a.Swap(&b); } + inline void Swap(ProposeResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ProposeResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ProposeResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ProposeResponse& from); + using Super_::MergeFrom; + void MergeFrom(const ProposeResponse& from) { ProposeResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ProposeResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ProposeResponse"; } + + explicit ProposeResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ProposeResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ProposeResponse& from); + ProposeResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ProposeResponse&& from) noexcept + : ProposeResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentFieldNumber = 1, + }; + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; + [[nodiscard]] bool has_experiment() const; + void clear_experiment() ; + [[nodiscard]] const ::xtcp_treatment::v1::Experiment& experiment() const; + [[nodiscard]] ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE release_experiment(); + ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL mutable_experiment(); + void set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE unsafe_arena_release_experiment(); + + private: + const ::xtcp_treatment::v1::Experiment& _internal_experiment() const; + ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL _internal_mutable_experiment(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ProposeResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<0, 1, + 1, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ProposeResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE experiment_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ProposeRequest final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ProposeRequest) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ProposeRequest() : ProposeRequest(nullptr) {} + ~ProposeRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ProposeRequest* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ProposeRequest)); + } +#endif + + template + explicit constexpr ProposeRequest(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ProposeRequest(const ProposeRequest& from) : ProposeRequest(nullptr, from) {} + inline ProposeRequest(ProposeRequest&& from) noexcept : ProposeRequest(nullptr, ::std::move(from)) {} + inline ProposeRequest& operator=(const ProposeRequest& from) { + CopyFrom(from); + return *this; + } + inline ProposeRequest& operator=(ProposeRequest&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ProposeRequest& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ProposeRequest_globals_); + } + static constexpr int kIndexInFileMessages = 0; + friend void swap(ProposeRequest& a, ProposeRequest& b) { a.Swap(&b); } + inline void Swap(ProposeRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ProposeRequest* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ProposeRequest* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ProposeRequest& from); + using Super_::MergeFrom; + void MergeFrom(const ProposeRequest& from) { ProposeRequest::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ProposeRequest* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ProposeRequest"; } + + explicit ProposeRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ProposeRequest(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ProposeRequest& from); + ProposeRequest( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ProposeRequest&& from) noexcept + : ProposeRequest(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kRequestIdFieldNumber = 2, + kExperimentFieldNumber = 1, + }; + // string request_id = 2 [json_name = "requestId", (.buf.validate.field) = { + void clear_request_id() ; + [[nodiscard]] const ::std::string& request_id() const; + template + void set_request_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_request_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_request_id(); + void set_allocated_request_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_request_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_request_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_request_id(); + + public: + // .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment", (.buf.validate.field) = { + [[nodiscard]] bool has_experiment() const; + void clear_experiment() ; + [[nodiscard]] const ::xtcp_treatment::v1::Experiment& experiment() const; + [[nodiscard]] ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE release_experiment(); + ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL mutable_experiment(); + void set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE unsafe_arena_release_experiment(); + + private: + const ::xtcp_treatment::v1::Experiment& _internal_experiment() const; + ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL _internal_mutable_experiment(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ProposeRequest) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<1, 2, + 1, 51, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ProposeRequest& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr request_id_; + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE experiment_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED InspectResponse final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.InspectResponse) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline InspectResponse() : InspectResponse(nullptr) {} + ~InspectResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(InspectResponse* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(InspectResponse)); + } +#endif + + template + explicit constexpr InspectResponse(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline InspectResponse(const InspectResponse& from) : InspectResponse(nullptr, from) {} + inline InspectResponse(InspectResponse&& from) noexcept : InspectResponse(nullptr, ::std::move(from)) {} + inline InspectResponse& operator=(const InspectResponse& from) { + CopyFrom(from); + return *this; + } + inline InspectResponse& operator=(InspectResponse&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const InspectResponse& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&InspectResponse_globals_); + } + static constexpr int kIndexInFileMessages = 9; + friend void swap(InspectResponse& a, InspectResponse& b) { a.Swap(&b); } + inline void Swap(InspectResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InspectResponse* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] InspectResponse* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const InspectResponse& from); + using Super_::MergeFrom; + void MergeFrom(const InspectResponse& from) { InspectResponse::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(InspectResponse* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.InspectResponse"; } + + explicit InspectResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + InspectResponse(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const InspectResponse& from); + InspectResponse( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, InspectResponse&& from) noexcept + : InspectResponse(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentsFieldNumber = 1, + kDesiredFieldNumber = 2, + kObservedFieldNumber = 3, + }; + // repeated .xtcp_treatment.v1.Experiment experiments = 1 [json_name = "experiments"]; + [[nodiscard]] int experiments_size() const; + private: + int _internal_experiments_size() const; + + public: + void clear_experiments() ; + [[nodiscard]] const ::xtcp_treatment::v1::Experiment& experiments(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL mutable_experiments(int index); + ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL add_experiments(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>& + experiments() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>* PROTOBUF_NONNULL + mutable_experiments(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>& _internal_experiments() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>* PROTOBUF_NONNULL _internal_mutable_experiments(); + + public: + // repeated .xtcp_treatment.v1.DesiredState desired = 2 [json_name = "desired"]; + [[nodiscard]] int desired_size() const; + private: + int _internal_desired_size() const; + + public: + void clear_desired() ; + [[nodiscard]] const ::xtcp_treatment::v1::DesiredState& desired(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL mutable_desired(int index); + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL add_desired(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>& + desired() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>* PROTOBUF_NONNULL + mutable_desired(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>& _internal_desired() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>* PROTOBUF_NONNULL _internal_mutable_desired(); + + public: + // repeated .xtcp_treatment.v1.CheckInRequest observed = 3 [json_name = "observed"]; + [[nodiscard]] int observed_size() const; + private: + int _internal_observed_size() const; + + public: + void clear_observed() ; + [[nodiscard]] const ::xtcp_treatment::v1::CheckInRequest& observed(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::CheckInRequest* PROTOBUF_NONNULL mutable_observed(int index); + ::xtcp_treatment::v1::CheckInRequest* PROTOBUF_NONNULL add_observed(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>& + observed() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>* PROTOBUF_NONNULL + mutable_observed(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>& _internal_observed() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>* PROTOBUF_NONNULL _internal_mutable_observed(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.InspectResponse) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<2, 3, + 3, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const InspectResponse& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::Experiment > experiments_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::DesiredState > desired_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::CheckInRequest > observed_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2foperator_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ProposeRequest + +// .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment", (.buf.validate.field) = { +inline bool ProposeRequest::has_experiment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + PROTOBUF_ASSUME(!value || _impl_.experiment_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::Experiment& ProposeRequest::_internal_experiment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Experiment* p = _impl_.experiment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Experiment>(&::xtcp_treatment::v1::Experiment_globals_); +} +inline const ::xtcp_treatment::v1::Experiment& ProposeRequest::experiment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ProposeRequest.experiment) + return _internal_experiment(); +} +inline void ProposeRequest::unsafe_arena_set_allocated_experiment( + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.experiment_); + } + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ProposeRequest.experiment) +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE ProposeRequest::release_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment::v1::Experiment* released = _impl_.experiment_; + _impl_.experiment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE ProposeRequest::unsafe_arena_release_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ProposeRequest.experiment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment::v1::Experiment* temp = _impl_.experiment_; + _impl_.experiment_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL ProposeRequest::_internal_mutable_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.experiment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Experiment>(GetArena()); + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(p); + } + return _impl_.experiment_; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL ProposeRequest::mutable_experiment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment::v1::Experiment* _msg = _internal_mutable_experiment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ProposeRequest.experiment) + return _msg; +} +inline void ProposeRequest::set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.experiment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ProposeRequest.experiment) +} + +// string request_id = 2 [json_name = "requestId", (.buf.validate.field) = { +inline void ProposeRequest::clear_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.request_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& ProposeRequest::request_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ProposeRequest.request_id) + return _internal_request_id(); +} +template +PROTOBUF_ALWAYS_INLINE void ProposeRequest::set_request_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.request_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ProposeRequest.request_id) +} +inline ::std::string* PROTOBUF_NONNULL ProposeRequest::mutable_request_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_request_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ProposeRequest.request_id) + return _s; +} +inline const ::std::string& ProposeRequest::_internal_request_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.request_id_.Get(); +} +inline void ProposeRequest::_internal_set_request_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.request_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ProposeRequest::_internal_mutable_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.request_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ProposeRequest::release_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ProposeRequest.request_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.request_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.request_id_.Set("", GetArena()); + } + return released; +} +inline void ProposeRequest::set_allocated_request_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.request_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.request_id_.IsDefault()) { + _impl_.request_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ProposeRequest.request_id) +} + +// ------------------------------------------------------------------- + +// ProposeResponse + +// .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; +inline bool ProposeResponse::has_experiment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.experiment_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::Experiment& ProposeResponse::_internal_experiment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Experiment* p = _impl_.experiment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Experiment>(&::xtcp_treatment::v1::Experiment_globals_); +} +inline const ::xtcp_treatment::v1::Experiment& ProposeResponse::experiment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ProposeResponse.experiment) + return _internal_experiment(); +} +inline void ProposeResponse::unsafe_arena_set_allocated_experiment( + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.experiment_); + } + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ProposeResponse.experiment) +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE ProposeResponse::release_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Experiment* released = _impl_.experiment_; + _impl_.experiment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE ProposeResponse::unsafe_arena_release_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ProposeResponse.experiment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Experiment* temp = _impl_.experiment_; + _impl_.experiment_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL ProposeResponse::_internal_mutable_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.experiment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Experiment>(GetArena()); + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(p); + } + return _impl_.experiment_; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL ProposeResponse::mutable_experiment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Experiment* _msg = _internal_mutable_experiment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ProposeResponse.experiment) + return _msg; +} +inline void ProposeResponse::set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.experiment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ProposeResponse.experiment) +} + +// ------------------------------------------------------------------- + +// AnalyzeRequest + +// string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { +inline void AnalyzeRequest::clear_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& AnalyzeRequest::experiment_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.AnalyzeRequest.experiment_id) + return _internal_experiment_id(); +} +template +PROTOBUF_ALWAYS_INLINE void AnalyzeRequest::set_experiment_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.experiment_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.AnalyzeRequest.experiment_id) +} +inline ::std::string* PROTOBUF_NONNULL AnalyzeRequest::mutable_experiment_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_experiment_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.AnalyzeRequest.experiment_id) + return _s; +} +inline const ::std::string& AnalyzeRequest::_internal_experiment_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.experiment_id_.Get(); +} +inline void AnalyzeRequest::_internal_set_experiment_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL AnalyzeRequest::_internal_mutable_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.experiment_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE AnalyzeRequest::release_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.AnalyzeRequest.experiment_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.experiment_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.experiment_id_.Set("", GetArena()); + } + return released; +} +inline void AnalyzeRequest::set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.experiment_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.experiment_id_.IsDefault()) { + _impl_.experiment_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.AnalyzeRequest.experiment_id) +} + +// uint64 expected_revision = 2 [json_name = "expectedRevision"]; +inline void AnalyzeRequest::clear_expected_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expected_revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline ::uint64_t AnalyzeRequest::expected_revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.AnalyzeRequest.expected_revision) + return _internal_expected_revision(); +} +inline void AnalyzeRequest::set_expected_revision(::uint64_t value) { + _internal_set_expected_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.AnalyzeRequest.expected_revision) +} +inline ::uint64_t AnalyzeRequest::_internal_expected_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.expected_revision_; +} +inline void AnalyzeRequest::_internal_set_expected_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expected_revision_ = value; +} + +// ------------------------------------------------------------------- + +// AnalyzeResponse + +// .xtcp_treatment.v1.Evidence evidence = 1 [json_name = "evidence"]; +inline bool AnalyzeResponse::has_evidence() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.evidence_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::Evidence& AnalyzeResponse::_internal_evidence() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Evidence* p = _impl_.evidence_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Evidence>(&::xtcp_treatment::v1::Evidence_globals_); +} +inline const ::xtcp_treatment::v1::Evidence& AnalyzeResponse::evidence() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.AnalyzeResponse.evidence) + return _internal_evidence(); +} +inline void AnalyzeResponse::unsafe_arena_set_allocated_evidence( + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evidence_); + } + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.AnalyzeResponse.evidence) +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE AnalyzeResponse::release_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Evidence* released = _impl_.evidence_; + _impl_.evidence_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE AnalyzeResponse::unsafe_arena_release_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.AnalyzeResponse.evidence) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Evidence* temp = _impl_.evidence_; + _impl_.evidence_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL AnalyzeResponse::_internal_mutable_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evidence_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Evidence>(GetArena()); + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(p); + } + return _impl_.evidence_; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL AnalyzeResponse::mutable_evidence() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Evidence* _msg = _internal_mutable_evidence(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.AnalyzeResponse.evidence) + return _msg; +} +inline void AnalyzeResponse::set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evidence_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.AnalyzeResponse.evidence) +} + +// .xtcp_treatment.v1.Outcome outcome = 2 [json_name = "outcome"]; +inline void AnalyzeResponse::clear_outcome() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.outcome_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline ::xtcp_treatment::v1::Outcome AnalyzeResponse::outcome() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.AnalyzeResponse.outcome) + return _internal_outcome(); +} +inline void AnalyzeResponse::set_outcome(::xtcp_treatment::v1::Outcome value) { + _internal_set_outcome(value); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.AnalyzeResponse.outcome) +} +inline ::xtcp_treatment::v1::Outcome AnalyzeResponse::_internal_outcome() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment::v1::Outcome>(_impl_.outcome_); +} +inline void AnalyzeResponse::_internal_set_outcome(::xtcp_treatment::v1::Outcome value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.outcome_ = value; +} + +// ------------------------------------------------------------------- + +// ReviewRequest + +// string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { +inline void ReviewRequest::clear_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& ReviewRequest::experiment_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ReviewRequest.experiment_id) + return _internal_experiment_id(); +} +template +PROTOBUF_ALWAYS_INLINE void ReviewRequest::set_experiment_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.experiment_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ReviewRequest.experiment_id) +} +inline ::std::string* PROTOBUF_NONNULL ReviewRequest::mutable_experiment_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_experiment_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ReviewRequest.experiment_id) + return _s; +} +inline const ::std::string& ReviewRequest::_internal_experiment_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.experiment_id_.Get(); +} +inline void ReviewRequest::_internal_set_experiment_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ReviewRequest::_internal_mutable_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.experiment_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ReviewRequest::release_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ReviewRequest.experiment_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.experiment_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.experiment_id_.Set("", GetArena()); + } + return released; +} +inline void ReviewRequest::set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.experiment_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.experiment_id_.IsDefault()) { + _impl_.experiment_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ReviewRequest.experiment_id) +} + +// uint64 expected_revision = 2 [json_name = "expectedRevision"]; +inline void ReviewRequest::clear_expected_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expected_revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline ::uint64_t ReviewRequest::expected_revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ReviewRequest.expected_revision) + return _internal_expected_revision(); +} +inline void ReviewRequest::set_expected_revision(::uint64_t value) { + _internal_set_expected_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ReviewRequest.expected_revision) +} +inline ::uint64_t ReviewRequest::_internal_expected_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.expected_revision_; +} +inline void ReviewRequest::_internal_set_expected_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expected_revision_ = value; +} + +// bool approve = 3 [json_name = "approve"]; +inline void ReviewRequest::clear_approve() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.approve_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline bool ReviewRequest::approve() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ReviewRequest.approve) + return _internal_approve(); +} +inline void ReviewRequest::set_approve(bool value) { + _internal_set_approve(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ReviewRequest.approve) +} +inline bool ReviewRequest::_internal_approve() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.approve_; +} +inline void ReviewRequest::_internal_set_approve(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.approve_ = value; +} + +// string reason = 4 [json_name = "reason", (.buf.validate.field) = { +inline void ReviewRequest::clear_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reason_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& ReviewRequest::reason() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ReviewRequest.reason) + return _internal_reason(); +} +template +PROTOBUF_ALWAYS_INLINE void ReviewRequest::set_reason(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.reason_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ReviewRequest.reason) +} +inline ::std::string* PROTOBUF_NONNULL ReviewRequest::mutable_reason() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_reason(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ReviewRequest.reason) + return _s; +} +inline const ::std::string& ReviewRequest::_internal_reason() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.reason_.Get(); +} +inline void ReviewRequest::_internal_set_reason(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reason_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ReviewRequest::_internal_mutable_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.reason_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ReviewRequest::release_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ReviewRequest.reason) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.reason_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.reason_.Set("", GetArena()); + } + return released; +} +inline void ReviewRequest::set_allocated_reason(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.reason_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.reason_.IsDefault()) { + _impl_.reason_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ReviewRequest.reason) +} + +// string request_id = 5 [json_name = "requestId", (.buf.validate.field) = { +inline void ReviewRequest::clear_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.request_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& ReviewRequest::request_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ReviewRequest.request_id) + return _internal_request_id(); +} +template +PROTOBUF_ALWAYS_INLINE void ReviewRequest::set_request_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.request_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ReviewRequest.request_id) +} +inline ::std::string* PROTOBUF_NONNULL ReviewRequest::mutable_request_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_request_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ReviewRequest.request_id) + return _s; +} +inline const ::std::string& ReviewRequest::_internal_request_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.request_id_.Get(); +} +inline void ReviewRequest::_internal_set_request_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.request_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ReviewRequest::_internal_mutable_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.request_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ReviewRequest::release_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ReviewRequest.request_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.request_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.request_id_.Set("", GetArena()); + } + return released; +} +inline void ReviewRequest::set_allocated_request_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.request_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.request_id_.IsDefault()) { + _impl_.request_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ReviewRequest.request_id) +} + +// .xtcp_treatment.v1.Evidence evidence = 6 [json_name = "evidence"]; +inline bool ReviewRequest::has_evidence() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.evidence_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::Evidence& ReviewRequest::_internal_evidence() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Evidence* p = _impl_.evidence_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Evidence>(&::xtcp_treatment::v1::Evidence_globals_); +} +inline const ::xtcp_treatment::v1::Evidence& ReviewRequest::evidence() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ReviewRequest.evidence) + return _internal_evidence(); +} +inline void ReviewRequest::unsafe_arena_set_allocated_evidence( + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evidence_); + } + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ReviewRequest.evidence) +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE ReviewRequest::release_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Evidence* released = _impl_.evidence_; + _impl_.evidence_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE ReviewRequest::unsafe_arena_release_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ReviewRequest.evidence) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Evidence* temp = _impl_.evidence_; + _impl_.evidence_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL ReviewRequest::_internal_mutable_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evidence_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Evidence>(GetArena()); + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(p); + } + return _impl_.evidence_; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL ReviewRequest::mutable_evidence() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Evidence* _msg = _internal_mutable_evidence(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ReviewRequest.evidence) + return _msg; +} +inline void ReviewRequest::set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evidence_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ReviewRequest.evidence) +} + +// ------------------------------------------------------------------- + +// ReviewResponse + +// .xtcp_treatment.v1.Experiment experiment = 1 [json_name = "experiment"]; +inline bool ReviewResponse::has_experiment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.experiment_ != nullptr); + return value; +} +inline const ::xtcp_treatment::v1::Experiment& ReviewResponse::_internal_experiment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Experiment* p = _impl_.experiment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Experiment>(&::xtcp_treatment::v1::Experiment_globals_); +} +inline const ::xtcp_treatment::v1::Experiment& ReviewResponse::experiment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ReviewResponse.experiment) + return _internal_experiment(); +} +inline void ReviewResponse::unsafe_arena_set_allocated_experiment( + ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.experiment_); + } + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ReviewResponse.experiment) +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE ReviewResponse::release_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Experiment* released = _impl_.experiment_; + _impl_.experiment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE ReviewResponse::unsafe_arena_release_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ReviewResponse.experiment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Experiment* temp = _impl_.experiment_; + _impl_.experiment_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL ReviewResponse::_internal_mutable_experiment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.experiment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Experiment>(GetArena()); + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(p); + } + return _impl_.experiment_; +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL ReviewResponse::mutable_experiment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::xtcp_treatment::v1::Experiment* _msg = _internal_mutable_experiment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ReviewResponse.experiment) + return _msg; +} +inline void ReviewResponse::set_allocated_experiment(::xtcp_treatment::v1::Experiment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.experiment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.experiment_ = reinterpret_cast<::xtcp_treatment::v1::Experiment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ReviewResponse.experiment) +} + +// ------------------------------------------------------------------- + +// ControlRequest + +// string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { +inline void ControlRequest::clear_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& ControlRequest::experiment_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlRequest.experiment_id) + return _internal_experiment_id(); +} +template +PROTOBUF_ALWAYS_INLINE void ControlRequest::set_experiment_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.experiment_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlRequest.experiment_id) +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::mutable_experiment_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_experiment_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ControlRequest.experiment_id) + return _s; +} +inline const ::std::string& ControlRequest::_internal_experiment_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.experiment_id_.Get(); +} +inline void ControlRequest::_internal_set_experiment_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::_internal_mutable_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.experiment_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ControlRequest::release_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ControlRequest.experiment_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.experiment_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.experiment_id_.Set("", GetArena()); + } + return released; +} +inline void ControlRequest::set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.experiment_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.experiment_id_.IsDefault()) { + _impl_.experiment_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ControlRequest.experiment_id) +} + +// string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { +inline void ControlRequest::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& ControlRequest::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlRequest.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void ControlRequest::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlRequest.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ControlRequest.agent_id) + return _s; +} +inline const ::std::string& ControlRequest::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void ControlRequest::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ControlRequest::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ControlRequest.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void ControlRequest::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ControlRequest.agent_id) +} + +// string location = 3 [json_name = "location", (.buf.validate.field) = { +inline void ControlRequest::clear_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& ControlRequest::location() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlRequest.location) + return _internal_location(); +} +template +PROTOBUF_ALWAYS_INLINE void ControlRequest::set_location(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.location_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlRequest.location) +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::mutable_location() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_location(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ControlRequest.location) + return _s; +} +inline const ::std::string& ControlRequest::_internal_location() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.location_.Get(); +} +inline void ControlRequest::_internal_set_location(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::_internal_mutable_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.location_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ControlRequest::release_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ControlRequest.location) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.location_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.location_.Set("", GetArena()); + } + return released; +} +inline void ControlRequest::set_allocated_location(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.location_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.location_.IsDefault()) { + _impl_.location_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ControlRequest.location) +} + +// bool fleet = 4 [json_name = "fleet"]; +inline void ControlRequest::clear_fleet() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.fleet_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline bool ControlRequest::fleet() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlRequest.fleet) + return _internal_fleet(); +} +inline void ControlRequest::set_fleet(bool value) { + _internal_set_fleet(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlRequest.fleet) +} +inline bool ControlRequest::_internal_fleet() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.fleet_; +} +inline void ControlRequest::_internal_set_fleet(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.fleet_ = value; +} + +// .xtcp_treatment.v1.ControlAction action = 5 [json_name = "action", (.buf.validate.field) = { +inline void ControlRequest::clear_action() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.action_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline ::xtcp_treatment::v1::ControlAction ControlRequest::action() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlRequest.action) + return _internal_action(); +} +inline void ControlRequest::set_action(::xtcp_treatment::v1::ControlAction value) { + _internal_set_action(value); + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlRequest.action) +} +inline ::xtcp_treatment::v1::ControlAction ControlRequest::_internal_action() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment::v1::ControlAction>(_impl_.action_); +} +inline void ControlRequest::_internal_set_action(::xtcp_treatment::v1::ControlAction value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.action_ = value; +} + +// string reason = 6 [json_name = "reason", (.buf.validate.field) = { +inline void ControlRequest::clear_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reason_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::std::string& ControlRequest::reason() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlRequest.reason) + return _internal_reason(); +} +template +PROTOBUF_ALWAYS_INLINE void ControlRequest::set_reason(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + _impl_.reason_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlRequest.reason) +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::mutable_reason() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::std::string* _s = _internal_mutable_reason(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ControlRequest.reason) + return _s; +} +inline const ::std::string& ControlRequest::_internal_reason() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.reason_.Get(); +} +inline void ControlRequest::_internal_set_reason(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reason_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::_internal_mutable_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.reason_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ControlRequest::release_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ControlRequest.reason) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000008U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + auto* released = _impl_.reason_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.reason_.Set("", GetArena()); + } + return released; +} +inline void ControlRequest::set_allocated_reason(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + _impl_.reason_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.reason_.IsDefault()) { + _impl_.reason_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ControlRequest.reason) +} + +// string request_id = 7 [json_name = "requestId", (.buf.validate.field) = { +inline void ControlRequest::clear_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.request_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline const ::std::string& ControlRequest::request_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlRequest.request_id) + return _internal_request_id(); +} +template +PROTOBUF_ALWAYS_INLINE void ControlRequest::set_request_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + _impl_.request_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlRequest.request_id) +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::mutable_request_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + ::std::string* _s = _internal_mutable_request_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ControlRequest.request_id) + return _s; +} +inline const ::std::string& ControlRequest::_internal_request_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.request_id_.Get(); +} +inline void ControlRequest::_internal_set_request_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.request_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ControlRequest::_internal_mutable_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.request_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ControlRequest::release_request_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ControlRequest.request_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000010U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + auto* released = _impl_.request_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.request_id_.Set("", GetArena()); + } + return released; +} +inline void ControlRequest::set_allocated_request_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + _impl_.request_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.request_id_.IsDefault()) { + _impl_.request_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ControlRequest.request_id) +} + +// ------------------------------------------------------------------- + +// ControlResponse + +// uint32 affected_agents = 1 [json_name = "affectedAgents"]; +inline void ControlResponse::clear_affected_agents() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.affected_agents_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline ::uint32_t ControlResponse::affected_agents() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ControlResponse.affected_agents) + return _internal_affected_agents(); +} +inline void ControlResponse::set_affected_agents(::uint32_t value) { + _internal_set_affected_agents(value); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ControlResponse.affected_agents) +} +inline ::uint32_t ControlResponse::_internal_affected_agents() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.affected_agents_; +} +inline void ControlResponse::_internal_set_affected_agents(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.affected_agents_ = value; +} + +// ------------------------------------------------------------------- + +// InspectRequest + +// string experiment_id = 1 [json_name = "experimentId", (.buf.validate.field) = { +inline void InspectRequest::clear_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& InspectRequest::experiment_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.InspectRequest.experiment_id) + return _internal_experiment_id(); +} +template +PROTOBUF_ALWAYS_INLINE void InspectRequest::set_experiment_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.experiment_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.InspectRequest.experiment_id) +} +inline ::std::string* PROTOBUF_NONNULL InspectRequest::mutable_experiment_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_experiment_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.InspectRequest.experiment_id) + return _s; +} +inline const ::std::string& InspectRequest::_internal_experiment_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.experiment_id_.Get(); +} +inline void InspectRequest::_internal_set_experiment_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL InspectRequest::_internal_mutable_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.experiment_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE InspectRequest::release_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.InspectRequest.experiment_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.experiment_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.experiment_id_.Set("", GetArena()); + } + return released; +} +inline void InspectRequest::set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.experiment_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.experiment_id_.IsDefault()) { + _impl_.experiment_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.InspectRequest.experiment_id) +} + +// string agent_id = 2 [json_name = "agentId", (.buf.validate.field) = { +inline void InspectRequest::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& InspectRequest::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.InspectRequest.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void InspectRequest::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.InspectRequest.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL InspectRequest::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.InspectRequest.agent_id) + return _s; +} +inline const ::std::string& InspectRequest::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void InspectRequest::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL InspectRequest::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE InspectRequest::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.InspectRequest.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void InspectRequest::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.InspectRequest.agent_id) +} + +// ------------------------------------------------------------------- + +// InspectResponse + +// repeated .xtcp_treatment.v1.Experiment experiments = 1 [json_name = "experiments"]; +inline int InspectResponse::_internal_experiments_size() const { + return _internal_experiments().size(); +} +inline int InspectResponse::experiments_size() const { + return _internal_experiments_size(); +} +inline const ::xtcp_treatment::v1::Experiment& InspectResponse::experiments(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.InspectResponse.experiments) + return _internal_experiments().Get(index); +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL InspectResponse::mutable_experiments(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.InspectResponse.experiments) + return _internal_mutable_experiments()->Mutable(index); +} +inline ::xtcp_treatment::v1::Experiment* PROTOBUF_NONNULL InspectResponse::add_experiments() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::Experiment* _add = + _internal_mutable_experiments()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.InspectResponse.experiments) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>& InspectResponse::experiments() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.InspectResponse.experiments) + return _internal_experiments(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>* PROTOBUF_NONNULL +InspectResponse::mutable_experiments() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.InspectResponse.experiments) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_experiments(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>& +InspectResponse::_internal_experiments() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.experiments_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Experiment>* PROTOBUF_NONNULL +InspectResponse::_internal_mutable_experiments() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.experiments_; +} + +// repeated .xtcp_treatment.v1.DesiredState desired = 2 [json_name = "desired"]; +inline int InspectResponse::_internal_desired_size() const { + return _internal_desired().size(); +} +inline int InspectResponse::desired_size() const { + return _internal_desired_size(); +} +inline const ::xtcp_treatment::v1::DesiredState& InspectResponse::desired(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.InspectResponse.desired) + return _internal_desired().Get(index); +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL InspectResponse::mutable_desired(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.InspectResponse.desired) + return _internal_mutable_desired()->Mutable(index); +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL InspectResponse::add_desired() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::DesiredState* _add = + _internal_mutable_desired()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.InspectResponse.desired) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>& InspectResponse::desired() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.InspectResponse.desired) + return _internal_desired(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>* PROTOBUF_NONNULL +InspectResponse::mutable_desired() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.InspectResponse.desired) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_desired(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>& +InspectResponse::_internal_desired() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.desired_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::DesiredState>* PROTOBUF_NONNULL +InspectResponse::_internal_mutable_desired() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.desired_; +} + +// repeated .xtcp_treatment.v1.CheckInRequest observed = 3 [json_name = "observed"]; +inline int InspectResponse::_internal_observed_size() const { + return _internal_observed().size(); +} +inline int InspectResponse::observed_size() const { + return _internal_observed_size(); +} +inline const ::xtcp_treatment::v1::CheckInRequest& InspectResponse::observed(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.InspectResponse.observed) + return _internal_observed().Get(index); +} +inline ::xtcp_treatment::v1::CheckInRequest* PROTOBUF_NONNULL InspectResponse::mutable_observed(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.InspectResponse.observed) + return _internal_mutable_observed()->Mutable(index); +} +inline ::xtcp_treatment::v1::CheckInRequest* PROTOBUF_NONNULL InspectResponse::add_observed() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::CheckInRequest* _add = + _internal_mutable_observed()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.InspectResponse.observed) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>& InspectResponse::observed() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.InspectResponse.observed) + return _internal_observed(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>* PROTOBUF_NONNULL +InspectResponse::mutable_observed() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.InspectResponse.observed) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_observed(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>& +InspectResponse::_internal_observed() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.observed_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::CheckInRequest>* PROTOBUF_NONNULL +InspectResponse::_internal_mutable_observed() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.observed_; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment + + +namespace google { +namespace protobuf { + +template <> +struct is_proto_enum<::xtcp_treatment::v1::ControlAction> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment::v1::ControlAction>() { + return ::xtcp_treatment::v1::ControlAction_descriptor(); +} + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" +// clang-format on + +#endif // xtcp_5ftreatment_2fv1_2foperator_2eproto_2epb_2eh diff --git a/gen/cpp/xtcp_treatment/v1/treatment.grpc.pb.cc b/gen/cpp/xtcp_treatment/v1/treatment.grpc.pb.cc new file mode 100644 index 000000000..fe99fc76f --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/treatment.grpc.pb.cc @@ -0,0 +1,29 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment/v1/treatment.proto + +#include "xtcp_treatment/v1/treatment.pb.h" +#include "xtcp_treatment/v1/treatment.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace xtcp_treatment { +namespace v1 { + +} // namespace xtcp_treatment +} // namespace v1 +#include + diff --git a/gen/cpp/xtcp_treatment/v1/treatment.grpc.pb.h b/gen/cpp/xtcp_treatment/v1/treatment.grpc.pb.h new file mode 100644 index 000000000..bc6412b0f --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/treatment.grpc.pb.h @@ -0,0 +1,56 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment/v1/treatment.proto +// Original file comments: +// +// xTCP - treatment +// +// Shared message types for the TCP route treatment control plane: what a +// treatment is, how it is assigned to an agent, what an agent reports back, +// and how an experiment over a cohort of agents is described and evidenced. +// +// Wire contract only. The controller and the agent work on Go domain types +// and convert at the gRPC boundary; nothing here is a storage schema. +// +// Validation: every client-controlled field carries a buf.validate rule that +// mirrors the bound in pkg/treatment/validate.go, so a malformed request is +// rejected before any handler runs. The Go validators remain authoritative +// for contextual rules that need more than one message (duplicate assignment +// IDs, overlapping destinations, cohort/baseline agreement). +// +// See docs/tcp-controller.md. +// +#ifndef GRPC_xtcp_5ftreatment_2fv1_2ftreatment_2eproto__INCLUDED +#define GRPC_xtcp_5ftreatment_2fv1_2ftreatment_2eproto__INCLUDED + +#include "xtcp_treatment/v1/treatment.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xtcp_treatment { +namespace v1 { + +} // namespace v1 +} // namespace xtcp_treatment + + +#include +#endif // GRPC_xtcp_5ftreatment_2fv1_2ftreatment_2eproto__INCLUDED diff --git a/gen/cpp/xtcp_treatment/v1/treatment.pb.cc b/gen/cpp/xtcp_treatment/v1/treatment.pb.cc new file mode 100644 index 000000000..70b1a386d --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/treatment.pb.cc @@ -0,0 +1,8279 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment/v1/treatment.proto +// Protobuf C++ Version: 7.36.2 + +#include "xtcp_treatment/v1/treatment.pb.h" + +#include +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/internal_visibility.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; +#ifdef PROTOBUF_MESSAGE_GLOBALS +namespace { +PROTOBUF_CONSTINIT ::google::protobuf::internal::ReflectionData + file_reflection_data[] = { + // ::xtcp_treatment::v1::TCPSettings + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::Treatment + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::Assignment + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::DesiredState + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::Capabilities + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::ApplicationRecord + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::LocalState + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::HostEvidence + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::Evidence + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::ExperimentPolicy + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::Phase + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment::v1::Experiment + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, /* tracker*/ nullptr,}, +}; +} // namespace +#endif +namespace xtcp_treatment { +namespace v1 { +class TCPSettings::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_._has_bits_); +}; + +constexpr TCPSettings::ParseTableT_ TCPSettings::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_._has_bits_), + 0, // no _extensions_ + 7, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967168, // skipmap + offsetof(ParseTableT_, field_entries), + 7, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::TCPSettings>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // optional string congestion_control = 1 [json_name = "congestionControl", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_control_)}}, + // bool congestion_lock = 2 [json_name = "congestionLock"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {16, 4, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_lock_)}}, + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TCPSettings, _impl_.rto_min_ms_), 1>(), + {24, 1, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.rto_min_ms_)}}, + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TCPSettings, _impl_.initial_congestion_window_), 2>(), + {32, 2, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_congestion_window_)}}, + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TCPSettings, _impl_.initial_receive_window_), 3>(), + {40, 3, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_receive_window_)}}, + // optional bool quick_ack = 6 [json_name = "quickAck"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {48, 5, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.quick_ack_)}}, + // optional bool ecn = 7 [json_name = "ecn"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {56, 6, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.ecn_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // optional string congestion_control = 1 [json_name = "congestionControl", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_control_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bool congestion_lock = 2 [json_name = "congestionLock"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_lock_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.rto_min_ms_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_congestion_window_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_receive_window_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional bool quick_ack = 6 [json_name = "quickAck"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.quick_ack_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional bool ecn = 7 [json_name = "ecn"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.ecn_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + // no aux_entries + {{ + "\35\22\0\0\0\0\0\0" + "xtcp_treatment.v1.TCPSettings" + "congestion_control" + }}, + }; +} + + +inline constexpr TCPSettings::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : congestion_control_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + rto_min_ms_{0u}, + initial_congestion_window_{0u}, + initial_receive_window_{0u}, + congestion_lock_{false}, + quick_ack_{false}, + ecn_{false} {} + +template +constexpr TCPSettings::TCPSettings(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL TCPSettings::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TCPSettings(arena); +} +constexpr auto TCPSettings::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(TCPSettings), alignof(TCPSettings)); +} +constexpr auto TCPSettings::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &TCPSettings::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TCPSettings::SharedDtor, + Super_::GetClearImpl(), &TCPSettings::ByteSizeLong, + &TCPSettings::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[0], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct TCPSettingsGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr TCPSettingsGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + TCPSettings_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(TCPSettings::InternalGenerateClassData_( + _default, &TCPSettings_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~TCPSettingsGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) TCPSettings _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(TCPSettingsGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST TCPSettingsGlobalsTypeInternal TCPSettings_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* TCPSettings_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return TCPSettings_globals_.GetClassData(); +#else + return TCPSettings_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class HostEvidence::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_._has_bits_); +}; + +constexpr HostEvidence::ParseTableT_ HostEvidence::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_._has_bits_), + 0, // no _extensions_ + 9, 120, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294966784, // skipmap + offsetof(ParseTableT_, field_entries), + 9, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::HostEvidence>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.agent_id_)}}, + // uint64 sockets = 2 [json_name = "sockets"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(HostEvidence, _impl_.sockets_), 1>(), + {16, 1, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.sockets_)}}, + // uint64 bytes_acked = 3 [json_name = "bytesAcked"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(HostEvidence, _impl_.bytes_acked_), 2>(), + {24, 2, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.bytes_acked_)}}, + // double goodput_bps = 4 [json_name = "goodputBps", (.buf.validate.field) = { + {::_pbi::TcParser::FastF64S1, + {33, 3, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.goodput_bps_)}}, + // double retransmission_ratio = 5 [json_name = "retransmissionRatio", (.buf.validate.field) = { + {::_pbi::TcParser::FastF64S1, + {41, 4, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.retransmission_ratio_)}}, + // double rtt_p95_ms = 6 [json_name = "rttP95Ms", (.buf.validate.field) = { + {::_pbi::TcParser::FastF64S1, + {49, 5, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.rtt_p95_ms_)}}, + // uint64 exposed_sockets = 7 [json_name = "exposedSockets"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(HostEvidence, _impl_.exposed_sockets_), 6>(), + {56, 6, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.exposed_sockets_)}}, + // bool collection_healthy = 8 [json_name = "collectionHealthy"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {64, 8, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.collection_healthy_)}}, + // uint64 unbound_sockets = 9 [json_name = "unboundSockets"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(HostEvidence, _impl_.unbound_sockets_), 7>(), + {72, 7, 0, + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.unbound_sockets_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.agent_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint64 sockets = 2 [json_name = "sockets"]; + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.sockets_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // uint64 bytes_acked = 3 [json_name = "bytesAcked"]; + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.bytes_acked_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // double goodput_bps = 4 [json_name = "goodputBps", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.goodput_bps_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kDouble)}, + // double retransmission_ratio = 5 [json_name = "retransmissionRatio", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.retransmission_ratio_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kDouble)}, + // double rtt_p95_ms = 6 [json_name = "rttP95Ms", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.rtt_p95_ms_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kDouble)}, + // uint64 exposed_sockets = 7 [json_name = "exposedSockets"]; + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.exposed_sockets_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // bool collection_healthy = 8 [json_name = "collectionHealthy"]; + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.collection_healthy_), _Internal::kHasBitsOffset + 8, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // uint64 unbound_sockets = 9 [json_name = "unboundSockets"]; + {PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.unbound_sockets_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + }}, + // no aux_entries + {{ + "\36\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "xtcp_treatment.v1.HostEvidence" + "agent_id" + }}, + }; +} + + +inline constexpr HostEvidence::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + sockets_{::uint64_t{0u}}, + bytes_acked_{::uint64_t{0u}}, + goodput_bps_{0}, + retransmission_ratio_{0}, + rtt_p95_ms_{0}, + exposed_sockets_{::uint64_t{0u}}, + unbound_sockets_{::uint64_t{0u}}, + collection_healthy_{false} {} + +template +constexpr HostEvidence::HostEvidence(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL HostEvidence::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) HostEvidence(arena); +} +constexpr auto HostEvidence::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(HostEvidence), alignof(HostEvidence)); +} +constexpr auto HostEvidence::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &HostEvidence::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &HostEvidence::SharedDtor, + Super_::GetClearImpl(), &HostEvidence::ByteSizeLong, + &HostEvidence::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[7], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct HostEvidenceGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr HostEvidenceGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + HostEvidence_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(HostEvidence::InternalGenerateClassData_( + _default, &HostEvidence_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~HostEvidenceGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) HostEvidence _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(HostEvidenceGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST HostEvidenceGlobalsTypeInternal HostEvidence_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* HostEvidence_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return HostEvidence_globals_.GetClassData(); +#else + return HostEvidence_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Capabilities::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Capabilities, _impl_._has_bits_); +}; + +constexpr Capabilities::ParseTableT_ Capabilities::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_._has_bits_), + 0, // no _extensions_ + 6, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967232, // skipmap + offsetof(ParseTableT_, field_entries), + 6, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Capabilities>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string boot_id = 1 [json_name = "bootId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 1, 0, + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.boot_id_)}}, + // string kernel_release = 2 [json_name = "kernelRelease", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {18, 2, 0, + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.kernel_release_)}}, + // repeated string congestion_algorithms = 3 [json_name = "congestionAlgorithms", (.buf.validate.field) = { + {::_pbi::TcParser::FastUR1, + {26, 0, 0, + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.congestion_algorithms_)}}, + // bool simple_host_routing = 4 [json_name = "simpleHostRouting"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {32, 4, 0, + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.simple_host_routing_)}}, + // bool actuator_enabled = 5 [json_name = "actuatorEnabled"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {40, 5, 0, + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.actuator_enabled_)}}, + // string collection_id = 6 [json_name = "collectionId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {50, 3, 0, + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.collection_id_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string boot_id = 1 [json_name = "bootId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.boot_id_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string kernel_release = 2 [json_name = "kernelRelease", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.kernel_release_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // repeated string congestion_algorithms = 3 [json_name = "congestionAlgorithms", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.congestion_algorithms_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kUtf8String | ::_fl::kRepSString)}, + // bool simple_host_routing = 4 [json_name = "simpleHostRouting"]; + {PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.simple_host_routing_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // bool actuator_enabled = 5 [json_name = "actuatorEnabled"]; + {PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.actuator_enabled_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // string collection_id = 6 [json_name = "collectionId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.collection_id_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + // no aux_entries + {{ + "\36\7\16\25\0\0\15\0" + "xtcp_treatment.v1.Capabilities" + "boot_id" + "kernel_release" + "congestion_algorithms" + "collection_id" + }}, + }; +} + + +inline constexpr Capabilities::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : congestion_algorithms_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Capabilities, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.congestion_algorithms_)>() + } + , + boot_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + kernel_release_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + collection_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + simple_host_routing_{false}, + actuator_enabled_{false} {} + +template +constexpr Capabilities::Capabilities(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Capabilities::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Capabilities(arena); +} +constexpr auto Capabilities::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Capabilities), alignof(Capabilities)); +} +constexpr auto Capabilities::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Capabilities::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Capabilities::SharedDtor, + Super_::GetClearImpl(), &Capabilities::ByteSizeLong, + &Capabilities::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[4], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct CapabilitiesGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr CapabilitiesGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Capabilities_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Capabilities::InternalGenerateClassData_( + _default, &Capabilities_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~CapabilitiesGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Capabilities _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(CapabilitiesGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST CapabilitiesGlobalsTypeInternal Capabilities_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Capabilities_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Capabilities_globals_.GetClassData(); +#else + return Capabilities_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Treatment::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Treatment, _impl_._has_bits_); +}; + +constexpr Treatment::ParseTableT_ Treatment::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Treatment, _impl_._has_bits_), + 0, // no _extensions_ + 5, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967264, // skipmap + offsetof(ParseTableT_, field_entries), + 5, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Treatment>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string id = 1 [json_name = "id", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.id_)}}, + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Treatment, _impl_.revision_), 3>(), + {16, 3, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.revision_)}}, + // string destination = 3 [json_name = "destination", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {26, 1, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.destination_)}}, + // .xtcp_treatment.v1.TCPSettings settings = 4 [json_name = "settings", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {34, 2, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.settings_)}}, + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {40, 4, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.ecn_fabric_verified_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string id = 1 [json_name = "id", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.revision_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // string destination = 3 [json_name = "destination", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.destination_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment.v1.TCPSettings settings = 4 [json_name = "settings", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.settings_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.ecn_fabric_verified_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::TCPSettings>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::TCPSettings_globals_}, + #endif + }}, + {{ + "\33\2\0\13\0\0\0\0" + "xtcp_treatment.v1.Treatment" + "id" + "destination" + }}, + }; +} + + +inline constexpr Treatment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + destination_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + settings_{nullptr}, + revision_{::uint64_t{0u}}, + ecn_fabric_verified_{false} {} + +template +constexpr Treatment::Treatment(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Treatment::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Treatment(arena); +} +constexpr auto Treatment::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Treatment), alignof(Treatment)); +} +constexpr auto Treatment::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Treatment::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Treatment::SharedDtor, + Super_::GetClearImpl(), &Treatment::ByteSizeLong, + &Treatment::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Treatment, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[1], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct TreatmentGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr TreatmentGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Treatment_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Treatment::InternalGenerateClassData_( + _default, &Treatment_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~TreatmentGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Treatment _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(TreatmentGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST TreatmentGlobalsTypeInternal Treatment_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Treatment_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Treatment_globals_.GetClassData(); +#else + return Treatment_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ExperimentPolicy::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_._has_bits_); +}; + +constexpr ExperimentPolicy::ParseTableT_ ExperimentPolicy::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_._has_bits_), + 0, // no _extensions_ + 9, 120, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294966784, // skipmap + offsetof(ParseTableT_, field_entries), + 9, // num_field_entries + 3, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ExperimentPolicy>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // .google.protobuf.Duration minimum_observation = 1 [json_name = "minimumObservation", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_observation_)}}, + // .google.protobuf.Duration maximum_phase = 2 [json_name = "maximumPhase", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {18, 1, 1, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_phase_)}}, + // uint64 minimum_sockets_per_host = 3 [json_name = "minimumSocketsPerHost", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ExperimentPolicy, _impl_.minimum_sockets_per_host_), 3>(), + {24, 3, 0, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_sockets_per_host_)}}, + // uint64 minimum_bytes_per_host = 4 [json_name = "minimumBytesPerHost", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ExperimentPolicy, _impl_.minimum_bytes_per_host_), 4>(), + {32, 4, 0, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_bytes_per_host_)}}, + // uint32 minimum_treated_hosts = 5 [json_name = "minimumTreatedHosts", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ExperimentPolicy, _impl_.minimum_treated_hosts_), 8>(), + {40, 8, 0, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_treated_hosts_)}}, + // double minimum_improvement = 6 [json_name = "minimumImprovement", (.buf.validate.field) = { + {::_pbi::TcParser::FastF64S1, + {49, 5, 0, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_improvement_)}}, + // double maximum_retransmission_increase = 7 [json_name = "maximumRetransmissionIncrease", (.buf.validate.field) = { + {::_pbi::TcParser::FastF64S1, + {57, 6, 0, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_retransmission_increase_)}}, + // double maximum_rtt_increase = 8 [json_name = "maximumRttIncrease", (.buf.validate.field) = { + {::_pbi::TcParser::FastF64S1, + {65, 7, 0, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_rtt_increase_)}}, + // .google.protobuf.Duration maximum_evidence_age = 9 [json_name = "maximumEvidenceAge", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {74, 2, 2, + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_evidence_age_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // .google.protobuf.Duration minimum_observation = 1 [json_name = "minimumObservation", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_observation_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Duration maximum_phase = 2 [json_name = "maximumPhase", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_phase_), _Internal::kHasBitsOffset + 1, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint64 minimum_sockets_per_host = 3 [json_name = "minimumSocketsPerHost", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_sockets_per_host_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // uint64 minimum_bytes_per_host = 4 [json_name = "minimumBytesPerHost", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_bytes_per_host_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // uint32 minimum_treated_hosts = 5 [json_name = "minimumTreatedHosts", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_treated_hosts_), _Internal::kHasBitsOffset + 8, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // double minimum_improvement = 6 [json_name = "minimumImprovement", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_improvement_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kDouble)}, + // double maximum_retransmission_increase = 7 [json_name = "maximumRetransmissionIncrease", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_retransmission_increase_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kDouble)}, + // double maximum_rtt_increase = 8 [json_name = "maximumRttIncrease", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_rtt_increase_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcOptional | ::_fl::kDouble)}, + // .google.protobuf.Duration maximum_evidence_age = 9 [json_name = "maximumEvidenceAge", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.maximum_evidence_age_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Duration>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Duration_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Duration>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Duration_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Duration>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Duration_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr ExperimentPolicy::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : minimum_observation_{nullptr}, + maximum_phase_{nullptr}, + maximum_evidence_age_{nullptr}, + minimum_sockets_per_host_{::uint64_t{0u}}, + minimum_bytes_per_host_{::uint64_t{0u}}, + minimum_improvement_{0}, + maximum_retransmission_increase_{0}, + maximum_rtt_increase_{0}, + minimum_treated_hosts_{0u} {} + +template +constexpr ExperimentPolicy::ExperimentPolicy(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ExperimentPolicy::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ExperimentPolicy(arena); +} +constexpr auto ExperimentPolicy::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(ExperimentPolicy), alignof(ExperimentPolicy)); +} +constexpr auto ExperimentPolicy::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ExperimentPolicy::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ExperimentPolicy::SharedDtor, + Super_::GetClearImpl(), &ExperimentPolicy::ByteSizeLong, + &ExperimentPolicy::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[9], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ExperimentPolicyGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ExperimentPolicyGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ExperimentPolicy_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ExperimentPolicy::InternalGenerateClassData_( + _default, &ExperimentPolicy_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ExperimentPolicyGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ExperimentPolicy _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ExperimentPolicyGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ExperimentPolicyGlobalsTypeInternal ExperimentPolicy_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ExperimentPolicy_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ExperimentPolicy_globals_.GetClassData(); +#else + return ExperimentPolicy_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Evidence::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Evidence, _impl_._has_bits_); +}; + +constexpr Evidence::ParseTableT_ Evidence::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Evidence, _impl_._has_bits_), + 0, // no _extensions_ + 8, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967040, // skipmap + offsetof(ParseTableT_, field_entries), + 8, // num_field_entries + 4, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Evidence>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // string artifact_sha256 = 8 [json_name = "artifactSha256", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {66, 4, 0, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.artifact_sha256_)}}, + // string id = 1 [json_name = "id", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 1, 0, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.id_)}}, + // .google.protobuf.Timestamp analyzed_at = 2 [json_name = "analyzedAt", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {18, 5, 0, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.analyzed_at_)}}, + // .google.protobuf.Timestamp window_start = 3 [json_name = "windowStart", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {26, 6, 1, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.window_start_)}}, + // .google.protobuf.Timestamp window_end = 4 [json_name = "windowEnd", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {34, 7, 2, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.window_end_)}}, + // string query_version = 5 [json_name = "queryVersion", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {42, 2, 0, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.query_version_)}}, + // string enrichment_version = 6 [json_name = "enrichmentVersion", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {50, 3, 0, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.enrichment_version_)}}, + // repeated .xtcp_treatment.v1.HostEvidence hosts = 7 [json_name = "hosts", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtR1, + {58, 0, 3, + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.hosts_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string id = 1 [json_name = "id", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.id_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .google.protobuf.Timestamp analyzed_at = 2 [json_name = "analyzedAt", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.analyzed_at_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp window_start = 3 [json_name = "windowStart", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.window_start_), _Internal::kHasBitsOffset + 6, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp window_end = 4 [json_name = "windowEnd", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.window_end_), _Internal::kHasBitsOffset + 7, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // string query_version = 5 [json_name = "queryVersion", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.query_version_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string enrichment_version = 6 [json_name = "enrichmentVersion", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.enrichment_version_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // repeated .xtcp_treatment.v1.HostEvidence hosts = 7 [json_name = "hosts", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.hosts_), _Internal::kHasBitsOffset + 0, 3, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // string artifact_sha256 = 8 [json_name = "artifactSha256", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Evidence, _impl_.artifact_sha256_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::HostEvidence>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::HostEvidence_globals_}, + #endif + }}, + {{ + "\32\2\0\0\0\15\22\0\17\0\0\0\0\0\0\0" + "xtcp_treatment.v1.Evidence" + "id" + "query_version" + "enrichment_version" + "artifact_sha256" + }}, + }; +} + + +inline constexpr Evidence::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : hosts_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Evidence, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.hosts_)>() + } + , + id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + query_version_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + enrichment_version_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + artifact_sha256_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + analyzed_at_{nullptr}, + window_start_{nullptr}, + window_end_{nullptr} {} + +template +constexpr Evidence::Evidence(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Evidence::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Evidence(arena); +} +constexpr auto Evidence::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Evidence), alignof(Evidence)); +} +constexpr auto Evidence::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Evidence::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Evidence::SharedDtor, + Super_::GetClearImpl(), &Evidence::ByteSizeLong, + &Evidence::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Evidence, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[8], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct EvidenceGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr EvidenceGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Evidence_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Evidence::InternalGenerateClassData_( + _default, &Evidence_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~EvidenceGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Evidence _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(EvidenceGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST EvidenceGlobalsTypeInternal Evidence_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Evidence_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Evidence_globals_.GetClassData(); +#else + return Evidence_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Phase::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Phase, _impl_._has_bits_); +}; + +constexpr Phase::ParseTableT_ Phase::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Phase, _impl_._has_bits_), + 0, // no _extensions_ + 8, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967040, // skipmap + offsetof(ParseTableT_, field_entries), + 8, // num_field_entries + 4, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Phase>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // string reason = 8 [json_name = "reason", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {66, 1, 0, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.reason_)}}, + // uint32 target_hosts = 1 [json_name = "targetHosts", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Phase, _impl_.target_hosts_), 6>(), + {8, 6, 0, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.target_hosts_)}}, + // .google.protobuf.Timestamp issued_at = 2 [json_name = "issuedAt"]; + {::_pbi::TcParser::FastMtS1, + {18, 2, 0, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.issued_at_)}}, + // .google.protobuf.Timestamp observation_started_at = 3 [json_name = "observationStartedAt"]; + {::_pbi::TcParser::FastMtS1, + {26, 3, 1, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.observation_started_at_)}}, + // .google.protobuf.Timestamp evaluated_at = 4 [json_name = "evaluatedAt"]; + {::_pbi::TcParser::FastMtS1, + {34, 4, 2, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.evaluated_at_)}}, + // .xtcp_treatment.v1.Evidence evidence = 5 [json_name = "evidence"]; + {::_pbi::TcParser::FastMtS1, + {42, 5, 3, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.evidence_)}}, + // .xtcp_treatment.v1.Outcome outcome = 6 [json_name = "outcome", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Phase, _impl_.outcome_), 7>(), + {48, 7, 0, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.outcome_)}}, + // string reviewer = 7 [json_name = "reviewer", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {58, 0, 0, + PROTOBUF_FIELD_OFFSET(Phase, _impl_.reviewer_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint32 target_hosts = 1 [json_name = "targetHosts", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.target_hosts_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // .google.protobuf.Timestamp issued_at = 2 [json_name = "issuedAt"]; + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.issued_at_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp observation_started_at = 3 [json_name = "observationStartedAt"]; + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.observation_started_at_), _Internal::kHasBitsOffset + 3, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp evaluated_at = 4 [json_name = "evaluatedAt"]; + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.evaluated_at_), _Internal::kHasBitsOffset + 4, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.Evidence evidence = 5 [json_name = "evidence"]; + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.evidence_), _Internal::kHasBitsOffset + 5, 3, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.Outcome outcome = 6 [json_name = "outcome", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.outcome_), _Internal::kHasBitsOffset + 7, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // string reviewer = 7 [json_name = "reviewer", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.reviewer_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string reason = 8 [json_name = "reason", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Phase, _impl_.reason_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Evidence>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Evidence_globals_}, + #endif + }}, + {{ + "\27\0\0\0\0\0\0\10\6\0\0\0\0\0\0\0" + "xtcp_treatment.v1.Phase" + "reviewer" + "reason" + }}, + }; +} + + +inline constexpr Phase::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : reviewer_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + reason_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + issued_at_{nullptr}, + observation_started_at_{nullptr}, + evaluated_at_{nullptr}, + evidence_{nullptr}, + target_hosts_{0u}, + outcome_{static_cast< ::xtcp_treatment::v1::Outcome >(0)} {} + +template +constexpr Phase::Phase(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Phase::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Phase(arena); +} +constexpr auto Phase::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Phase), alignof(Phase)); +} +constexpr auto Phase::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Phase::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Phase::SharedDtor, + Super_::GetClearImpl(), &Phase::ByteSizeLong, + &Phase::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Phase, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[10], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct PhaseGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr PhaseGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Phase_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Phase::InternalGenerateClassData_( + _default, &Phase_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~PhaseGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Phase _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(PhaseGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST PhaseGlobalsTypeInternal Phase_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Phase_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Phase_globals_.GetClassData(); +#else + return Phase_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Assignment::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Assignment, _impl_._has_bits_); +}; + +constexpr Assignment::ParseTableT_ Assignment::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Assignment, _impl_._has_bits_), + 0, // no _extensions_ + 7, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967169, // skipmap + offsetof(ParseTableT_, field_entries), + 6, // num_field_entries + 3, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Assignment>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // string experiment_id = 2 [json_name = "experimentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {18, 0, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.experiment_id_)}}, + // .xtcp_treatment.v1.Treatment treatment = 3 [json_name = "treatment", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {26, 1, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.treatment_)}}, + // .xtcp_treatment.v1.AssignmentMode mode = 4 [json_name = "mode", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Assignment, _impl_.mode_), 5>(), + {32, 5, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.mode_)}}, + // .google.protobuf.Timestamp lease_expires_at = 5 [json_name = "leaseExpiresAt"]; + {::_pbi::TcParser::FastMtS1, + {42, 2, 1, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.lease_expires_at_)}}, + // .xtcp_treatment.v1.Treatment predecessor = 6 [json_name = "predecessor"]; + {::_pbi::TcParser::FastMtS1, + {50, 3, 2, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.predecessor_)}}, + // uint64 generation = 7 [json_name = "generation", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Assignment, _impl_.generation_), 4>(), + {56, 4, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.generation_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string experiment_id = 2 [json_name = "experimentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.experiment_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment.v1.Treatment treatment = 3 [json_name = "treatment", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.treatment_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.AssignmentMode mode = 4 [json_name = "mode", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.mode_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .google.protobuf.Timestamp lease_expires_at = 5 [json_name = "leaseExpiresAt"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.lease_expires_at_), _Internal::kHasBitsOffset + 2, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.Treatment predecessor = 6 [json_name = "predecessor"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.predecessor_), _Internal::kHasBitsOffset + 3, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint64 generation = 7 [json_name = "generation", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.generation_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Treatment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Treatment_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Treatment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Treatment_globals_}, + #endif + }}, + {{ + "\34\15\0\0\0\0\0\0" + "xtcp_treatment.v1.Assignment" + "experiment_id" + }}, + }; +} + + +inline constexpr Assignment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + treatment_{nullptr}, + lease_expires_at_{nullptr}, + predecessor_{nullptr}, + generation_{::uint64_t{0u}}, + mode_{static_cast< ::xtcp_treatment::v1::AssignmentMode >(0)} {} + +template +constexpr Assignment::Assignment(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Assignment::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Assignment(arena); +} +constexpr auto Assignment::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Assignment), alignof(Assignment)); +} +constexpr auto Assignment::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Assignment::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Assignment::SharedDtor, + Super_::GetClearImpl(), &Assignment::ByteSizeLong, + &Assignment::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Assignment, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[2], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct AssignmentGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr AssignmentGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Assignment_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Assignment::InternalGenerateClassData_( + _default, &Assignment_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~AssignmentGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Assignment _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(AssignmentGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST AssignmentGlobalsTypeInternal Assignment_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Assignment_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Assignment_globals_.GetClassData(); +#else + return Assignment_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Experiment::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Experiment, _impl_._has_bits_); +}; + +constexpr Experiment::ParseTableT_ Experiment::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Experiment, _impl_._has_bits_), + 0, // no _extensions_ + 14, 120, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294950912, // skipmap + offsetof(ParseTableT_, field_entries), + 14, // num_field_entries + 7, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Experiment>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string id = 1 [json_name = "id", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 2, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.id_)}}, + // string location = 2 [json_name = "location", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {18, 3, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.location_)}}, + // string hypothesis = 3 [json_name = "hypothesis", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {26, 4, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.hypothesis_)}}, + // .xtcp_treatment.v1.Treatment treatment = 4 [json_name = "treatment", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {34, 5, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.treatment_)}}, + // .xtcp_treatment.v1.ExperimentPolicy policy = 5 [json_name = "policy", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {42, 6, 1, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.policy_)}}, + // .xtcp_treatment.v1.Evidence baseline = 6 [json_name = "baseline", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {50, 7, 2, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.baseline_)}}, + // repeated string cohort_order = 7 [json_name = "cohortOrder", (.buf.validate.field) = { + {::_pbi::TcParser::FastUR1, + {58, 0, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.cohort_order_)}}, + // repeated .xtcp_treatment.v1.Phase phases = 8 [json_name = "phases", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtR1, + {66, 1, 3, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.phases_)}}, + // .xtcp_treatment.v1.ExperimentStatus status = 9 [json_name = "status", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Experiment, _impl_.status_), 12>(), + {72, 12, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.status_)}}, + // uint64 revision = 10 [json_name = "revision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Experiment, _impl_.revision_), 11>(), + {80, 11, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.revision_)}}, + // .google.protobuf.Timestamp proposed_at = 11 [json_name = "proposedAt"]; + {::_pbi::TcParser::FastMtS1, + {90, 8, 4, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.proposed_at_)}}, + // .xtcp_treatment.v1.Evidence latest_evidence = 12 [json_name = "latestEvidence"]; + {::_pbi::TcParser::FastMtS1, + {98, 9, 5, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.latest_evidence_)}}, + // .xtcp_treatment.v1.Outcome latest_outcome = 13 [json_name = "latestOutcome", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Experiment, _impl_.latest_outcome_), 13>(), + {104, 13, 0, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.latest_outcome_)}}, + // .google.protobuf.Timestamp updated_at = 14 [json_name = "updatedAt"]; + {::_pbi::TcParser::FastMtS1, + {114, 10, 6, + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.updated_at_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string id = 1 [json_name = "id", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.id_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string location = 2 [json_name = "location", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.location_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string hypothesis = 3 [json_name = "hypothesis", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.hypothesis_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment.v1.Treatment treatment = 4 [json_name = "treatment", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.treatment_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.ExperimentPolicy policy = 5 [json_name = "policy", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.policy_), _Internal::kHasBitsOffset + 6, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.Evidence baseline = 6 [json_name = "baseline", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.baseline_), _Internal::kHasBitsOffset + 7, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated string cohort_order = 7 [json_name = "cohortOrder", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.cohort_order_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kUtf8String | ::_fl::kRepSString)}, + // repeated .xtcp_treatment.v1.Phase phases = 8 [json_name = "phases", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.phases_), _Internal::kHasBitsOffset + 1, 3, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.ExperimentStatus status = 9 [json_name = "status", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.status_), _Internal::kHasBitsOffset + 12, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // uint64 revision = 10 [json_name = "revision"]; + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.revision_), _Internal::kHasBitsOffset + 11, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // .google.protobuf.Timestamp proposed_at = 11 [json_name = "proposedAt"]; + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.proposed_at_), _Internal::kHasBitsOffset + 8, 4, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.Evidence latest_evidence = 12 [json_name = "latestEvidence"]; + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.latest_evidence_), _Internal::kHasBitsOffset + 9, 5, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment.v1.Outcome latest_outcome = 13 [json_name = "latestOutcome", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.latest_outcome_), _Internal::kHasBitsOffset + 13, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .google.protobuf.Timestamp updated_at = 14 [json_name = "updatedAt"]; + {PROTOBUF_FIELD_OFFSET(Experiment, _impl_.updated_at_), _Internal::kHasBitsOffset + 10, 6, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Treatment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Treatment_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ExperimentPolicy>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::ExperimentPolicy_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Evidence>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Evidence_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Phase>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Phase_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Evidence>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Evidence_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + }}, + {{ + "\34\2\10\12\0\0\0\14\0\0\0\0\0\0\0\0" + "xtcp_treatment.v1.Experiment" + "id" + "location" + "hypothesis" + "cohort_order" + }}, + }; +} + + +inline constexpr Experiment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : cohort_order_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Experiment, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.cohort_order_)>() + } + , + phases_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Experiment, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.phases_)>() + } + , + id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + location_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + hypothesis_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + treatment_{nullptr}, + policy_{nullptr}, + baseline_{nullptr}, + proposed_at_{nullptr}, + latest_evidence_{nullptr}, + updated_at_{nullptr}, + revision_{::uint64_t{0u}}, + status_{static_cast< ::xtcp_treatment::v1::ExperimentStatus >(0)}, + latest_outcome_{static_cast< ::xtcp_treatment::v1::Outcome >(0)} {} + +template +constexpr Experiment::Experiment(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Experiment::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Experiment(arena); +} +constexpr auto Experiment::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Experiment), alignof(Experiment)); +} +constexpr auto Experiment::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Experiment::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Experiment::SharedDtor, + Super_::GetClearImpl(), &Experiment::ByteSizeLong, + &Experiment::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Experiment, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[11], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ExperimentGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ExperimentGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Experiment_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Experiment::InternalGenerateClassData_( + _default, &Experiment_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ExperimentGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Experiment _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ExperimentGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ExperimentGlobalsTypeInternal Experiment_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Experiment_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Experiment_globals_.GetClassData(); +#else + return Experiment_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class DesiredState::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(DesiredState, _impl_._has_bits_); +}; + +constexpr DesiredState::ParseTableT_ DesiredState::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_._has_bits_), + 0, // no _extensions_ + 5, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967264, // skipmap + offsetof(ParseTableT_, field_entries), + 5, // num_field_entries + 2, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::DesiredState>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {10, 1, 0, + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.agent_id_)}}, + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(DesiredState, _impl_.revision_), 3>(), + {16, 3, 0, + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.revision_)}}, + // bool suspended = 3 [json_name = "suspended"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 4, 0, + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.suspended_)}}, + // repeated .xtcp_treatment.v1.Assignment assignments = 4 [json_name = "assignments", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtR1, + {34, 0, 0, + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.assignments_)}}, + // .google.protobuf.Timestamp issued_at = 5 [json_name = "issuedAt", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {42, 2, 1, + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.issued_at_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.agent_id_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.revision_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // bool suspended = 3 [json_name = "suspended"]; + {PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.suspended_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // repeated .xtcp_treatment.v1.Assignment assignments = 4 [json_name = "assignments", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.assignments_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp issued_at = 5 [json_name = "issuedAt", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.issued_at_), _Internal::kHasBitsOffset + 2, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Assignment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Assignment_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + }}, + {{ + "\36\10\0\0\0\0\0\0" + "xtcp_treatment.v1.DesiredState" + "agent_id" + }}, + }; +} + + +inline constexpr DesiredState::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : assignments_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::DesiredState, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.assignments_)>() + } + , + agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + issued_at_{nullptr}, + revision_{::uint64_t{0u}}, + suspended_{false} {} + +template +constexpr DesiredState::DesiredState(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL DesiredState::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) DesiredState(arena); +} +constexpr auto DesiredState::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(DesiredState), alignof(DesiredState)); +} +constexpr auto DesiredState::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &DesiredState::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &DesiredState::SharedDtor, + Super_::GetClearImpl(), &DesiredState::ByteSizeLong, + &DesiredState::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[3], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct DesiredStateGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr DesiredStateGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + DesiredState_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(DesiredState::InternalGenerateClassData_( + _default, &DesiredState_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~DesiredStateGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) DesiredState _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(DesiredStateGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST DesiredStateGlobalsTypeInternal DesiredState_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* DesiredState_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return DesiredState_globals_.GetClassData(); +#else + return DesiredState_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class ApplicationRecord::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_._has_bits_); +}; + +constexpr ApplicationRecord::ParseTableT_ ApplicationRecord::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_._has_bits_), + 0, // no _extensions_ + 12, 120, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294963200, // skipmap + offsetof(ParseTableT_, field_entries), + 12, // num_field_entries + 6, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ApplicationRecord>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // .xtcp_treatment.v1.Assignment assignment = 1 [json_name = "assignment", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtS1, + {10, 3, 0, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.assignment_)}}, + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ApplicationRecord, _impl_.desired_revision_), 9>(), + {16, 9, 0, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.desired_revision_)}}, + // .xtcp_treatment.v1.ApplyStatus status = 3 [json_name = "status", (.buf.validate.field) = { + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ApplicationRecord, _impl_.status_), 10>(), + {24, 10, 0, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.status_)}}, + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + {::_pbi::TcParser::FastMtS1, + {34, 4, 1, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.received_at_)}}, + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + {::_pbi::TcParser::FastMtS1, + {42, 5, 2, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.attempted_at_)}}, + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + {::_pbi::TcParser::FastMtS1, + {50, 6, 3, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.applied_at_)}}, + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + {::_pbi::TcParser::FastMtS1, + {58, 7, 4, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.verified_at_)}}, + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + {::_pbi::TcParser::FastMtS1, + {66, 8, 5, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.removed_at_)}}, + // string error = 9 [json_name = "error", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {74, 0, 0, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.error_)}}, + // bytes installed_route = 10 [json_name = "installedRoute", (.buf.validate.field) = { + {::_pbi::TcParser::FastBS1, + {82, 1, 0, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.installed_route_)}}, + // string installed_boot_id = 11 [json_name = "installedBootId", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {90, 2, 0, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.installed_boot_id_)}}, + // bool expired_latched = 12 [json_name = "expiredLatched"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {96, 11, 0, + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.expired_latched_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.Assignment assignment = 1 [json_name = "assignment", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.assignment_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.desired_revision_), _Internal::kHasBitsOffset + 9, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // .xtcp_treatment.v1.ApplyStatus status = 3 [json_name = "status", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.status_), _Internal::kHasBitsOffset + 10, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.received_at_), _Internal::kHasBitsOffset + 4, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.attempted_at_), _Internal::kHasBitsOffset + 5, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.applied_at_), _Internal::kHasBitsOffset + 6, 3, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.verified_at_), _Internal::kHasBitsOffset + 7, 4, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.removed_at_), _Internal::kHasBitsOffset + 8, 5, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // string error = 9 [json_name = "error", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.error_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bytes installed_route = 10 [json_name = "installedRoute", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.installed_route_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)}, + // string installed_boot_id = 11 [json_name = "installedBootId", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.installed_boot_id_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bool expired_latched = 12 [json_name = "expiredLatched"]; + {PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.expired_latched_), _Internal::kHasBitsOffset + 11, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::Assignment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::Assignment_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + }}, + {{ + "\43\0\0\0\0\0\0\0\0\5\0\21\0\0\0\0" + "xtcp_treatment.v1.ApplicationRecord" + "error" + "installed_boot_id" + }}, + }; +} + + +inline constexpr ApplicationRecord::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : error_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + installed_route_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + installed_boot_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + assignment_{nullptr}, + received_at_{nullptr}, + attempted_at_{nullptr}, + applied_at_{nullptr}, + verified_at_{nullptr}, + removed_at_{nullptr}, + desired_revision_{::uint64_t{0u}}, + status_{static_cast< ::xtcp_treatment::v1::ApplyStatus >(0)}, + expired_latched_{false} {} + +template +constexpr ApplicationRecord::ApplicationRecord(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL ApplicationRecord::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) ApplicationRecord(arena); +} +constexpr auto ApplicationRecord::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(ApplicationRecord), alignof(ApplicationRecord)); +} +constexpr auto ApplicationRecord::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &ApplicationRecord::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ApplicationRecord::SharedDtor, + Super_::GetClearImpl(), &ApplicationRecord::ByteSizeLong, + &ApplicationRecord::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[5], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct ApplicationRecordGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr ApplicationRecordGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + ApplicationRecord_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(ApplicationRecord::InternalGenerateClassData_( + _default, &ApplicationRecord_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~ApplicationRecordGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) ApplicationRecord _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(ApplicationRecordGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST ApplicationRecordGlobalsTypeInternal ApplicationRecord_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* ApplicationRecord_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return ApplicationRecord_globals_.GetClassData(); +#else + return ApplicationRecord_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class LocalState::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(LocalState, _impl_._has_bits_); +}; + +constexpr LocalState::ParseTableT_ LocalState::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(LocalState, _impl_._has_bits_), + 0, // no _extensions_ + 5, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967264, // skipmap + offsetof(ParseTableT_, field_entries), + 5, // num_field_entries + 3, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment::v1::LocalState>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + {::_pbi::TcParser::FastMtS1, + {10, 2, 0, + PROTOBUF_FIELD_OFFSET(LocalState, _impl_.desired_)}}, + // bool locally_suspended = 2 [json_name = "locallySuspended"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {16, 4, 0, + PROTOBUF_FIELD_OFFSET(LocalState, _impl_.locally_suspended_)}}, + // string suspension_reason = 3 [json_name = "suspensionReason", (.buf.validate.field) = { + {::_pbi::TcParser::FastUS1, + {26, 1, 0, + PROTOBUF_FIELD_OFFSET(LocalState, _impl_.suspension_reason_)}}, + // repeated .xtcp_treatment.v1.ApplicationRecord records = 4 [json_name = "records", (.buf.validate.field) = { + {::_pbi::TcParser::FastMtR1, + {34, 0, 1, + PROTOBUF_FIELD_OFFSET(LocalState, _impl_.records_)}}, + // .google.protobuf.Timestamp updated_at = 5 [json_name = "updatedAt"]; + {::_pbi::TcParser::FastMtS1, + {42, 3, 2, + PROTOBUF_FIELD_OFFSET(LocalState, _impl_.updated_at_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + {PROTOBUF_FIELD_OFFSET(LocalState, _impl_.desired_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool locally_suspended = 2 [json_name = "locallySuspended"]; + {PROTOBUF_FIELD_OFFSET(LocalState, _impl_.locally_suspended_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // string suspension_reason = 3 [json_name = "suspensionReason", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(LocalState, _impl_.suspension_reason_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // repeated .xtcp_treatment.v1.ApplicationRecord records = 4 [json_name = "records", (.buf.validate.field) = { + {PROTOBUF_FIELD_OFFSET(LocalState, _impl_.records_), _Internal::kHasBitsOffset + 0, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp updated_at = 5 [json_name = "updatedAt"]; + {PROTOBUF_FIELD_OFFSET(LocalState, _impl_.updated_at_), _Internal::kHasBitsOffset + 3, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::DesiredState>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::DesiredState_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment::v1::ApplicationRecord>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment::v1::ApplicationRecord_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + }}, + {{ + "\34\0\0\21\0\0\0\0" + "xtcp_treatment.v1.LocalState" + "suspension_reason" + }}, + }; +} + + +inline constexpr LocalState::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : records_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::LocalState, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.records_)>() + } + , + suspension_reason_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + desired_{nullptr}, + updated_at_{nullptr}, + locally_suspended_{false} {} + +template +constexpr LocalState::LocalState(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL LocalState::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) LocalState(arena); +} +constexpr auto LocalState::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(LocalState), alignof(LocalState)); +} +constexpr auto LocalState::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &LocalState::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &LocalState::SharedDtor, + Super_::GetClearImpl(), &LocalState::ByteSizeLong, + &LocalState::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(LocalState, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[6], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct LocalStateGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr LocalStateGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + LocalState_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(LocalState::InternalGenerateClassData_( + _default, &LocalState_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~LocalStateGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) LocalState _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(LocalStateGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST LocalStateGlobalsTypeInternal LocalState_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* LocalState_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return LocalState_globals_.GetClassData(); +#else + return LocalState_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +} // namespace v1 +} // namespace xtcp_treatment +static const ::_pb::EnumDescriptor* PROTOBUF_NONNULL + file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto[5]; +static constexpr const ::_pb::ServiceDescriptor* PROTOBUF_NONNULL* PROTOBUF_NULLABLE + file_level_service_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto = nullptr; +const ::uint32_t + TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_._has_bits_), + 10, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_.congestion_control_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_.congestion_lock_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_.rto_min_ms_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_.initial_congestion_window_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_.initial_receive_window_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_.quick_ack_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::TCPSettings, _impl_.ecn_), + 0, + 4, + 1, + 2, + 3, + 5, + 6, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Treatment, _impl_._has_bits_), + 8, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Treatment, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Treatment, _impl_.revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Treatment, _impl_.destination_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Treatment, _impl_.settings_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Treatment, _impl_.ecn_fabric_verified_), + 0, + 3, + 1, + 2, + 4, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Assignment, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Assignment, _impl_.experiment_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Assignment, _impl_.treatment_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Assignment, _impl_.mode_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Assignment, _impl_.lease_expires_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Assignment, _impl_.predecessor_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Assignment, _impl_.generation_), + 0, + 1, + 5, + 2, + 3, + 4, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_._has_bits_), + 8, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.agent_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.suspended_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.assignments_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.issued_at_), + 1, + 3, + 4, + 0, + 2, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.boot_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.kernel_release_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.congestion_algorithms_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.simple_host_routing_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.actuator_enabled_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.collection_id_), + 1, + 2, + 0, + 4, + 5, + 3, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_._has_bits_), + 15, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.assignment_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.desired_revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.status_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.received_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.attempted_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.applied_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.verified_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.removed_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.error_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.installed_route_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.installed_boot_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ApplicationRecord, _impl_.expired_latched_), + 3, + 9, + 10, + 4, + 5, + 6, + 7, + 8, + 0, + 1, + 2, + 11, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_._has_bits_), + 8, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.desired_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.locally_suspended_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.suspension_reason_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.records_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.updated_at_), + 2, + 4, + 1, + 0, + 3, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_._has_bits_), + 12, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.agent_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.sockets_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.bytes_acked_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.goodput_bps_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.retransmission_ratio_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.rtt_p95_ms_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.exposed_sockets_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.collection_healthy_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::HostEvidence, _impl_.unbound_sockets_), + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 8, + 7, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_._has_bits_), + 11, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.analyzed_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.window_start_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.window_end_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.query_version_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.enrichment_version_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.hosts_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.artifact_sha256_), + 1, + 5, + 6, + 7, + 2, + 3, + 0, + 4, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_._has_bits_), + 12, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.minimum_observation_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.maximum_phase_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.minimum_sockets_per_host_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.minimum_bytes_per_host_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.minimum_treated_hosts_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.minimum_improvement_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.maximum_retransmission_increase_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.maximum_rtt_increase_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::ExperimentPolicy, _impl_.maximum_evidence_age_), + 0, + 1, + 3, + 4, + 8, + 5, + 6, + 7, + 2, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_._has_bits_), + 11, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.target_hosts_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.issued_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.observation_started_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.evaluated_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.evidence_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.outcome_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.reviewer_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Phase, _impl_.reason_), + 6, + 2, + 3, + 4, + 5, + 7, + 0, + 1, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_._has_bits_), + 17, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.hypothesis_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.treatment_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.policy_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.baseline_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.cohort_order_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.phases_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.status_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.proposed_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.latest_evidence_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.latest_outcome_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.updated_at_), + 2, + 3, + 4, + 5, + 6, + 7, + 0, + 1, + 12, + 11, + 8, + 9, + 13, + 10, +}; + +static const ::_pbi::MigrationSchema + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + {0, sizeof(::xtcp_treatment::v1::TCPSettings)}, + {17, sizeof(::xtcp_treatment::v1::Treatment)}, + {30, sizeof(::xtcp_treatment::v1::Assignment)}, + {45, sizeof(::xtcp_treatment::v1::DesiredState)}, + {58, sizeof(::xtcp_treatment::v1::Capabilities)}, + {73, sizeof(::xtcp_treatment::v1::ApplicationRecord)}, + {100, sizeof(::xtcp_treatment::v1::LocalState)}, + {113, sizeof(::xtcp_treatment::v1::HostEvidence)}, + {134, sizeof(::xtcp_treatment::v1::Evidence)}, + {153, sizeof(::xtcp_treatment::v1::ExperimentPolicy)}, + {174, sizeof(::xtcp_treatment::v1::Phase)}, + {193, sizeof(::xtcp_treatment::v1::Experiment)}, +}; +static const ::_pbi::MessageGlobalsBase* PROTOBUF_NONNULL const + file_message_globals[] = { + &::xtcp_treatment::v1::TCPSettings_globals_, + &::xtcp_treatment::v1::Treatment_globals_, + &::xtcp_treatment::v1::Assignment_globals_, + &::xtcp_treatment::v1::DesiredState_globals_, + &::xtcp_treatment::v1::Capabilities_globals_, + &::xtcp_treatment::v1::ApplicationRecord_globals_, + &::xtcp_treatment::v1::LocalState_globals_, + &::xtcp_treatment::v1::HostEvidence_globals_, + &::xtcp_treatment::v1::Evidence_globals_, + &::xtcp_treatment::v1::ExperimentPolicy_globals_, + &::xtcp_treatment::v1::Phase_globals_, + &::xtcp_treatment::v1::Experiment_globals_, +}; +const char descriptor_table_protodef_xtcp_5ftreatment_2fv1_2ftreatment_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + "\n!xtcp_treatment/v1/treatment.proto\022\021xtc" + "p_treatment.v1\032\033buf/validate/validate.pr" + "oto\032 google/protobuf/descriptor.proto\032\036g" + "oogle/protobuf/duration.proto\032\037google/pr" + "otobuf/timestamp.proto\"\215\007\n\013TCPSettings\022Y" + "\n\022congestion_control\030\001 \001(\tB%\272H\"r \030\0172\034^[a" + "-zA-Z0-9][a-zA-Z0-9_.-]*$H\000R\021congestionC" + "ontrol\210\001\001\022\'\n\017congestion_lock\030\002 \001(\010R\016cong" + "estionLock\022.\n\nrto_min_ms\030\003 \001(\rB\013\272H\010*\006\030\300\251" + "\007(\001H\001R\010rtoMinMs\210\001\001\022K\n\031initial_congestion" + "_window\030\004 \001(\rB\n\272H\007*\005\030\200\010(\001H\002R\027initialCong" + "estionWindow\210\001\001\022E\n\026initial_receive_windo" + "w\030\005 \001(\rB\n\272H\007*\005\030\200\010(\001H\003R\024initialReceiveWin" + "dow\210\001\001\022 \n\tquick_ack\030\006 \001(\010H\004R\010quickAck\210\001\001" + "\022\025\n\003ecn\030\007 \001(\010H\005R\003ecn\210\001\001:\207\003\272H\203\003\032\363\001\n\026tcp_s" + "ettings.non_empty\022/a treatment must set " + "at least one TCP parameter\032\247\001has(this.co" + "ngestion_control) || has(this.rto_min_ms" + ") || has(this.initial_congestion_window)" + " || has(this.initial_receive_window) || " + "has(this.quick_ack) || has(this.ecn)\032\212\001\n" + "$tcp_settings.lock_requires_algorithm\022+c" + "ongestion_lock requires congestion_contr" + "ol\0325!this.congestion_lock || has(this.co" + "ngestion_control)B\025\n\023_congestion_control" + "B\r\n\013_rto_min_msB\034\n\032_initial_congestion_w" + "indowB\031\n\027_initial_receive_windowB\014\n\n_qui" + "ck_ackB\006\n\004_ecn\"\330\003\n\tTreatment\0229\n\002id\030\001 \001(\t" + "B)\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,12" + "7}$R\002id\022#\n\010revision\030\002 \001(\004B\007\272H\0042\002 \000R\010revi" + "sion\022,\n\013destination\030\003 \001(\tB\n\272H\007r\005\0301\350\001\001R\013d" + "estination\022B\n\010settings\030\004 \001(\0132\036.xtcp_trea" + "tment.v1.TCPSettingsB\006\272H\003\310\001\001R\010settings\022." + "\n\023ecn_fabric_verified\030\005 \001(\010R\021ecnFabricVe" + "rified:\310\001\272H\304\001\032\301\001\n\034treatment.dctcp_requir" + "es_ecn\022ADCTCP requires independently ver" + "ified ECN fabric and explicit ECN\032^this." + "settings.congestion_control != \'dctcp\' |" + "| (this.ecn_fabric_verified && this.sett" + "ings.ecn)\"\314\005\n\nAssignment\022N\n\rexperiment_i" + "d\030\002 \001(\tB)\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_." + "-]{0,127}$R\014experimentId\022B\n\ttreatment\030\003 " + "\001(\0132\034.xtcp_treatment.v1.TreatmentB\006\272H\003\310\001" + "\001R\ttreatment\022A\n\004mode\030\004 \001(\0162!.xtcp_treatm" + "ent.v1.AssignmentModeB\n\272H\007\202\001\004\020\001 \000R\004mode\022" + "D\n\020lease_expires_at\030\005 \001(\0132\032.google.proto" + "buf.TimestampR\016leaseExpiresAt\022>\n\013predece" + "ssor\030\006 \001(\0132\034.xtcp_treatment.v1.Treatment" + "R\013predecessor\022\'\n\ngeneration\030\007 \001(\004B\007\272H\0042\002" + " \000R\ngeneration:\255\002\272H\251\002\032}\n\037assignment.tria" + "l_requires_lease\022,a trial assignment req" + "uires lease_expires_at\032,this.mode != 1 |" + "| has(this.lease_expires_at)\032\247\001\n\"assignm" + "ent.predecessor_destination\022+predecessor" + " must cover the same destination\032T!has(t" + "his.predecessor) || this.predecessor.des" + "tination == this.treatment.destinationJ\004" + "\010\001\020\002R\002id\"\244\002\n\014DesiredState\022D\n\010agent_id\030\001 " + "\001(\tB)\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0" + ",127}$R\007agentId\022#\n\010revision\030\002 \001(\004B\007\272H\0042\002" + " \000R\010revision\022\034\n\tsuspended\030\003 \001(\010R\tsuspend" + "ed\022J\n\013assignments\030\004 \003(\0132\035.xtcp_treatment" + ".v1.AssignmentB\t\272H\006\222\001\003\020\200 R\013assignments\022\?" + "\n\tissued_at\030\005 \001(\0132\032.google.protobuf.Time" + "stampB\006\272H\003\310\001\001R\010issuedAt\"\337\002\n\014Capabilities" + "\022B\n\007boot_id\030\001 \001(\tB)\272H&r$2\"^[a-zA-Z0-9][a" + "-zA-Z0-9_.-]{0,127}$R\006bootId\022/\n\016kernel_r" + "elease\030\002 \001(\tB\010\272H\005r\003\030\200\002R\rkernelRelease\022C\n" + "\025congestion_algorithms\030\003 \003(\tB\016\272H\013\222\001\010\020@\"\004" + "r\002\030\017R\024congestionAlgorithms\022.\n\023simple_hos" + "t_routing\030\004 \001(\010R\021simpleHostRouting\022)\n\020ac" + "tuator_enabled\030\005 \001(\010R\017actuatorEnabled\022:\n" + "\rcollection_id\030\006 \001(\tB\025\272H\022r\0202\016^[0-9a-f]{3" + "2}$R\014collectionId\"\250\005\n\021ApplicationRecord\022" + "E\n\nassignment\030\001 \001(\0132\035.xtcp_treatment.v1." + "AssignmentB\006\272H\003\310\001\001R\nassignment\022)\n\020desire" + "d_revision\030\002 \001(\004R\017desiredRevision\022@\n\006sta" + "tus\030\003 \001(\0162\036.xtcp_treatment.v1.ApplyStatu" + "sB\010\272H\005\202\001\002\020\001R\006status\022;\n\013received_at\030\004 \001(\013" + "2\032.google.protobuf.TimestampR\nreceivedAt" + "\022=\n\014attempted_at\030\005 \001(\0132\032.google.protobuf" + ".TimestampR\013attemptedAt\0229\n\napplied_at\030\006 " + "\001(\0132\032.google.protobuf.TimestampR\tapplied" + "At\022;\n\013verified_at\030\007 \001(\0132\032.google.protobu" + "f.TimestampR\nverifiedAt\0229\n\nremoved_at\030\010 " + "\001(\0132\032.google.protobuf.TimestampR\tremoved" + "At\022\036\n\005error\030\t \001(\tB\010\272H\005r\003\030\200 R\005error\0221\n\017in" + "stalled_route\030\n \001(\014B\010\272H\005z\003\030\200 R\016installed" + "Route\0224\n\021installed_boot_id\030\013 \001(\tB\010\272H\005r\003\030" + "\200\001R\017installedBootId\022\'\n\017expired_latched\030\014" + " \001(\010R\016expiredLatched\"\261\002\n\nLocalState\0229\n\007d" + "esired\030\001 \001(\0132\037.xtcp_treatment.v1.Desired" + "StateR\007desired\022+\n\021locally_suspended\030\002 \001(" + "\010R\020locallySuspended\0225\n\021suspension_reason" + "\030\003 \001(\tB\010\272H\005r\003\030\200\010R\020suspensionReason\022I\n\007re" + "cords\030\004 \003(\0132$.xtcp_treatment.v1.Applicat" + "ionRecordB\t\272H\006\222\001\003\020\200@R\007records\0229\n\nupdated" + "_at\030\005 \001(\0132\032.google.protobuf.TimestampR\tu" + "pdatedAt\"\262\004\n\014HostEvidence\022D\n\010agent_id\030\001 " + "\001(\tB)\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0" + ",127}$R\007agentId\022\030\n\007sockets\030\002 \001(\004R\007socket" + "s\022\037\n\013bytes_acked\030\003 \001(\004R\nbytesAcked\0221\n\013go" + "odput_bps\030\004 \001(\001B\020\272H\r\022\013)\000\000\000\000\000\000\000\000@\001R\ngoodp" + "utBps\022C\n\024retransmission_ratio\030\005 \001(\001B\020\272H\r" + "\022\013)\000\000\000\000\000\000\000\000@\001R\023retransmissionRatio\022.\n\nrt" + "t_p95_ms\030\006 \001(\001B\020\272H\r\022\013)\000\000\000\000\000\000\000\000@\001R\010rttP95" + "Ms\022\'\n\017exposed_sockets\030\007 \001(\004R\016exposedSock" + "ets\022-\n\022collection_healthy\030\010 \001(\010R\021collect" + "ionHealthy\022\'\n\017unbound_sockets\030\t \001(\004R\016unb" + "oundSockets:x\272Hu\032s\n$host_evidence.expose" + "d_within_sockets\022%exposed_sockets cannot" + " exceed sockets\032$this.exposed_sockets <=" + " this.sockets\"\274\005\n\010Evidence\0229\n\002id\030\001 \001(\tB)" + "\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}" + "$R\002id\022C\n\013analyzed_at\030\002 \001(\0132\032.google.prot" + "obuf.TimestampB\006\272H\003\310\001\001R\nanalyzedAt\022E\n\014wi" + "ndow_start\030\003 \001(\0132\032.google.protobuf.Times" + "tampB\006\272H\003\310\001\001R\013windowStart\022A\n\nwindow_end\030" + "\004 \001(\0132\032.google.protobuf.TimestampB\006\272H\003\310\001" + "\001R\twindowEnd\022/\n\rquery_version\030\005 \001(\tB\n\272H\007" + "r\005\020\001\030\200\002R\014queryVersion\0227\n\022enrichment_vers" + "ion\030\006 \001(\tB\010\272H\005r\003\030\200\002R\021enrichmentVersion\022B" + "\n\005hosts\030\007 \003(\0132\037.xtcp_treatment.v1.HostEv" + "idenceB\013\272H\010\222\001\005\010\001\020\220NR\005hosts\022>\n\017artifact_s" + "ha256\030\010 \001(\tB\025\272H\022r\0202\016^[0-9a-f]{64}$R\016arti" + "factSha256:\267\001\272H\263\001\032\260\001\n\021evidence.interval\022" + "Owindow_end must follow window_start and" + " analyzed_at must not precede window_end" + "\032Jthis.window_end > this.window_start &&" + " this.analyzed_at >= this.window_end\"\354\006\n" + "\020ExperimentPolicy\022]\n\023minimum_observation" + "\030\001 \001(\0132\031.google.protobuf.DurationB\021\272H\016\252\001" + "\010\"\004\010\200\365$*\000\310\001\001R\022minimumObservation\022Q\n\rmaxi" + "mum_phase\030\002 \001(\0132\031.google.protobuf.Durati" + "onB\021\272H\016\252\001\010\"\004\010\200\365$*\000\310\001\001R\014maximumPhase\022@\n\030m" + "inimum_sockets_per_host\030\003 \001(\004B\007\272H\0042\002 \000R\025" + "minimumSocketsPerHost\022<\n\026minimum_bytes_p" + "er_host\030\004 \001(\004B\007\272H\0042\002 \000R\023minimumBytesPerH" + "ost\022>\n\025minimum_treated_hosts\030\005 \001(\rB\n\272H\007*" + "\005\030\220N(\002R\023minimumTreatedHosts\022J\n\023minimum_i" + "mprovement\030\006 \001(\001B\031\272H\026\022\024\031\000\000\000\000\000\000\360\?)\000\000\000\000\000\000\000" + "\000@\001R\022minimumImprovement\022a\n\037maximum_retra" + "nsmission_increase\030\007 \001(\001B\031\272H\026\022\024\031\000\000\000\000\000\000\360\?" + ")\000\000\000\000\000\000\000\000@\001R\035maximumRetransmissionIncrea" + "se\022K\n\024maximum_rtt_increase\030\010 \001(\001B\031\272H\026\022\024\031" + "\000\000\000\000\000\000\360\?)\000\000\000\000\000\000\000\000@\001R\022maximumRttIncrease\022" + "^\n\024maximum_evidence_age\030\t \001(\0132\031.google.p" + "rotobuf.DurationB\021\272H\016\252\001\010\"\004\010\200\365$*\000\310\001\001R\022max" + "imumEvidenceAge:\211\001\272H\205\001\032\202\001\n\037policy.observ" + "ation_within_phase\022/minimum_observation " + "cannot exceed maximum_phase\032.this.minimu" + "m_observation <= this.maximum_phase\"\301\003\n\005" + "Phase\022-\n\014target_hosts\030\001 \001(\rB\n\272H\007*\005\030\220N(\001R" + "\013targetHosts\0227\n\tissued_at\030\002 \001(\0132\032.google" + ".protobuf.TimestampR\010issuedAt\022P\n\026observa" + "tion_started_at\030\003 \001(\0132\032.google.protobuf." + "TimestampR\024observationStartedAt\022=\n\014evalu" + "ated_at\030\004 \001(\0132\032.google.protobuf.Timestam" + "pR\013evaluatedAt\0227\n\010evidence\030\005 \001(\0132\033.xtcp_" + "treatment.v1.EvidenceR\010evidence\022>\n\007outco" + "me\030\006 \001(\0162\032.xtcp_treatment.v1.OutcomeB\010\272H" + "\005\202\001\002\020\001R\007outcome\022$\n\010reviewer\030\007 \001(\tB\010\272H\005r\003" + "\030\200\001R\010reviewer\022 \n\006reason\030\010 \001(\tB\010\272H\005r\003\030\200 R" + "\006reason\"\210\007\n\nExperiment\0229\n\002id\030\001 \001(\tB)\272H&r" + "$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\002i" + "d\022E\n\010location\030\002 \001(\tB)\272H&r$2\"^[a-zA-Z0-9]" + "[a-zA-Z0-9_.-]{0,127}$R\010location\022*\n\nhypo" + "thesis\030\003 \001(\tB\n\272H\007r\005\020\001\030\200@R\nhypothesis\022B\n\t" + "treatment\030\004 \001(\0132\034.xtcp_treatment.v1.Trea" + "tmentB\006\272H\003\310\001\001R\ttreatment\022C\n\006policy\030\005 \001(\013" + "2#.xtcp_treatment.v1.ExperimentPolicyB\006\272" + "H\003\310\001\001R\006policy\022\?\n\010baseline\030\006 \001(\0132\033.xtcp_t" + "reatment.v1.EvidenceB\006\272H\003\310\001\001R\010baseline\022X" + "\n\014cohort_order\030\007 \003(\tB5\272H2\222\001/\010\003\020\220N\030\001\"&r$2" + "\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\013coh" + "ortOrder\022:\n\006phases\030\010 \003(\0132\030.xtcp_treatmen" + "t.v1.PhaseB\010\272H\005\222\001\002\020@R\006phases\022E\n\006status\030\t" + " \001(\0162#.xtcp_treatment.v1.ExperimentStatu" + "sB\010\272H\005\202\001\002\020\001R\006status\022\032\n\010revision\030\n \001(\004R\010r" + "evision\022;\n\013proposed_at\030\013 \001(\0132\032.google.pr" + "otobuf.TimestampR\nproposedAt\022D\n\017latest_e" + "vidence\030\014 \001(\0132\033.xtcp_treatment.v1.Eviden" + "ceR\016latestEvidence\022K\n\016latest_outcome\030\r \001" + "(\0162\032.xtcp_treatment.v1.OutcomeB\010\272H\005\202\001\002\020\001" + "R\rlatestOutcome\0229\n\nupdated_at\030\016 \001(\0132\032.go" + "ogle.protobuf.TimestampR\tupdatedAt*\?\n\004Ro" + "le\022\024\n\020ROLE_UNSPECIFIED\020\000\022\016\n\nROLE_AGENT\020\001" + "\022\021\n\rROLE_OPERATOR\020\002*\244\001\n\016AssignmentMode\022\037" + "\n\033ASSIGNMENT_MODE_UNSPECIFIED\020\000\022\031\n\025ASSIG" + "NMENT_MODE_TRIAL\020\001\022\032\n\026ASSIGNMENT_MODE_ST" + "ABLE\020\002\022\035\n\031ASSIGNMENT_MODE_SUSPENDED\020\003\022\033\n" + "\027ASSIGNMENT_MODE_RETIRED\020\004*\255\001\n\013ApplyStat" + "us\022\034\n\030APPLY_STATUS_UNSPECIFIED\020\000\022\030\n\024APPL" + "Y_STATUS_PENDING\020\001\022\031\n\025APPLY_STATUS_VERIF" + "IED\020\002\022\030\n\024APPLY_STATUS_REMOVED\020\003\022\030\n\024APPLY" + "_STATUS_EXPIRED\020\004\022\027\n\023APPLY_STATUS_FAILED" + "\020\005*\244\004\n\007Outcome\022\027\n\023OUTCOME_UNSPECIFIED\020\000\022" + "\024\n\020OUTCOME_BASELINE\020\001\022 \n\034OUTCOME_AWAITIN" + "G_APPLICATION\020\002\022\035\n\031OUTCOME_AWAITING_EXPO" + "SURE\020\003\022!\n\035OUTCOME_INSUFFICIENT_DURATION\020" + "\004\022\035\n\031OUTCOME_INSUFFICIENT_DATA\020\005\022!\n\035OUTC" + "OME_INSUFFICIENT_CONTROLS\020\006\022\021\n\rOUTCOME_S" + "TALE\020\007\022\027\n\023OUTCOME_UNAVAILABLE\020\010\022\030\n\024OUTCO" + "ME_INCONCLUSIVE\020\t\022\027\n\023OUTCOME_SAFETY_ONLY" + "\020\n\022\030\n\024OUTCOME_FINAL_SAFETY\020\013\022\026\n\022OUTCOME_" + "BENEFICIAL\020\014\022\023\n\017OUTCOME_HARMFUL\020\r\022\023\n\017OUT" + "COME_EXPIRED\020\016\022\033\n\027OUTCOME_STABLE_OBSERVE" + "D\020\017\022&\n\"OUTCOME_STABLE_EVIDENCE_INCOMPLET" + "E\020\020\022-\n)OUTCOME_STABLE_REGRESSION_REVIEW_" + "REQUIRED\020\021\022\025\n\021OUTCOME_OBSERVING\020\022*\225\002\n\020Ex" + "perimentStatus\022!\n\035EXPERIMENT_STATUS_UNSP" + "ECIFIED\020\000\022\036\n\032EXPERIMENT_STATUS_PROPOSED\020" + "\001\022\035\n\031EXPERIMENT_STATUS_RUNNING\020\002\022\034\n\030EXPE" + "RIMENT_STATUS_PAUSED\020\003\022\037\n\033EXPERIMENT_STA" + "TUS_SUSPENDED\020\004\022\036\n\032EXPERIMENT_STATUS_COM" + "PLETE\020\005\022\035\n\031EXPERIMENT_STATUS_RETIRED\020\006\022!" + "\n\035EXPERIMENT_STATUS_ROLLED_BACK\020\007:M\n\004rol" + "e\022\036.google.protobuf.MethodOptions\030\272\216\003 \001(" + "\0162\027.xtcp_treatment.v1.RoleR\004roleB\300\001\n\025com" + ".xtcp_treatment.v1B\016TreatmentProtoP\001Z6gi" + "thub.com/randomizedcoder/xtcp2/gen/go/xt" + "cp_treatment\242\002\003XXX\252\002\020XtcpTreatment.V1\312\002\020" + "XtcpTreatment\\V1\342\002\034XtcpTreatment\\V1\\GPBM" + "etadata\352\002\021XtcpTreatment::V1b\006proto3" +}; +static const ::_pbi::DescriptorTable* PROTOBUF_NONNULL const + descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto_deps[4] = { + &::descriptor_table_buf_2fvalidate_2fvalidate_2eproto, + &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + &::descriptor_table_google_2fprotobuf_2fduration_2eproto, + &::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto, +}; +static ::absl::once_flag descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto_once; +PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto = { + false, + false, + 8955, + descriptor_table_protodef_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + "xtcp_treatment/v1/treatment.proto", + &descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto_once, + descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto_deps, + 4, + 12, + schemas, + file_message_globals, + TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto::offsets, + file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, + file_level_service_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto, +}; +namespace xtcp_treatment { +namespace v1 { +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +Role_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto[0]; +} +PROTOBUF_CONSTINIT const uint32_t Role_internal_data_[] = { + 196608u, 0u, }; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +AssignmentMode_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto[1]; +} +PROTOBUF_CONSTINIT const uint32_t AssignmentMode_internal_data_[] = { + 327680u, 0u, }; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ApplyStatus_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto[2]; +} +PROTOBUF_CONSTINIT const uint32_t ApplyStatus_internal_data_[] = { + 393216u, 0u, }; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +Outcome_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto[3]; +} +PROTOBUF_CONSTINIT const uint32_t Outcome_internal_data_[] = { + 1245184u, 0u, }; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ExperimentStatus_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_2fv1_2ftreatment_2eproto[4]; +} +PROTOBUF_CONSTINIT const uint32_t ExperimentStatus_internal_data_[] = { + 524288u, 0u, }; +// =================================================================== + +TCPSettings::TCPSettings(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, TCPSettings_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.TCPSettings) +} +PROTOBUF_NDEBUG_INLINE TCPSettings::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::TCPSettings& from_msg) + : _has_bits_{from._has_bits_}, + congestion_control_(arena, from.congestion_control_) {} + +TCPSettings::TCPSettings( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const TCPSettings& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, TCPSettings_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + TCPSettings* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, rto_min_ms_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, rto_min_ms_), + offsetof(Impl_, ecn_) - + offsetof(Impl_, rto_min_ms_) + + sizeof(Impl_::ecn_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.TCPSettings) +} +PROTOBUF_NDEBUG_INLINE TCPSettings::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : congestion_control_(arena) {} + +inline void TCPSettings::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, rto_min_ms_), + 0, + offsetof(Impl_, ecn_) - + offsetof(Impl_, rto_min_ms_) + + sizeof(Impl_::ecn_)); +} +TCPSettings::~TCPSettings() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.TCPSettings) + SharedDtor(*this); +} +inline void TCPSettings::SharedDtor(MessageLite& self) { + TCPSettings& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.congestion_control_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TCPSettings_class_data_ = + TCPSettings::InternalGenerateClassData_(TCPSettings_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TCPSettings::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TCPSettings_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TCPSettings_class_data_.tc_table); + return TCPSettings_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TCPSettings::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TCPSettings_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&TCPSettings_globals_)); + return TCPSettings_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const TCPSettings::ParseTableT_ + TCPSettings::_table_ = + TCPSettings::InternalGenerateParseTable_(TCPSettings_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void TCPSettings::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.TCPSettings) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.congestion_control_.ClearNonDefaultToEmpty(); + } + if (BatchCheckHasBit(cached_has_bits, 0x0000007eU)) { + ::memset(&this_._impl_.rto_min_ms_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.ecn_) - + reinterpret_cast(&this_._impl_.rto_min_ms_)) + + sizeof(_impl_.ecn_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TCPSettings::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TCPSettings& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TCPSettings::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TCPSettings& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.TCPSettings) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string congestion_control = 1 [json_name = "congestionControl", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + const ::std::string& _s = this_._internal_congestion_control(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.TCPSettings.congestion_control"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // bool congestion_lock = 2 [json_name = "congestionLock"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_congestion_lock() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_congestion_lock(), target); + } + } + + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_rto_min_ms(), target); + } + + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 4, this_._internal_initial_congestion_window(), target); + } + + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 5, this_._internal_initial_receive_window(), target); + } + + // optional bool quick_ack = 6 [json_name = "quickAck"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_quick_ack(), target); + } + + // optional bool ecn = 7 [json_name = "ecn"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 7, this_._internal_ecn(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.TCPSettings) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TCPSettings::ByteSizeLong(const MessageLite& base) { + const TCPSettings& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TCPSettings::ByteSizeLong() const { + const TCPSettings& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.TCPSettings) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + total_size += ::absl::popcount(0x00000060U & cached_has_bits) * 2; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + // optional string congestion_control = 1 [json_name = "congestionControl", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_congestion_control()); + } + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_rto_min_ms()); + } + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_initial_congestion_window()); + } + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_initial_receive_window()); + } + // bool congestion_lock = 2 [json_name = "congestionLock"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_congestion_lock() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TCPSettings::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.TCPSettings) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000007fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_set_congestion_control(from._internal_congestion_control()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + _this->_impl_.rto_min_ms_ = from._impl_.rto_min_ms_; + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + _this->_impl_.initial_congestion_window_ = from._impl_.initial_congestion_window_; + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + _this->_impl_.initial_receive_window_ = from._impl_.initial_receive_window_; + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_congestion_lock() != 0) { + _this->_impl_.congestion_lock_ = from._impl_.congestion_lock_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + _this->_impl_.quick_ack_ = from._impl_.quick_ack_; + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + _this->_impl_.ecn_ = from._impl_.ecn_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void TCPSettings::CopyFrom(const TCPSettings& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.TCPSettings) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TCPSettings::InternalSwap(TCPSettings* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.congestion_control_, &other->_impl_.congestion_control_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.ecn_) + + sizeof(TCPSettings::_impl_.ecn_) + - PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.rto_min_ms_)>( + reinterpret_cast(&_impl_.rto_min_ms_), + reinterpret_cast(&other->_impl_.rto_min_ms_)); +} + +::google::protobuf::Metadata TCPSettings::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +Treatment::Treatment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Treatment_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.Treatment) +} +PROTOBUF_NDEBUG_INLINE Treatment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::Treatment& from_msg) + : _has_bits_{from._has_bits_}, + id_(arena, from.id_), + destination_(arena, from.destination_) {} + +Treatment::Treatment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Treatment& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Treatment_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Treatment* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.settings_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.settings_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, revision_), + offsetof(Impl_, ecn_fabric_verified_) - + offsetof(Impl_, revision_) + + sizeof(Impl_::ecn_fabric_verified_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.Treatment) +} +PROTOBUF_NDEBUG_INLINE Treatment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : id_(arena), + destination_(arena) {} + +inline void Treatment::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, settings_), + 0, + offsetof(Impl_, ecn_fabric_verified_) - + offsetof(Impl_, settings_) + + sizeof(Impl_::ecn_fabric_verified_)); +} +Treatment::~Treatment() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.Treatment) + SharedDtor(*this); +} +inline void Treatment::SharedDtor(MessageLite& self) { + Treatment& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.id_.Destroy(); + this_._impl_.destination_.Destroy(); + delete this_._impl_.settings_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Treatment_class_data_ = + Treatment::InternalGenerateClassData_(Treatment_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Treatment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Treatment_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Treatment_class_data_.tc_table); + return Treatment_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Treatment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Treatment_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Treatment_globals_)); + return Treatment_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Treatment::ParseTableT_ + Treatment::_table_ = + Treatment::InternalGenerateParseTable_(Treatment_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Treatment::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.Treatment) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.destination_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.settings_ != nullptr); + this_._impl_.settings_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000018U)) { + ::memset(&this_._impl_.revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.ecn_fabric_verified_) - + reinterpret_cast(&this_._impl_.revision_)) + + sizeof(_impl_.ecn_fabric_verified_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Treatment::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Treatment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Treatment::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Treatment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.Treatment) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string id = 1 [json_name = "id", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_id().empty()) { + const ::std::string& _s = this_._internal_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Treatment.id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_revision(), target); + } + } + + // string destination = 3 [json_name = "destination", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_destination().empty()) { + const ::std::string& _s = this_._internal_destination(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Treatment.destination"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + } + + // .xtcp_treatment.v1.TCPSettings settings = 4 [json_name = "settings", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.settings_, this_._impl_.settings_->GetCachedSize(), target, + stream); + } + + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_ecn_fabric_verified() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_ecn_fabric_verified(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.Treatment) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Treatment::ByteSizeLong(const MessageLite& base) { + const Treatment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Treatment::ByteSizeLong() const { + const Treatment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.Treatment) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + // string id = 1 [json_name = "id", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_id()); + } + } + // string destination = 3 [json_name = "destination", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_destination().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_destination()); + } + } + // .xtcp_treatment.v1.TCPSettings settings = 4 [json_name = "settings", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.settings_); + } + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_revision()); + } + } + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_ecn_fabric_verified() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Treatment::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.Treatment) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_id().empty()) { + _this->_internal_set_id(from._internal_id()); + } else { + if (_this->_impl_.id_.IsDefault()) { + _this->_internal_set_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_destination().empty()) { + _this->_internal_set_destination(from._internal_destination()); + } else { + if (_this->_impl_.destination_.IsDefault()) { + _this->_internal_set_destination(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.settings_ != nullptr); + if (_this->_impl_.settings_ == nullptr) { + _this->_impl_.settings_ = Super_::CopyConstruct(arena, *from._impl_.settings_); + } else { + _this->_impl_.settings_->MergeFrom(*from._impl_.settings_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (from._internal_revision() != 0) { + _this->_impl_.revision_ = from._impl_.revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_ecn_fabric_verified() != 0) { + _this->_impl_.ecn_fabric_verified_ = from._impl_.ecn_fabric_verified_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Treatment::CopyFrom(const Treatment& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.Treatment) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Treatment::InternalSwap(Treatment* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.id_, &other->_impl_.id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.destination_, &other->_impl_.destination_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.ecn_fabric_verified_) + + sizeof(Treatment::_impl_.ecn_fabric_verified_) + - PROTOBUF_FIELD_OFFSET(Treatment, _impl_.settings_)>( + reinterpret_cast(&_impl_.settings_), + reinterpret_cast(&other->_impl_.settings_)); +} + +::google::protobuf::Metadata Treatment::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Assignment::clear_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.lease_expires_at_ != nullptr) _impl_.lease_expires_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +Assignment::Assignment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Assignment_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.Assignment) +} +PROTOBUF_NDEBUG_INLINE Assignment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::Assignment& from_msg) + : _has_bits_{from._has_bits_}, + experiment_id_(arena, from.experiment_id_) {} + +Assignment::Assignment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Assignment& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Assignment_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Assignment* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.treatment_ = (CheckHasBit(cached_has_bits, 0x00000002U)) + ? Super_::CopyConstruct(arena, *from._impl_.treatment_) + : nullptr; + _impl_.lease_expires_at_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.lease_expires_at_) + : nullptr; + _impl_.predecessor_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.predecessor_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, generation_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, generation_), + offsetof(Impl_, mode_) - + offsetof(Impl_, generation_) + + sizeof(Impl_::mode_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.Assignment) +} +PROTOBUF_NDEBUG_INLINE Assignment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : experiment_id_(arena) {} + +inline void Assignment::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, treatment_), + 0, + offsetof(Impl_, mode_) - + offsetof(Impl_, treatment_) + + sizeof(Impl_::mode_)); +} +Assignment::~Assignment() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.Assignment) + SharedDtor(*this); +} +inline void Assignment::SharedDtor(MessageLite& self) { + Assignment& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.experiment_id_.Destroy(); + delete this_._impl_.treatment_; + delete this_._impl_.lease_expires_at_; + delete this_._impl_.predecessor_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Assignment_class_data_ = + Assignment::InternalGenerateClassData_(Assignment_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Assignment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Assignment_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Assignment_class_data_.tc_table); + return Assignment_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Assignment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Assignment_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Assignment_globals_)); + return Assignment_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Assignment::ParseTableT_ + Assignment::_table_ = + Assignment::InternalGenerateParseTable_(Assignment_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Assignment::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.Assignment) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.experiment_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(this_._impl_.treatment_ != nullptr); + this_._impl_.treatment_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.lease_expires_at_ != nullptr); + this_._impl_.lease_expires_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.predecessor_ != nullptr); + this_._impl_.predecessor_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000030U)) { + ::memset(&this_._impl_.generation_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.mode_) - + reinterpret_cast(&this_._impl_.generation_)) + + sizeof(_impl_.mode_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Assignment::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Assignment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Assignment::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Assignment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.Assignment) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string experiment_id = 2 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + const ::std::string& _s = this_._internal_experiment_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Assignment.experiment_id"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + // .xtcp_treatment.v1.Treatment treatment = 3 [json_name = "treatment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.treatment_, this_._impl_.treatment_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.AssignmentMode mode = 4 [json_name = "mode", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_mode() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this_._internal_mode(), target); + } + } + + // .google.protobuf.Timestamp lease_expires_at = 5 [json_name = "leaseExpiresAt"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.lease_expires_at_, this_._impl_.lease_expires_at_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.Treatment predecessor = 6 [json_name = "predecessor"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.predecessor_, this_._impl_.predecessor_->GetCachedSize(), target, + stream); + } + + // uint64 generation = 7 [json_name = "generation", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_generation() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 7, this_._internal_generation(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.Assignment) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Assignment::ByteSizeLong(const MessageLite& base) { + const Assignment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Assignment::ByteSizeLong() const { + const Assignment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.Assignment) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + // string experiment_id = 2 [json_name = "experimentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_experiment_id()); + } + } + // .xtcp_treatment.v1.Treatment treatment = 3 [json_name = "treatment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.treatment_); + } + // .google.protobuf.Timestamp lease_expires_at = 5 [json_name = "leaseExpiresAt"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.lease_expires_at_); + } + // .xtcp_treatment.v1.Treatment predecessor = 6 [json_name = "predecessor"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.predecessor_); + } + // uint64 generation = 7 [json_name = "generation", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_generation() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_generation()); + } + } + // .xtcp_treatment.v1.AssignmentMode mode = 4 [json_name = "mode", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_mode() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_mode()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Assignment::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.Assignment) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_experiment_id().empty()) { + _this->_internal_set_experiment_id(from._internal_experiment_id()); + } else { + if (_this->_impl_.experiment_id_.IsDefault()) { + _this->_internal_set_experiment_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(from._impl_.treatment_ != nullptr); + if (_this->_impl_.treatment_ == nullptr) { + _this->_impl_.treatment_ = Super_::CopyConstruct(arena, *from._impl_.treatment_); + } else { + _this->_impl_.treatment_->MergeFrom(*from._impl_.treatment_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.lease_expires_at_ != nullptr); + if (_this->_impl_.lease_expires_at_ == nullptr) { + _this->_impl_.lease_expires_at_ = Super_::CopyConstruct(arena, *from._impl_.lease_expires_at_); + } else { + _this->_impl_.lease_expires_at_->MergeFrom(*from._impl_.lease_expires_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.predecessor_ != nullptr); + if (_this->_impl_.predecessor_ == nullptr) { + _this->_impl_.predecessor_ = Super_::CopyConstruct(arena, *from._impl_.predecessor_); + } else { + _this->_impl_.predecessor_->MergeFrom(*from._impl_.predecessor_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_generation() != 0) { + _this->_impl_.generation_ = from._impl_.generation_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (from._internal_mode() != 0) { + _this->_impl_.mode_ = from._impl_.mode_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Assignment::CopyFrom(const Assignment& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.Assignment) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Assignment::InternalSwap(Assignment* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.experiment_id_, &other->_impl_.experiment_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.mode_) + + sizeof(Assignment::_impl_.mode_) + - PROTOBUF_FIELD_OFFSET(Assignment, _impl_.treatment_)>( + reinterpret_cast(&_impl_.treatment_), + reinterpret_cast(&other->_impl_.treatment_)); +} + +::google::protobuf::Metadata Assignment::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void DesiredState::clear_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.issued_at_ != nullptr) _impl_.issued_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +DesiredState::DesiredState(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, DesiredState_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.DesiredState) +} +PROTOBUF_NDEBUG_INLINE DesiredState::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::DesiredState& from_msg) + : _has_bits_{from._has_bits_}, + assignments_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::DesiredState, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.assignments_)>() + , arena, from.assignments_ + } + , + agent_id_(arena, from.agent_id_) {} + +DesiredState::DesiredState( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const DesiredState& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, DesiredState_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + DesiredState* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.issued_at_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.issued_at_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, revision_), + offsetof(Impl_, suspended_) - + offsetof(Impl_, revision_) + + sizeof(Impl_::suspended_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.DesiredState) +} +PROTOBUF_NDEBUG_INLINE DesiredState::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : assignments_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::DesiredState, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::DesiredState, _impl_.assignments_)>() + } + , + agent_id_(arena) {} + +inline void DesiredState::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, issued_at_), + 0, + offsetof(Impl_, suspended_) - + offsetof(Impl_, issued_at_) + + sizeof(Impl_::suspended_)); +} +DesiredState::~DesiredState() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.DesiredState) + SharedDtor(*this); +} +inline void DesiredState::SharedDtor(MessageLite& self) { + DesiredState& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.agent_id_.Destroy(); + delete this_._impl_.issued_at_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull DesiredState_class_data_ = + DesiredState::InternalGenerateClassData_(DesiredState_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +DesiredState::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&DesiredState_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(DesiredState_class_data_.tc_table); + return DesiredState_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +DesiredState::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&DesiredState_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&DesiredState_globals_)); + return DesiredState_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const DesiredState::ParseTableT_ + DesiredState::_table_ = + DesiredState::InternalGenerateParseTable_(DesiredState_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void DesiredState::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.DesiredState) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.assignments_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.issued_at_ != nullptr); + this_._impl_.issued_at_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000018U)) { + ::memset(&this_._impl_.revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.suspended_) - + reinterpret_cast(&this_._impl_.revision_)) + + sizeof(_impl_.suspended_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL DesiredState::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const DesiredState& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL DesiredState::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const DesiredState& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.DesiredState) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.DesiredState.agent_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_revision(), target); + } + } + + // bool suspended = 3 [json_name = "suspended"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_suspended() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_suspended(), target); + } + } + + // repeated .xtcp_treatment.v1.Assignment assignments = 4 [json_name = "assignments", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_assignments_size()); + i < n; i++) { + const auto& repfield = this_._internal_assignments().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // .google.protobuf.Timestamp issued_at = 5 [json_name = "issuedAt", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.issued_at_, this_._impl_.issued_at_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.DesiredState) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t DesiredState::ByteSizeLong(const MessageLite& base) { + const DesiredState& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t DesiredState::ByteSizeLong() const { + const DesiredState& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.DesiredState) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + // repeated .xtcp_treatment.v1.Assignment assignments = 4 [json_name = "assignments", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_assignments_size(); + for (const auto& msg : this_._internal_assignments()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + // .google.protobuf.Timestamp issued_at = 5 [json_name = "issuedAt", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.issued_at_); + } + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_revision()); + } + } + // bool suspended = 3 [json_name = "suspended"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_suspended() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void DesiredState::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.DesiredState) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_assignments()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_assignments()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.issued_at_ != nullptr); + if (_this->_impl_.issued_at_ == nullptr) { + _this->_impl_.issued_at_ = Super_::CopyConstruct(arena, *from._impl_.issued_at_); + } else { + _this->_impl_.issued_at_->MergeFrom(*from._impl_.issued_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (from._internal_revision() != 0) { + _this->_impl_.revision_ = from._impl_.revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_suspended() != 0) { + _this->_impl_.suspended_ = from._impl_.suspended_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void DesiredState::CopyFrom(const DesiredState& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.DesiredState) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void DesiredState::InternalSwap(DesiredState* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.assignments_.InternalSwap(&other->_impl_.assignments_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.suspended_) + + sizeof(DesiredState::_impl_.suspended_) + - PROTOBUF_FIELD_OFFSET(DesiredState, _impl_.issued_at_)>( + reinterpret_cast(&_impl_.issued_at_), + reinterpret_cast(&other->_impl_.issued_at_)); +} + +::google::protobuf::Metadata DesiredState::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +Capabilities::Capabilities(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Capabilities_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.Capabilities) +} +PROTOBUF_NDEBUG_INLINE Capabilities::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::Capabilities& from_msg) + : _has_bits_{from._has_bits_}, + congestion_algorithms_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Capabilities, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.congestion_algorithms_)>() + , arena, from.congestion_algorithms_ + } + , + boot_id_(arena, from.boot_id_), + kernel_release_(arena, from.kernel_release_), + collection_id_(arena, from.collection_id_) {} + +Capabilities::Capabilities( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Capabilities& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Capabilities_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Capabilities* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, simple_host_routing_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, simple_host_routing_), + offsetof(Impl_, actuator_enabled_) - + offsetof(Impl_, simple_host_routing_) + + sizeof(Impl_::actuator_enabled_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.Capabilities) +} +PROTOBUF_NDEBUG_INLINE Capabilities::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : congestion_algorithms_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Capabilities, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Capabilities, _impl_.congestion_algorithms_)>() + } + , + boot_id_(arena), + kernel_release_(arena), + collection_id_(arena) {} + +inline void Capabilities::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, simple_host_routing_), + 0, + offsetof(Impl_, actuator_enabled_) - + offsetof(Impl_, simple_host_routing_) + + sizeof(Impl_::actuator_enabled_)); +} +Capabilities::~Capabilities() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.Capabilities) + SharedDtor(*this); +} +inline void Capabilities::SharedDtor(MessageLite& self) { + Capabilities& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.boot_id_.Destroy(); + this_._impl_.kernel_release_.Destroy(); + this_._impl_.collection_id_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Capabilities_class_data_ = + Capabilities::InternalGenerateClassData_(Capabilities_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Capabilities::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Capabilities_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Capabilities_class_data_.tc_table); + return Capabilities_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Capabilities::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Capabilities_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Capabilities_globals_)); + return Capabilities_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Capabilities::ParseTableT_ + Capabilities::_table_ = + Capabilities::InternalGenerateParseTable_(Capabilities_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Capabilities::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.Capabilities) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.congestion_algorithms_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.boot_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.kernel_release_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + this_._impl_.collection_id_.ClearNonDefaultToEmpty(); + } + } + ::memset(&this_._impl_.simple_host_routing_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.actuator_enabled_) - + reinterpret_cast(&this_._impl_.simple_host_routing_)) + + sizeof(_impl_.actuator_enabled_)); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Capabilities::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Capabilities& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Capabilities::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Capabilities& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.Capabilities) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string boot_id = 1 [json_name = "bootId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_boot_id().empty()) { + const ::std::string& _s = this_._internal_boot_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Capabilities.boot_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string kernel_release = 2 [json_name = "kernelRelease", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_kernel_release().empty()) { + const ::std::string& _s = this_._internal_kernel_release(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Capabilities.kernel_release"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + // repeated string congestion_algorithms = 3 [json_name = "congestionAlgorithms", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (int i = 0, n = this_._internal_congestion_algorithms_size(); i < n; ++i) { + const auto& s = this_._internal_congestion_algorithms().Get(i); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Capabilities.congestion_algorithms"); + target = stream->WriteString(3, s, target); + } + } + + // bool simple_host_routing = 4 [json_name = "simpleHostRouting"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_simple_host_routing() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 4, this_._internal_simple_host_routing(), target); + } + } + + // bool actuator_enabled = 5 [json_name = "actuatorEnabled"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_actuator_enabled() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_actuator_enabled(), target); + } + } + + // string collection_id = 6 [json_name = "collectionId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_collection_id().empty()) { + const ::std::string& _s = this_._internal_collection_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Capabilities.collection_id"); + target = stream->WriteStringMaybeAliased(6, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.Capabilities) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Capabilities::ByteSizeLong(const MessageLite& base) { + const Capabilities& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Capabilities::ByteSizeLong() const { + const Capabilities& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.Capabilities) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + // repeated string congestion_algorithms = 3 [json_name = "congestionAlgorithms", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_congestion_algorithms().size()); + for (int i = 0, n = this_._internal_congestion_algorithms().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_congestion_algorithms().Get(i)); + } + } + // string boot_id = 1 [json_name = "bootId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_boot_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_boot_id()); + } + } + // string kernel_release = 2 [json_name = "kernelRelease", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_kernel_release().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_kernel_release()); + } + } + // string collection_id = 6 [json_name = "collectionId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_collection_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_collection_id()); + } + } + // bool simple_host_routing = 4 [json_name = "simpleHostRouting"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_simple_host_routing() != 0) { + total_size += 2; + } + } + // bool actuator_enabled = 5 [json_name = "actuatorEnabled"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_actuator_enabled() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Capabilities::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.Capabilities) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_congestion_algorithms()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_congestion_algorithms()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_boot_id().empty()) { + _this->_internal_set_boot_id(from._internal_boot_id()); + } else { + if (_this->_impl_.boot_id_.IsDefault()) { + _this->_internal_set_boot_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_kernel_release().empty()) { + _this->_internal_set_kernel_release(from._internal_kernel_release()); + } else { + if (_this->_impl_.kernel_release_.IsDefault()) { + _this->_internal_set_kernel_release(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!from._internal_collection_id().empty()) { + _this->_internal_set_collection_id(from._internal_collection_id()); + } else { + if (_this->_impl_.collection_id_.IsDefault()) { + _this->_internal_set_collection_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_simple_host_routing() != 0) { + _this->_impl_.simple_host_routing_ = from._impl_.simple_host_routing_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (from._internal_actuator_enabled() != 0) { + _this->_impl_.actuator_enabled_ = from._impl_.actuator_enabled_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Capabilities::CopyFrom(const Capabilities& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.Capabilities) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Capabilities::InternalSwap(Capabilities* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.congestion_algorithms_.InternalSwap(&other->_impl_.congestion_algorithms_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.boot_id_, &other->_impl_.boot_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.kernel_release_, &other->_impl_.kernel_release_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.collection_id_, &other->_impl_.collection_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.actuator_enabled_) + + sizeof(Capabilities::_impl_.actuator_enabled_) + - PROTOBUF_FIELD_OFFSET(Capabilities, _impl_.simple_host_routing_)>( + reinterpret_cast(&_impl_.simple_host_routing_), + reinterpret_cast(&other->_impl_.simple_host_routing_)); +} + +::google::protobuf::Metadata Capabilities::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void ApplicationRecord::clear_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.received_at_ != nullptr) _impl_.received_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +void ApplicationRecord::clear_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attempted_at_ != nullptr) _impl_.attempted_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +void ApplicationRecord::clear_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.applied_at_ != nullptr) _impl_.applied_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +void ApplicationRecord::clear_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.verified_at_ != nullptr) _impl_.verified_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +void ApplicationRecord::clear_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.removed_at_ != nullptr) _impl_.removed_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); +} +ApplicationRecord::ApplicationRecord(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ApplicationRecord_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ApplicationRecord) +} +PROTOBUF_NDEBUG_INLINE ApplicationRecord::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::ApplicationRecord& from_msg) + : _has_bits_{from._has_bits_}, + error_(arena, from.error_), + installed_route_(arena, from.installed_route_), + installed_boot_id_(arena, from.installed_boot_id_) {} + +ApplicationRecord::ApplicationRecord( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ApplicationRecord& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ApplicationRecord_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ApplicationRecord* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.assignment_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.assignment_) + : nullptr; + _impl_.received_at_ = (CheckHasBit(cached_has_bits, 0x00000010U)) + ? Super_::CopyConstruct(arena, *from._impl_.received_at_) + : nullptr; + _impl_.attempted_at_ = (CheckHasBit(cached_has_bits, 0x00000020U)) + ? Super_::CopyConstruct(arena, *from._impl_.attempted_at_) + : nullptr; + _impl_.applied_at_ = (CheckHasBit(cached_has_bits, 0x00000040U)) + ? Super_::CopyConstruct(arena, *from._impl_.applied_at_) + : nullptr; + _impl_.verified_at_ = (CheckHasBit(cached_has_bits, 0x00000080U)) + ? Super_::CopyConstruct(arena, *from._impl_.verified_at_) + : nullptr; + _impl_.removed_at_ = (CheckHasBit(cached_has_bits, 0x00000100U)) + ? Super_::CopyConstruct(arena, *from._impl_.removed_at_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, desired_revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, desired_revision_), + offsetof(Impl_, expired_latched_) - + offsetof(Impl_, desired_revision_) + + sizeof(Impl_::expired_latched_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.ApplicationRecord) +} +PROTOBUF_NDEBUG_INLINE ApplicationRecord::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : error_(arena), + installed_route_(arena), + installed_boot_id_(arena) {} + +inline void ApplicationRecord::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, assignment_), + 0, + offsetof(Impl_, expired_latched_) - + offsetof(Impl_, assignment_) + + sizeof(Impl_::expired_latched_)); +} +ApplicationRecord::~ApplicationRecord() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ApplicationRecord) + SharedDtor(*this); +} +inline void ApplicationRecord::SharedDtor(MessageLite& self) { + ApplicationRecord& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.error_.Destroy(); + this_._impl_.installed_route_.Destroy(); + this_._impl_.installed_boot_id_.Destroy(); + delete this_._impl_.assignment_; + delete this_._impl_.received_at_; + delete this_._impl_.attempted_at_; + delete this_._impl_.applied_at_; + delete this_._impl_.verified_at_; + delete this_._impl_.removed_at_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ApplicationRecord_class_data_ = + ApplicationRecord::InternalGenerateClassData_(ApplicationRecord_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ApplicationRecord::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ApplicationRecord_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ApplicationRecord_class_data_.tc_table); + return ApplicationRecord_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ApplicationRecord::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ApplicationRecord_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ApplicationRecord_globals_)); + return ApplicationRecord_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ApplicationRecord::ParseTableT_ + ApplicationRecord::_table_ = + ApplicationRecord::InternalGenerateParseTable_(ApplicationRecord_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ApplicationRecord::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ApplicationRecord) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.error_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.installed_route_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.installed_boot_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.assignment_ != nullptr); + this_._impl_.assignment_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + ABSL_DCHECK(this_._impl_.received_at_ != nullptr); + this_._impl_.received_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(this_._impl_.attempted_at_ != nullptr); + this_._impl_.attempted_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(this_._impl_.applied_at_ != nullptr); + this_._impl_.applied_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(this_._impl_.verified_at_ != nullptr); + this_._impl_.verified_at_->Clear(); + } + } + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + ABSL_DCHECK(this_._impl_.removed_at_ != nullptr); + this_._impl_.removed_at_->Clear(); + } + if (BatchCheckHasBit(cached_has_bits, 0x00000e00U)) { + ::memset(&this_._impl_.desired_revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.expired_latched_) - + reinterpret_cast(&this_._impl_.desired_revision_)) + + sizeof(_impl_.expired_latched_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ApplicationRecord::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ApplicationRecord& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ApplicationRecord::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ApplicationRecord& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ApplicationRecord) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.Assignment assignment = 1 [json_name = "assignment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.assignment_, this_._impl_.assignment_->GetCachedSize(), target, + stream); + } + + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + if (this_._internal_desired_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_desired_revision(), target); + } + } + + // .xtcp_treatment.v1.ApplyStatus status = 3 [json_name = "status", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + if (this_._internal_status() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_status(), target); + } + } + + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.received_at_, this_._impl_.received_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.attempted_at_, this_._impl_.attempted_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.applied_at_, this_._impl_.applied_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, *this_._impl_.verified_at_, this_._impl_.verified_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.removed_at_, this_._impl_.removed_at_->GetCachedSize(), target, + stream); + } + + // string error = 9 [json_name = "error", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_error().empty()) { + const ::std::string& _s = this_._internal_error(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ApplicationRecord.error"); + target = stream->WriteStringMaybeAliased(9, _s, target); + } + } + + // bytes installed_route = 10 [json_name = "installedRoute", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_installed_route().empty()) { + const ::std::string& _s = this_._internal_installed_route(); + target = stream->WriteBytesMaybeAliased(10, _s, target); + } + } + + // string installed_boot_id = 11 [json_name = "installedBootId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_installed_boot_id().empty()) { + const ::std::string& _s = this_._internal_installed_boot_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.ApplicationRecord.installed_boot_id"); + target = stream->WriteStringMaybeAliased(11, _s, target); + } + } + + // bool expired_latched = 12 [json_name = "expiredLatched"]; + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (this_._internal_expired_latched() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 12, this_._internal_expired_latched(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ApplicationRecord) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ApplicationRecord::ByteSizeLong(const MessageLite& base) { + const ApplicationRecord& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ApplicationRecord::ByteSizeLong() const { + const ApplicationRecord& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ApplicationRecord) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // string error = 9 [json_name = "error", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_error().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_error()); + } + } + // bytes installed_route = 10 [json_name = "installedRoute", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_installed_route().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( + this_._internal_installed_route()); + } + } + // string installed_boot_id = 11 [json_name = "installedBootId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_installed_boot_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_installed_boot_id()); + } + } + // .xtcp_treatment.v1.Assignment assignment = 1 [json_name = "assignment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.assignment_); + } + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.received_at_); + } + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.attempted_at_); + } + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.applied_at_); + } + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.verified_at_); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000f00U)) { + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.removed_at_); + } + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + if (this_._internal_desired_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_desired_revision()); + } + } + // .xtcp_treatment.v1.ApplyStatus status = 3 [json_name = "status", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + if (this_._internal_status() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_status()); + } + } + // bool expired_latched = 12 [json_name = "expiredLatched"]; + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (this_._internal_expired_latched() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ApplicationRecord::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ApplicationRecord) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_error().empty()) { + _this->_internal_set_error(from._internal_error()); + } else { + if (_this->_impl_.error_.IsDefault()) { + _this->_internal_set_error(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_installed_route().empty()) { + _this->_internal_set_installed_route(from._internal_installed_route()); + } else { + if (_this->_impl_.installed_route_.IsDefault()) { + _this->_internal_set_installed_route(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_installed_boot_id().empty()) { + _this->_internal_set_installed_boot_id(from._internal_installed_boot_id()); + } else { + if (_this->_impl_.installed_boot_id_.IsDefault()) { + _this->_internal_set_installed_boot_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.assignment_ != nullptr); + if (_this->_impl_.assignment_ == nullptr) { + _this->_impl_.assignment_ = Super_::CopyConstruct(arena, *from._impl_.assignment_); + } else { + _this->_impl_.assignment_->MergeFrom(*from._impl_.assignment_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + ABSL_DCHECK(from._impl_.received_at_ != nullptr); + if (_this->_impl_.received_at_ == nullptr) { + _this->_impl_.received_at_ = Super_::CopyConstruct(arena, *from._impl_.received_at_); + } else { + _this->_impl_.received_at_->MergeFrom(*from._impl_.received_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(from._impl_.attempted_at_ != nullptr); + if (_this->_impl_.attempted_at_ == nullptr) { + _this->_impl_.attempted_at_ = Super_::CopyConstruct(arena, *from._impl_.attempted_at_); + } else { + _this->_impl_.attempted_at_->MergeFrom(*from._impl_.attempted_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(from._impl_.applied_at_ != nullptr); + if (_this->_impl_.applied_at_ == nullptr) { + _this->_impl_.applied_at_ = Super_::CopyConstruct(arena, *from._impl_.applied_at_); + } else { + _this->_impl_.applied_at_->MergeFrom(*from._impl_.applied_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(from._impl_.verified_at_ != nullptr); + if (_this->_impl_.verified_at_ == nullptr) { + _this->_impl_.verified_at_ = Super_::CopyConstruct(arena, *from._impl_.verified_at_); + } else { + _this->_impl_.verified_at_->MergeFrom(*from._impl_.verified_at_); + } + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000f00U)) { + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + ABSL_DCHECK(from._impl_.removed_at_ != nullptr); + if (_this->_impl_.removed_at_ == nullptr) { + _this->_impl_.removed_at_ = Super_::CopyConstruct(arena, *from._impl_.removed_at_); + } else { + _this->_impl_.removed_at_->MergeFrom(*from._impl_.removed_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + if (from._internal_desired_revision() != 0) { + _this->_impl_.desired_revision_ = from._impl_.desired_revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + if (from._internal_status() != 0) { + _this->_impl_.status_ = from._impl_.status_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (from._internal_expired_latched() != 0) { + _this->_impl_.expired_latched_ = from._impl_.expired_latched_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ApplicationRecord::CopyFrom(const ApplicationRecord& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ApplicationRecord) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ApplicationRecord::InternalSwap(ApplicationRecord* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.error_, &other->_impl_.error_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.installed_route_, &other->_impl_.installed_route_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.installed_boot_id_, &other->_impl_.installed_boot_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.expired_latched_) + + sizeof(ApplicationRecord::_impl_.expired_latched_) + - PROTOBUF_FIELD_OFFSET(ApplicationRecord, _impl_.assignment_)>( + reinterpret_cast(&_impl_.assignment_), + reinterpret_cast(&other->_impl_.assignment_)); +} + +::google::protobuf::Metadata ApplicationRecord::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void LocalState::clear_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.updated_at_ != nullptr) _impl_.updated_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +LocalState::LocalState(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, LocalState_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.LocalState) +} +PROTOBUF_NDEBUG_INLINE LocalState::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::LocalState& from_msg) + : _has_bits_{from._has_bits_}, + records_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::LocalState, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.records_)>() + , arena, from.records_ + } + , + suspension_reason_(arena, from.suspension_reason_) {} + +LocalState::LocalState( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const LocalState& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, LocalState_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + LocalState* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.desired_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.desired_) + : nullptr; + _impl_.updated_at_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.updated_at_) + : nullptr; + _impl_.locally_suspended_ = from._impl_.locally_suspended_; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.LocalState) +} +PROTOBUF_NDEBUG_INLINE LocalState::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : records_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::LocalState, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::LocalState, _impl_.records_)>() + } + , + suspension_reason_(arena) {} + +inline void LocalState::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, desired_), + 0, + offsetof(Impl_, locally_suspended_) - + offsetof(Impl_, desired_) + + sizeof(Impl_::locally_suspended_)); +} +LocalState::~LocalState() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.LocalState) + SharedDtor(*this); +} +inline void LocalState::SharedDtor(MessageLite& self) { + LocalState& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.suspension_reason_.Destroy(); + delete this_._impl_.desired_; + delete this_._impl_.updated_at_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull LocalState_class_data_ = + LocalState::InternalGenerateClassData_(LocalState_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +LocalState::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&LocalState_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(LocalState_class_data_.tc_table); + return LocalState_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +LocalState::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&LocalState_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&LocalState_globals_)); + return LocalState_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const LocalState::ParseTableT_ + LocalState::_table_ = + LocalState::InternalGenerateParseTable_(LocalState_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void LocalState::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.LocalState) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.records_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.suspension_reason_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.desired_ != nullptr); + this_._impl_.desired_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.updated_at_ != nullptr); + this_._impl_.updated_at_->Clear(); + } + } + this_._impl_.locally_suspended_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL LocalState::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const LocalState& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL LocalState::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const LocalState& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.LocalState) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.desired_, this_._impl_.desired_->GetCachedSize(), target, + stream); + } + + // bool locally_suspended = 2 [json_name = "locallySuspended"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_locally_suspended() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_locally_suspended(), target); + } + } + + // string suspension_reason = 3 [json_name = "suspensionReason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_suspension_reason().empty()) { + const ::std::string& _s = this_._internal_suspension_reason(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.LocalState.suspension_reason"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + } + + // repeated .xtcp_treatment.v1.ApplicationRecord records = 4 [json_name = "records", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_records_size()); + i < n; i++) { + const auto& repfield = this_._internal_records().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // .google.protobuf.Timestamp updated_at = 5 [json_name = "updatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.updated_at_, this_._impl_.updated_at_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.LocalState) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t LocalState::ByteSizeLong(const MessageLite& base) { + const LocalState& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t LocalState::ByteSizeLong() const { + const LocalState& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.LocalState) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + // repeated .xtcp_treatment.v1.ApplicationRecord records = 4 [json_name = "records", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_records_size(); + for (const auto& msg : this_._internal_records()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // string suspension_reason = 3 [json_name = "suspensionReason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_suspension_reason().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_suspension_reason()); + } + } + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.desired_); + } + // .google.protobuf.Timestamp updated_at = 5 [json_name = "updatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.updated_at_); + } + // bool locally_suspended = 2 [json_name = "locallySuspended"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_locally_suspended() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void LocalState::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.LocalState) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_records()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_records()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_suspension_reason().empty()) { + _this->_internal_set_suspension_reason(from._internal_suspension_reason()); + } else { + if (_this->_impl_.suspension_reason_.IsDefault()) { + _this->_internal_set_suspension_reason(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.desired_ != nullptr); + if (_this->_impl_.desired_ == nullptr) { + _this->_impl_.desired_ = Super_::CopyConstruct(arena, *from._impl_.desired_); + } else { + _this->_impl_.desired_->MergeFrom(*from._impl_.desired_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.updated_at_ != nullptr); + if (_this->_impl_.updated_at_ == nullptr) { + _this->_impl_.updated_at_ = Super_::CopyConstruct(arena, *from._impl_.updated_at_); + } else { + _this->_impl_.updated_at_->MergeFrom(*from._impl_.updated_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_locally_suspended() != 0) { + _this->_impl_.locally_suspended_ = from._impl_.locally_suspended_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void LocalState::CopyFrom(const LocalState& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.LocalState) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void LocalState::InternalSwap(LocalState* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.records_.InternalSwap(&other->_impl_.records_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.suspension_reason_, &other->_impl_.suspension_reason_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(LocalState, _impl_.locally_suspended_) + + sizeof(LocalState::_impl_.locally_suspended_) + - PROTOBUF_FIELD_OFFSET(LocalState, _impl_.desired_)>( + reinterpret_cast(&_impl_.desired_), + reinterpret_cast(&other->_impl_.desired_)); +} + +::google::protobuf::Metadata LocalState::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +HostEvidence::HostEvidence(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, HostEvidence_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.HostEvidence) +} +PROTOBUF_NDEBUG_INLINE HostEvidence::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::HostEvidence& from_msg) + : _has_bits_{from._has_bits_}, + agent_id_(arena, from.agent_id_) {} + +HostEvidence::HostEvidence( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const HostEvidence& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, HostEvidence_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + HostEvidence* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, sockets_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, sockets_), + offsetof(Impl_, collection_healthy_) - + offsetof(Impl_, sockets_) + + sizeof(Impl_::collection_healthy_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.HostEvidence) +} +PROTOBUF_NDEBUG_INLINE HostEvidence::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : agent_id_(arena) {} + +inline void HostEvidence::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, sockets_), + 0, + offsetof(Impl_, collection_healthy_) - + offsetof(Impl_, sockets_) + + sizeof(Impl_::collection_healthy_)); +} +HostEvidence::~HostEvidence() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.HostEvidence) + SharedDtor(*this); +} +inline void HostEvidence::SharedDtor(MessageLite& self) { + HostEvidence& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.agent_id_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull HostEvidence_class_data_ = + HostEvidence::InternalGenerateClassData_(HostEvidence_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +HostEvidence::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&HostEvidence_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(HostEvidence_class_data_.tc_table); + return HostEvidence_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +HostEvidence::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&HostEvidence_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&HostEvidence_globals_)); + return HostEvidence_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const HostEvidence::ParseTableT_ + HostEvidence::_table_ = + HostEvidence::InternalGenerateParseTable_(HostEvidence_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void HostEvidence::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.HostEvidence) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + if (BatchCheckHasBit(cached_has_bits, 0x000000feU)) { + ::memset(&this_._impl_.sockets_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.unbound_sockets_) - + reinterpret_cast(&this_._impl_.sockets_)) + + sizeof(_impl_.unbound_sockets_)); + } + this_._impl_.collection_healthy_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL HostEvidence::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const HostEvidence& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL HostEvidence::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const HostEvidence& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.HostEvidence) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.HostEvidence.agent_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint64 sockets = 2 [json_name = "sockets"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_sockets() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_sockets(), target); + } + } + + // uint64 bytes_acked = 3 [json_name = "bytesAcked"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (this_._internal_bytes_acked() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 3, this_._internal_bytes_acked(), target); + } + } + + // double goodput_bps = 4 [json_name = "goodputBps", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_goodput_bps()) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 4, this_._internal_goodput_bps(), target); + } + } + + // double retransmission_ratio = 5 [json_name = "retransmissionRatio", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_retransmission_ratio()) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 5, this_._internal_retransmission_ratio(), target); + } + } + + // double rtt_p95_ms = 6 [json_name = "rttP95Ms", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_rtt_p95_ms()) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 6, this_._internal_rtt_p95_ms(), target); + } + } + + // uint64 exposed_sockets = 7 [json_name = "exposedSockets"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (this_._internal_exposed_sockets() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 7, this_._internal_exposed_sockets(), target); + } + } + + // bool collection_healthy = 8 [json_name = "collectionHealthy"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (this_._internal_collection_healthy() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 8, this_._internal_collection_healthy(), target); + } + } + + // uint64 unbound_sockets = 9 [json_name = "unboundSockets"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (this_._internal_unbound_sockets() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 9, this_._internal_unbound_sockets(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.HostEvidence) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t HostEvidence::ByteSizeLong(const MessageLite& base) { + const HostEvidence& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t HostEvidence::ByteSizeLong() const { + const HostEvidence& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.HostEvidence) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + // uint64 sockets = 2 [json_name = "sockets"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (this_._internal_sockets() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_sockets()); + } + } + // uint64 bytes_acked = 3 [json_name = "bytesAcked"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (this_._internal_bytes_acked() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_bytes_acked()); + } + } + // double goodput_bps = 4 [json_name = "goodputBps", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_goodput_bps()) != 0) { + total_size += 9; + } + } + // double retransmission_ratio = 5 [json_name = "retransmissionRatio", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_retransmission_ratio()) != 0) { + total_size += 9; + } + } + // double rtt_p95_ms = 6 [json_name = "rttP95Ms", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_rtt_p95_ms()) != 0) { + total_size += 9; + } + } + // uint64 exposed_sockets = 7 [json_name = "exposedSockets"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (this_._internal_exposed_sockets() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_exposed_sockets()); + } + } + // uint64 unbound_sockets = 9 [json_name = "unboundSockets"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (this_._internal_unbound_sockets() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_unbound_sockets()); + } + } + } + { + // bool collection_healthy = 8 [json_name = "collectionHealthy"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (this_._internal_collection_healthy() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void HostEvidence::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.HostEvidence) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (from._internal_sockets() != 0) { + _this->_impl_.sockets_ = from._impl_.sockets_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (from._internal_bytes_acked() != 0) { + _this->_impl_.bytes_acked_ = from._impl_.bytes_acked_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (::absl::bit_cast<::uint64_t>(from._internal_goodput_bps()) != 0) { + _this->_impl_.goodput_bps_ = from._impl_.goodput_bps_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (::absl::bit_cast<::uint64_t>(from._internal_retransmission_ratio()) != 0) { + _this->_impl_.retransmission_ratio_ = from._impl_.retransmission_ratio_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (::absl::bit_cast<::uint64_t>(from._internal_rtt_p95_ms()) != 0) { + _this->_impl_.rtt_p95_ms_ = from._impl_.rtt_p95_ms_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (from._internal_exposed_sockets() != 0) { + _this->_impl_.exposed_sockets_ = from._impl_.exposed_sockets_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (from._internal_unbound_sockets() != 0) { + _this->_impl_.unbound_sockets_ = from._impl_.unbound_sockets_; + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (from._internal_collection_healthy() != 0) { + _this->_impl_.collection_healthy_ = from._impl_.collection_healthy_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void HostEvidence::CopyFrom(const HostEvidence& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.HostEvidence) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void HostEvidence::InternalSwap(HostEvidence* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.collection_healthy_) + + sizeof(HostEvidence::_impl_.collection_healthy_) + - PROTOBUF_FIELD_OFFSET(HostEvidence, _impl_.sockets_)>( + reinterpret_cast(&_impl_.sockets_), + reinterpret_cast(&other->_impl_.sockets_)); +} + +::google::protobuf::Metadata HostEvidence::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Evidence::clear_analyzed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.analyzed_at_ != nullptr) _impl_.analyzed_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +void Evidence::clear_window_start() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.window_start_ != nullptr) _impl_.window_start_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +void Evidence::clear_window_end() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.window_end_ != nullptr) _impl_.window_end_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +Evidence::Evidence(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Evidence_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.Evidence) +} +PROTOBUF_NDEBUG_INLINE Evidence::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::Evidence& from_msg) + : _has_bits_{from._has_bits_}, + hosts_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Evidence, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.hosts_)>() + , arena, from.hosts_ + } + , + id_(arena, from.id_), + query_version_(arena, from.query_version_), + enrichment_version_(arena, from.enrichment_version_), + artifact_sha256_(arena, from.artifact_sha256_) {} + +Evidence::Evidence( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Evidence& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Evidence_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Evidence* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.analyzed_at_ = (CheckHasBit(cached_has_bits, 0x00000020U)) + ? Super_::CopyConstruct(arena, *from._impl_.analyzed_at_) + : nullptr; + _impl_.window_start_ = (CheckHasBit(cached_has_bits, 0x00000040U)) + ? Super_::CopyConstruct(arena, *from._impl_.window_start_) + : nullptr; + _impl_.window_end_ = (CheckHasBit(cached_has_bits, 0x00000080U)) + ? Super_::CopyConstruct(arena, *from._impl_.window_end_) + : nullptr; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.Evidence) +} +PROTOBUF_NDEBUG_INLINE Evidence::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : hosts_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Evidence, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Evidence, _impl_.hosts_)>() + } + , + id_(arena), + query_version_(arena), + enrichment_version_(arena), + artifact_sha256_(arena) {} + +inline void Evidence::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, analyzed_at_), + 0, + offsetof(Impl_, window_end_) - + offsetof(Impl_, analyzed_at_) + + sizeof(Impl_::window_end_)); +} +Evidence::~Evidence() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.Evidence) + SharedDtor(*this); +} +inline void Evidence::SharedDtor(MessageLite& self) { + Evidence& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.id_.Destroy(); + this_._impl_.query_version_.Destroy(); + this_._impl_.enrichment_version_.Destroy(); + this_._impl_.artifact_sha256_.Destroy(); + delete this_._impl_.analyzed_at_; + delete this_._impl_.window_start_; + delete this_._impl_.window_end_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Evidence_class_data_ = + Evidence::InternalGenerateClassData_(Evidence_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Evidence::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Evidence_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Evidence_class_data_.tc_table); + return Evidence_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Evidence::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Evidence_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Evidence_globals_)); + return Evidence_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Evidence::ParseTableT_ + Evidence::_table_ = + Evidence::InternalGenerateParseTable_(Evidence_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Evidence::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.Evidence) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.hosts_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.query_version_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + this_._impl_.enrichment_version_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + this_._impl_.artifact_sha256_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(this_._impl_.analyzed_at_ != nullptr); + this_._impl_.analyzed_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(this_._impl_.window_start_ != nullptr); + this_._impl_.window_start_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(this_._impl_.window_end_ != nullptr); + this_._impl_.window_end_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Evidence::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Evidence& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Evidence::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Evidence& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.Evidence) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string id = 1 [json_name = "id", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_id().empty()) { + const ::std::string& _s = this_._internal_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Evidence.id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // .google.protobuf.Timestamp analyzed_at = 2 [json_name = "analyzedAt", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.analyzed_at_, this_._impl_.analyzed_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp window_start = 3 [json_name = "windowStart", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.window_start_, this_._impl_.window_start_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp window_end = 4 [json_name = "windowEnd", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.window_end_, this_._impl_.window_end_->GetCachedSize(), target, + stream); + } + + // string query_version = 5 [json_name = "queryVersion", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_query_version().empty()) { + const ::std::string& _s = this_._internal_query_version(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Evidence.query_version"); + target = stream->WriteStringMaybeAliased(5, _s, target); + } + } + + // string enrichment_version = 6 [json_name = "enrichmentVersion", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_enrichment_version().empty()) { + const ::std::string& _s = this_._internal_enrichment_version(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Evidence.enrichment_version"); + target = stream->WriteStringMaybeAliased(6, _s, target); + } + } + + // repeated .xtcp_treatment.v1.HostEvidence hosts = 7 [json_name = "hosts", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_hosts_size()); + i < n; i++) { + const auto& repfield = this_._internal_hosts().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // string artifact_sha256 = 8 [json_name = "artifactSha256", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_artifact_sha256().empty()) { + const ::std::string& _s = this_._internal_artifact_sha256(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Evidence.artifact_sha256"); + target = stream->WriteStringMaybeAliased(8, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.Evidence) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Evidence::ByteSizeLong(const MessageLite& base) { + const Evidence& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Evidence::ByteSizeLong() const { + const Evidence& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.Evidence) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // repeated .xtcp_treatment.v1.HostEvidence hosts = 7 [json_name = "hosts", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_hosts_size(); + for (const auto& msg : this_._internal_hosts()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // string id = 1 [json_name = "id", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_id()); + } + } + // string query_version = 5 [json_name = "queryVersion", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_query_version().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_query_version()); + } + } + // string enrichment_version = 6 [json_name = "enrichmentVersion", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_enrichment_version().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_enrichment_version()); + } + } + // string artifact_sha256 = 8 [json_name = "artifactSha256", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_artifact_sha256().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_artifact_sha256()); + } + } + // .google.protobuf.Timestamp analyzed_at = 2 [json_name = "analyzedAt", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.analyzed_at_); + } + // .google.protobuf.Timestamp window_start = 3 [json_name = "windowStart", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.window_start_); + } + // .google.protobuf.Timestamp window_end = 4 [json_name = "windowEnd", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.window_end_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Evidence::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.Evidence) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_hosts()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_hosts()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_id().empty()) { + _this->_internal_set_id(from._internal_id()); + } else { + if (_this->_impl_.id_.IsDefault()) { + _this->_internal_set_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_query_version().empty()) { + _this->_internal_set_query_version(from._internal_query_version()); + } else { + if (_this->_impl_.query_version_.IsDefault()) { + _this->_internal_set_query_version(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!from._internal_enrichment_version().empty()) { + _this->_internal_set_enrichment_version(from._internal_enrichment_version()); + } else { + if (_this->_impl_.enrichment_version_.IsDefault()) { + _this->_internal_set_enrichment_version(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!from._internal_artifact_sha256().empty()) { + _this->_internal_set_artifact_sha256(from._internal_artifact_sha256()); + } else { + if (_this->_impl_.artifact_sha256_.IsDefault()) { + _this->_internal_set_artifact_sha256(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(from._impl_.analyzed_at_ != nullptr); + if (_this->_impl_.analyzed_at_ == nullptr) { + _this->_impl_.analyzed_at_ = Super_::CopyConstruct(arena, *from._impl_.analyzed_at_); + } else { + _this->_impl_.analyzed_at_->MergeFrom(*from._impl_.analyzed_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(from._impl_.window_start_ != nullptr); + if (_this->_impl_.window_start_ == nullptr) { + _this->_impl_.window_start_ = Super_::CopyConstruct(arena, *from._impl_.window_start_); + } else { + _this->_impl_.window_start_->MergeFrom(*from._impl_.window_start_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(from._impl_.window_end_ != nullptr); + if (_this->_impl_.window_end_ == nullptr) { + _this->_impl_.window_end_ = Super_::CopyConstruct(arena, *from._impl_.window_end_); + } else { + _this->_impl_.window_end_->MergeFrom(*from._impl_.window_end_); + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Evidence::CopyFrom(const Evidence& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.Evidence) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Evidence::InternalSwap(Evidence* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.hosts_.InternalSwap(&other->_impl_.hosts_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.id_, &other->_impl_.id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.query_version_, &other->_impl_.query_version_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.enrichment_version_, &other->_impl_.enrichment_version_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.artifact_sha256_, &other->_impl_.artifact_sha256_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Evidence, _impl_.window_end_) + + sizeof(Evidence::_impl_.window_end_) + - PROTOBUF_FIELD_OFFSET(Evidence, _impl_.analyzed_at_)>( + reinterpret_cast(&_impl_.analyzed_at_), + reinterpret_cast(&other->_impl_.analyzed_at_)); +} + +::google::protobuf::Metadata Evidence::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void ExperimentPolicy::clear_minimum_observation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.minimum_observation_ != nullptr) _impl_.minimum_observation_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +void ExperimentPolicy::clear_maximum_phase() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.maximum_phase_ != nullptr) _impl_.maximum_phase_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +void ExperimentPolicy::clear_maximum_evidence_age() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.maximum_evidence_age_ != nullptr) _impl_.maximum_evidence_age_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +ExperimentPolicy::ExperimentPolicy(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ExperimentPolicy_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.ExperimentPolicy) +} +PROTOBUF_NDEBUG_INLINE ExperimentPolicy::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::ExperimentPolicy& from_msg) + : _has_bits_{from._has_bits_} {} + +ExperimentPolicy::ExperimentPolicy( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const ExperimentPolicy& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, ExperimentPolicy_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + ExperimentPolicy* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.minimum_observation_ = (CheckHasBit(cached_has_bits, 0x00000001U)) + ? Super_::CopyConstruct(arena, *from._impl_.minimum_observation_) + : nullptr; + _impl_.maximum_phase_ = (CheckHasBit(cached_has_bits, 0x00000002U)) + ? Super_::CopyConstruct(arena, *from._impl_.maximum_phase_) + : nullptr; + _impl_.maximum_evidence_age_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.maximum_evidence_age_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, minimum_sockets_per_host_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, minimum_sockets_per_host_), + offsetof(Impl_, minimum_treated_hosts_) - + offsetof(Impl_, minimum_sockets_per_host_) + + sizeof(Impl_::minimum_treated_hosts_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.ExperimentPolicy) +} +PROTOBUF_NDEBUG_INLINE ExperimentPolicy::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + {} + +inline void ExperimentPolicy::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, minimum_observation_), + 0, + offsetof(Impl_, minimum_treated_hosts_) - + offsetof(Impl_, minimum_observation_) + + sizeof(Impl_::minimum_treated_hosts_)); +} +ExperimentPolicy::~ExperimentPolicy() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.ExperimentPolicy) + SharedDtor(*this); +} +inline void ExperimentPolicy::SharedDtor(MessageLite& self) { + ExperimentPolicy& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.minimum_observation_; + delete this_._impl_.maximum_phase_; + delete this_._impl_.maximum_evidence_age_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull ExperimentPolicy_class_data_ = + ExperimentPolicy::InternalGenerateClassData_(ExperimentPolicy_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ExperimentPolicy::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ExperimentPolicy_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ExperimentPolicy_class_data_.tc_table); + return ExperimentPolicy_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +ExperimentPolicy::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ExperimentPolicy_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&ExperimentPolicy_globals_)); + return ExperimentPolicy_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ExperimentPolicy::ParseTableT_ + ExperimentPolicy::_table_ = + ExperimentPolicy::InternalGenerateParseTable_(ExperimentPolicy_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void ExperimentPolicy::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.ExperimentPolicy) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(this_._impl_.minimum_observation_ != nullptr); + this_._impl_.minimum_observation_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(this_._impl_.maximum_phase_ != nullptr); + this_._impl_.maximum_phase_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.maximum_evidence_age_ != nullptr); + this_._impl_.maximum_evidence_age_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x000000f8U)) { + ::memset(&this_._impl_.minimum_sockets_per_host_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.maximum_rtt_increase_) - + reinterpret_cast(&this_._impl_.minimum_sockets_per_host_)) + + sizeof(_impl_.maximum_rtt_increase_)); + } + this_._impl_.minimum_treated_hosts_ = 0u; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL ExperimentPolicy::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const ExperimentPolicy& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL ExperimentPolicy::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const ExperimentPolicy& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.ExperimentPolicy) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .google.protobuf.Duration minimum_observation = 1 [json_name = "minimumObservation", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.minimum_observation_, this_._impl_.minimum_observation_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Duration maximum_phase = 2 [json_name = "maximumPhase", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.maximum_phase_, this_._impl_.maximum_phase_->GetCachedSize(), target, + stream); + } + + // uint64 minimum_sockets_per_host = 3 [json_name = "minimumSocketsPerHost", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_minimum_sockets_per_host() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 3, this_._internal_minimum_sockets_per_host(), target); + } + } + + // uint64 minimum_bytes_per_host = 4 [json_name = "minimumBytesPerHost", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_minimum_bytes_per_host() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 4, this_._internal_minimum_bytes_per_host(), target); + } + } + + // uint32 minimum_treated_hosts = 5 [json_name = "minimumTreatedHosts", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (this_._internal_minimum_treated_hosts() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 5, this_._internal_minimum_treated_hosts(), target); + } + } + + // double minimum_improvement = 6 [json_name = "minimumImprovement", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_minimum_improvement()) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 6, this_._internal_minimum_improvement(), target); + } + } + + // double maximum_retransmission_increase = 7 [json_name = "maximumRetransmissionIncrease", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_maximum_retransmission_increase()) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 7, this_._internal_maximum_retransmission_increase(), target); + } + } + + // double maximum_rtt_increase = 8 [json_name = "maximumRttIncrease", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_maximum_rtt_increase()) != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 8, this_._internal_maximum_rtt_increase(), target); + } + } + + // .google.protobuf.Duration maximum_evidence_age = 9 [json_name = "maximumEvidenceAge", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 9, *this_._impl_.maximum_evidence_age_, this_._impl_.maximum_evidence_age_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.ExperimentPolicy) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t ExperimentPolicy::ByteSizeLong(const MessageLite& base) { + const ExperimentPolicy& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t ExperimentPolicy::ByteSizeLong() const { + const ExperimentPolicy& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.ExperimentPolicy) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // .google.protobuf.Duration minimum_observation = 1 [json_name = "minimumObservation", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.minimum_observation_); + } + // .google.protobuf.Duration maximum_phase = 2 [json_name = "maximumPhase", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.maximum_phase_); + } + // .google.protobuf.Duration maximum_evidence_age = 9 [json_name = "maximumEvidenceAge", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.maximum_evidence_age_); + } + // uint64 minimum_sockets_per_host = 3 [json_name = "minimumSocketsPerHost", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_minimum_sockets_per_host() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_minimum_sockets_per_host()); + } + } + // uint64 minimum_bytes_per_host = 4 [json_name = "minimumBytesPerHost", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_minimum_bytes_per_host() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_minimum_bytes_per_host()); + } + } + // double minimum_improvement = 6 [json_name = "minimumImprovement", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_minimum_improvement()) != 0) { + total_size += 9; + } + } + // double maximum_retransmission_increase = 7 [json_name = "maximumRetransmissionIncrease", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_maximum_retransmission_increase()) != 0) { + total_size += 9; + } + } + // double maximum_rtt_increase = 8 [json_name = "maximumRttIncrease", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (::absl::bit_cast<::uint64_t>(this_._internal_maximum_rtt_increase()) != 0) { + total_size += 9; + } + } + } + { + // uint32 minimum_treated_hosts = 5 [json_name = "minimumTreatedHosts", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (this_._internal_minimum_treated_hosts() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_minimum_treated_hosts()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void ExperimentPolicy::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.ExperimentPolicy) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + ABSL_DCHECK(from._impl_.minimum_observation_ != nullptr); + if (_this->_impl_.minimum_observation_ == nullptr) { + _this->_impl_.minimum_observation_ = Super_::CopyConstruct(arena, *from._impl_.minimum_observation_); + } else { + _this->_impl_.minimum_observation_->MergeFrom(*from._impl_.minimum_observation_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(from._impl_.maximum_phase_ != nullptr); + if (_this->_impl_.maximum_phase_ == nullptr) { + _this->_impl_.maximum_phase_ = Super_::CopyConstruct(arena, *from._impl_.maximum_phase_); + } else { + _this->_impl_.maximum_phase_->MergeFrom(*from._impl_.maximum_phase_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.maximum_evidence_age_ != nullptr); + if (_this->_impl_.maximum_evidence_age_ == nullptr) { + _this->_impl_.maximum_evidence_age_ = Super_::CopyConstruct(arena, *from._impl_.maximum_evidence_age_); + } else { + _this->_impl_.maximum_evidence_age_->MergeFrom(*from._impl_.maximum_evidence_age_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (from._internal_minimum_sockets_per_host() != 0) { + _this->_impl_.minimum_sockets_per_host_ = from._impl_.minimum_sockets_per_host_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_minimum_bytes_per_host() != 0) { + _this->_impl_.minimum_bytes_per_host_ = from._impl_.minimum_bytes_per_host_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (::absl::bit_cast<::uint64_t>(from._internal_minimum_improvement()) != 0) { + _this->_impl_.minimum_improvement_ = from._impl_.minimum_improvement_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (::absl::bit_cast<::uint64_t>(from._internal_maximum_retransmission_increase()) != 0) { + _this->_impl_.maximum_retransmission_increase_ = from._impl_.maximum_retransmission_increase_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (::absl::bit_cast<::uint64_t>(from._internal_maximum_rtt_increase()) != 0) { + _this->_impl_.maximum_rtt_increase_ = from._impl_.maximum_rtt_increase_; + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (from._internal_minimum_treated_hosts() != 0) { + _this->_impl_.minimum_treated_hosts_ = from._impl_.minimum_treated_hosts_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void ExperimentPolicy::CopyFrom(const ExperimentPolicy& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.ExperimentPolicy) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void ExperimentPolicy::InternalSwap(ExperimentPolicy* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_treated_hosts_) + + sizeof(ExperimentPolicy::_impl_.minimum_treated_hosts_) + - PROTOBUF_FIELD_OFFSET(ExperimentPolicy, _impl_.minimum_observation_)>( + reinterpret_cast(&_impl_.minimum_observation_), + reinterpret_cast(&other->_impl_.minimum_observation_)); +} + +::google::protobuf::Metadata ExperimentPolicy::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Phase::clear_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.issued_at_ != nullptr) _impl_.issued_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +void Phase::clear_observation_started_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.observation_started_at_ != nullptr) _impl_.observation_started_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +void Phase::clear_evaluated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evaluated_at_ != nullptr) _impl_.evaluated_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +Phase::Phase(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Phase_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.Phase) +} +PROTOBUF_NDEBUG_INLINE Phase::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::Phase& from_msg) + : _has_bits_{from._has_bits_}, + reviewer_(arena, from.reviewer_), + reason_(arena, from.reason_) {} + +Phase::Phase( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Phase& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Phase_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Phase* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.issued_at_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.issued_at_) + : nullptr; + _impl_.observation_started_at_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.observation_started_at_) + : nullptr; + _impl_.evaluated_at_ = (CheckHasBit(cached_has_bits, 0x00000010U)) + ? Super_::CopyConstruct(arena, *from._impl_.evaluated_at_) + : nullptr; + _impl_.evidence_ = (CheckHasBit(cached_has_bits, 0x00000020U)) + ? Super_::CopyConstruct(arena, *from._impl_.evidence_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, target_hosts_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, target_hosts_), + offsetof(Impl_, outcome_) - + offsetof(Impl_, target_hosts_) + + sizeof(Impl_::outcome_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.Phase) +} +PROTOBUF_NDEBUG_INLINE Phase::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : reviewer_(arena), + reason_(arena) {} + +inline void Phase::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, issued_at_), + 0, + offsetof(Impl_, outcome_) - + offsetof(Impl_, issued_at_) + + sizeof(Impl_::outcome_)); +} +Phase::~Phase() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.Phase) + SharedDtor(*this); +} +inline void Phase::SharedDtor(MessageLite& self) { + Phase& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.reviewer_.Destroy(); + this_._impl_.reason_.Destroy(); + delete this_._impl_.issued_at_; + delete this_._impl_.observation_started_at_; + delete this_._impl_.evaluated_at_; + delete this_._impl_.evidence_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Phase_class_data_ = + Phase::InternalGenerateClassData_(Phase_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Phase::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Phase_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Phase_class_data_.tc_table); + return Phase_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Phase::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Phase_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Phase_globals_)); + return Phase_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Phase::ParseTableT_ + Phase::_table_ = + Phase::InternalGenerateParseTable_(Phase_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Phase::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.Phase) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.reviewer_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.reason_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.issued_at_ != nullptr); + this_._impl_.issued_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.observation_started_at_ != nullptr); + this_._impl_.observation_started_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + ABSL_DCHECK(this_._impl_.evaluated_at_ != nullptr); + this_._impl_.evaluated_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(this_._impl_.evidence_ != nullptr); + this_._impl_.evidence_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x000000c0U)) { + ::memset(&this_._impl_.target_hosts_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.outcome_) - + reinterpret_cast(&this_._impl_.target_hosts_)) + + sizeof(_impl_.outcome_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Phase::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Phase& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Phase::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Phase& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.Phase) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // uint32 target_hosts = 1 [json_name = "targetHosts", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (this_._internal_target_hosts() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 1, this_._internal_target_hosts(), target); + } + } + + // .google.protobuf.Timestamp issued_at = 2 [json_name = "issuedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.issued_at_, this_._impl_.issued_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp observation_started_at = 3 [json_name = "observationStartedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.observation_started_at_, this_._impl_.observation_started_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp evaluated_at = 4 [json_name = "evaluatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.evaluated_at_, this_._impl_.evaluated_at_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.Evidence evidence = 5 [json_name = "evidence"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.evidence_, this_._impl_.evidence_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.Outcome outcome = 6 [json_name = "outcome", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (this_._internal_outcome() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 6, this_._internal_outcome(), target); + } + } + + // string reviewer = 7 [json_name = "reviewer", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_reviewer().empty()) { + const ::std::string& _s = this_._internal_reviewer(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Phase.reviewer"); + target = stream->WriteStringMaybeAliased(7, _s, target); + } + } + + // string reason = 8 [json_name = "reason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_reason().empty()) { + const ::std::string& _s = this_._internal_reason(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Phase.reason"); + target = stream->WriteStringMaybeAliased(8, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.Phase) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Phase::ByteSizeLong(const MessageLite& base) { + const Phase& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Phase::ByteSizeLong() const { + const Phase& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.Phase) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // string reviewer = 7 [json_name = "reviewer", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_reviewer().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_reviewer()); + } + } + // string reason = 8 [json_name = "reason", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_reason().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_reason()); + } + } + // .google.protobuf.Timestamp issued_at = 2 [json_name = "issuedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.issued_at_); + } + // .google.protobuf.Timestamp observation_started_at = 3 [json_name = "observationStartedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.observation_started_at_); + } + // .google.protobuf.Timestamp evaluated_at = 4 [json_name = "evaluatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.evaluated_at_); + } + // .xtcp_treatment.v1.Evidence evidence = 5 [json_name = "evidence"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.evidence_); + } + // uint32 target_hosts = 1 [json_name = "targetHosts", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (this_._internal_target_hosts() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_target_hosts()); + } + } + // .xtcp_treatment.v1.Outcome outcome = 6 [json_name = "outcome", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (this_._internal_outcome() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_outcome()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Phase::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.Phase) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_reviewer().empty()) { + _this->_internal_set_reviewer(from._internal_reviewer()); + } else { + if (_this->_impl_.reviewer_.IsDefault()) { + _this->_internal_set_reviewer(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_reason().empty()) { + _this->_internal_set_reason(from._internal_reason()); + } else { + if (_this->_impl_.reason_.IsDefault()) { + _this->_internal_set_reason(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.issued_at_ != nullptr); + if (_this->_impl_.issued_at_ == nullptr) { + _this->_impl_.issued_at_ = Super_::CopyConstruct(arena, *from._impl_.issued_at_); + } else { + _this->_impl_.issued_at_->MergeFrom(*from._impl_.issued_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.observation_started_at_ != nullptr); + if (_this->_impl_.observation_started_at_ == nullptr) { + _this->_impl_.observation_started_at_ = Super_::CopyConstruct(arena, *from._impl_.observation_started_at_); + } else { + _this->_impl_.observation_started_at_->MergeFrom(*from._impl_.observation_started_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + ABSL_DCHECK(from._impl_.evaluated_at_ != nullptr); + if (_this->_impl_.evaluated_at_ == nullptr) { + _this->_impl_.evaluated_at_ = Super_::CopyConstruct(arena, *from._impl_.evaluated_at_); + } else { + _this->_impl_.evaluated_at_->MergeFrom(*from._impl_.evaluated_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(from._impl_.evidence_ != nullptr); + if (_this->_impl_.evidence_ == nullptr) { + _this->_impl_.evidence_ = Super_::CopyConstruct(arena, *from._impl_.evidence_); + } else { + _this->_impl_.evidence_->MergeFrom(*from._impl_.evidence_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + if (from._internal_target_hosts() != 0) { + _this->_impl_.target_hosts_ = from._impl_.target_hosts_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + if (from._internal_outcome() != 0) { + _this->_impl_.outcome_ = from._impl_.outcome_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Phase::CopyFrom(const Phase& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.Phase) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Phase::InternalSwap(Phase* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.reviewer_, &other->_impl_.reviewer_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.reason_, &other->_impl_.reason_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Phase, _impl_.outcome_) + + sizeof(Phase::_impl_.outcome_) + - PROTOBUF_FIELD_OFFSET(Phase, _impl_.issued_at_)>( + reinterpret_cast(&_impl_.issued_at_), + reinterpret_cast(&other->_impl_.issued_at_)); +} + +::google::protobuf::Metadata Phase::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Experiment::clear_proposed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.proposed_at_ != nullptr) _impl_.proposed_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); +} +void Experiment::clear_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.updated_at_ != nullptr) _impl_.updated_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000400U); +} +Experiment::Experiment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Experiment_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment.v1.Experiment) +} +PROTOBUF_NDEBUG_INLINE Experiment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment::v1::Experiment& from_msg) + : _has_bits_{from._has_bits_}, + cohort_order_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Experiment, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.cohort_order_)>() + , arena, from.cohort_order_ + } + , + phases_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Experiment, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.phases_)>() + , arena, from.phases_ + } + , + id_(arena, from.id_), + location_(arena, from.location_), + hypothesis_(arena, from.hypothesis_) {} + +Experiment::Experiment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Experiment& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Experiment_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Experiment* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.treatment_ = (CheckHasBit(cached_has_bits, 0x00000020U)) + ? Super_::CopyConstruct(arena, *from._impl_.treatment_) + : nullptr; + _impl_.policy_ = (CheckHasBit(cached_has_bits, 0x00000040U)) + ? Super_::CopyConstruct(arena, *from._impl_.policy_) + : nullptr; + _impl_.baseline_ = (CheckHasBit(cached_has_bits, 0x00000080U)) + ? Super_::CopyConstruct(arena, *from._impl_.baseline_) + : nullptr; + _impl_.proposed_at_ = (CheckHasBit(cached_has_bits, 0x00000100U)) + ? Super_::CopyConstruct(arena, *from._impl_.proposed_at_) + : nullptr; + _impl_.latest_evidence_ = (CheckHasBit(cached_has_bits, 0x00000200U)) + ? Super_::CopyConstruct(arena, *from._impl_.latest_evidence_) + : nullptr; + _impl_.updated_at_ = (CheckHasBit(cached_has_bits, 0x00000400U)) + ? Super_::CopyConstruct(arena, *from._impl_.updated_at_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, revision_), + offsetof(Impl_, latest_outcome_) - + offsetof(Impl_, revision_) + + sizeof(Impl_::latest_outcome_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment.v1.Experiment) +} +PROTOBUF_NDEBUG_INLINE Experiment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : cohort_order_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Experiment, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.cohort_order_)>() + } + , + phases_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment::v1::Experiment, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment::v1::Experiment, _impl_.phases_)>() + } + , + id_(arena), + location_(arena), + hypothesis_(arena) {} + +inline void Experiment::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, treatment_), + 0, + offsetof(Impl_, latest_outcome_) - + offsetof(Impl_, treatment_) + + sizeof(Impl_::latest_outcome_)); +} +Experiment::~Experiment() { + // @@protoc_insertion_point(destructor:xtcp_treatment.v1.Experiment) + SharedDtor(*this); +} +inline void Experiment::SharedDtor(MessageLite& self) { + Experiment& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.id_.Destroy(); + this_._impl_.location_.Destroy(); + this_._impl_.hypothesis_.Destroy(); + delete this_._impl_.treatment_; + delete this_._impl_.policy_; + delete this_._impl_.baseline_; + delete this_._impl_.proposed_at_; + delete this_._impl_.latest_evidence_; + delete this_._impl_.updated_at_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Experiment_class_data_ = + Experiment::InternalGenerateClassData_(Experiment_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Experiment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Experiment_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Experiment_class_data_.tc_table); + return Experiment_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Experiment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Experiment_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Experiment_globals_)); + return Experiment_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Experiment::ParseTableT_ + Experiment::_table_ = + Experiment::InternalGenerateParseTable_(Experiment_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Experiment::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment.v1.Experiment) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.cohort_order_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + _impl_.phases_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + this_._impl_.location_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + this_._impl_.hypothesis_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(this_._impl_.treatment_ != nullptr); + this_._impl_.treatment_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(this_._impl_.policy_ != nullptr); + this_._impl_.policy_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(this_._impl_.baseline_ != nullptr); + this_._impl_.baseline_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000700U)) { + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + ABSL_DCHECK(this_._impl_.proposed_at_ != nullptr); + this_._impl_.proposed_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + ABSL_DCHECK(this_._impl_.latest_evidence_ != nullptr); + this_._impl_.latest_evidence_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + ABSL_DCHECK(this_._impl_.updated_at_ != nullptr); + this_._impl_.updated_at_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00003800U)) { + ::memset(&this_._impl_.revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.latest_outcome_) - + reinterpret_cast(&this_._impl_.revision_)) + + sizeof(_impl_.latest_outcome_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Experiment::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Experiment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Experiment::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Experiment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment.v1.Experiment) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string id = 1 [json_name = "id", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_id().empty()) { + const ::std::string& _s = this_._internal_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Experiment.id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string location = 2 [json_name = "location", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_location().empty()) { + const ::std::string& _s = this_._internal_location(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Experiment.location"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + // string hypothesis = 3 [json_name = "hypothesis", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_hypothesis().empty()) { + const ::std::string& _s = this_._internal_hypothesis(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Experiment.hypothesis"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + } + + // .xtcp_treatment.v1.Treatment treatment = 4 [json_name = "treatment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.treatment_, this_._impl_.treatment_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.ExperimentPolicy policy = 5 [json_name = "policy", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.policy_, this_._impl_.policy_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.Evidence baseline = 6 [json_name = "baseline", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.baseline_, this_._impl_.baseline_->GetCachedSize(), target, + stream); + } + + // repeated string cohort_order = 7 [json_name = "cohortOrder", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (int i = 0, n = this_._internal_cohort_order_size(); i < n; ++i) { + const auto& s = this_._internal_cohort_order().Get(i); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment.v1.Experiment.cohort_order"); + target = stream->WriteString(7, s, target); + } + } + + // repeated .xtcp_treatment.v1.Phase phases = 8 [json_name = "phases", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_phases_size()); + i < n; i++) { + const auto& repfield = this_._internal_phases().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // .xtcp_treatment.v1.ExperimentStatus status = 9 [json_name = "status", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00001000U)) { + if (this_._internal_status() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 9, this_._internal_status(), target); + } + } + + // uint64 revision = 10 [json_name = "revision"]; + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (this_._internal_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 10, this_._internal_revision(), target); + } + } + + // .google.protobuf.Timestamp proposed_at = 11 [json_name = "proposedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 11, *this_._impl_.proposed_at_, this_._impl_.proposed_at_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.Evidence latest_evidence = 12 [json_name = "latestEvidence"]; + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 12, *this_._impl_.latest_evidence_, this_._impl_.latest_evidence_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment.v1.Outcome latest_outcome = 13 [json_name = "latestOutcome", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00002000U)) { + if (this_._internal_latest_outcome() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 13, this_._internal_latest_outcome(), target); + } + } + + // .google.protobuf.Timestamp updated_at = 14 [json_name = "updatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 14, *this_._impl_.updated_at_, this_._impl_.updated_at_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment.v1.Experiment) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Experiment::ByteSizeLong(const MessageLite& base) { + const Experiment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Experiment::ByteSizeLong() const { + const Experiment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment.v1.Experiment) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // repeated string cohort_order = 7 [json_name = "cohortOrder", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_cohort_order().size()); + for (int i = 0, n = this_._internal_cohort_order().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_cohort_order().Get(i)); + } + } + // repeated .xtcp_treatment.v1.Phase phases = 8 [json_name = "phases", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1UL * this_._internal_phases_size(); + for (const auto& msg : this_._internal_phases()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // string id = 1 [json_name = "id", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_id()); + } + } + // string location = 2 [json_name = "location", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_location().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_location()); + } + } + // string hypothesis = 3 [json_name = "hypothesis", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_hypothesis().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_hypothesis()); + } + } + // .xtcp_treatment.v1.Treatment treatment = 4 [json_name = "treatment", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.treatment_); + } + // .xtcp_treatment.v1.ExperimentPolicy policy = 5 [json_name = "policy", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.policy_); + } + // .xtcp_treatment.v1.Evidence baseline = 6 [json_name = "baseline", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.baseline_); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00003f00U)) { + // .google.protobuf.Timestamp proposed_at = 11 [json_name = "proposedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.proposed_at_); + } + // .xtcp_treatment.v1.Evidence latest_evidence = 12 [json_name = "latestEvidence"]; + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.latest_evidence_); + } + // .google.protobuf.Timestamp updated_at = 14 [json_name = "updatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.updated_at_); + } + // uint64 revision = 10 [json_name = "revision"]; + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (this_._internal_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_revision()); + } + } + // .xtcp_treatment.v1.ExperimentStatus status = 9 [json_name = "status", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00001000U)) { + if (this_._internal_status() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_status()); + } + } + // .xtcp_treatment.v1.Outcome latest_outcome = 13 [json_name = "latestOutcome", (.buf.validate.field) = { + if (CheckHasBit(cached_has_bits, 0x00002000U)) { + if (this_._internal_latest_outcome() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_latest_outcome()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Experiment::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment.v1.Experiment) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_cohort_order()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_cohort_order()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + _this->_internal_mutable_phases()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_phases()); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_id().empty()) { + _this->_internal_set_id(from._internal_id()); + } else { + if (_this->_impl_.id_.IsDefault()) { + _this->_internal_set_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!from._internal_location().empty()) { + _this->_internal_set_location(from._internal_location()); + } else { + if (_this->_impl_.location_.IsDefault()) { + _this->_internal_set_location(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!from._internal_hypothesis().empty()) { + _this->_internal_set_hypothesis(from._internal_hypothesis()); + } else { + if (_this->_impl_.hypothesis_.IsDefault()) { + _this->_internal_set_hypothesis(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(from._impl_.treatment_ != nullptr); + if (_this->_impl_.treatment_ == nullptr) { + _this->_impl_.treatment_ = Super_::CopyConstruct(arena, *from._impl_.treatment_); + } else { + _this->_impl_.treatment_->MergeFrom(*from._impl_.treatment_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(from._impl_.policy_ != nullptr); + if (_this->_impl_.policy_ == nullptr) { + _this->_impl_.policy_ = Super_::CopyConstruct(arena, *from._impl_.policy_); + } else { + _this->_impl_.policy_->MergeFrom(*from._impl_.policy_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(from._impl_.baseline_ != nullptr); + if (_this->_impl_.baseline_ == nullptr) { + _this->_impl_.baseline_ = Super_::CopyConstruct(arena, *from._impl_.baseline_); + } else { + _this->_impl_.baseline_->MergeFrom(*from._impl_.baseline_); + } + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00003f00U)) { + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + ABSL_DCHECK(from._impl_.proposed_at_ != nullptr); + if (_this->_impl_.proposed_at_ == nullptr) { + _this->_impl_.proposed_at_ = Super_::CopyConstruct(arena, *from._impl_.proposed_at_); + } else { + _this->_impl_.proposed_at_->MergeFrom(*from._impl_.proposed_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + ABSL_DCHECK(from._impl_.latest_evidence_ != nullptr); + if (_this->_impl_.latest_evidence_ == nullptr) { + _this->_impl_.latest_evidence_ = Super_::CopyConstruct(arena, *from._impl_.latest_evidence_); + } else { + _this->_impl_.latest_evidence_->MergeFrom(*from._impl_.latest_evidence_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + ABSL_DCHECK(from._impl_.updated_at_ != nullptr); + if (_this->_impl_.updated_at_ == nullptr) { + _this->_impl_.updated_at_ = Super_::CopyConstruct(arena, *from._impl_.updated_at_); + } else { + _this->_impl_.updated_at_->MergeFrom(*from._impl_.updated_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (from._internal_revision() != 0) { + _this->_impl_.revision_ = from._impl_.revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00001000U)) { + if (from._internal_status() != 0) { + _this->_impl_.status_ = from._impl_.status_; + } + } + if (CheckHasBit(cached_has_bits, 0x00002000U)) { + if (from._internal_latest_outcome() != 0) { + _this->_impl_.latest_outcome_ = from._impl_.latest_outcome_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Experiment::CopyFrom(const Experiment& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment.v1.Experiment) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Experiment::InternalSwap(Experiment* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.cohort_order_.InternalSwap(&other->_impl_.cohort_order_); + _impl_.phases_.InternalSwap(&other->_impl_.phases_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.id_, &other->_impl_.id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.location_, &other->_impl_.location_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.hypothesis_, &other->_impl_.hypothesis_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Experiment, _impl_.latest_outcome_) + + sizeof(Experiment::_impl_.latest_outcome_) + - PROTOBUF_FIELD_OFFSET(Experiment, _impl_.treatment_)>( + reinterpret_cast(&_impl_.treatment_), + reinterpret_cast(&other->_impl_.treatment_)); +} + +::google::protobuf::Metadata Experiment::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi::ExtensionIdentifier< + ::google::protobuf::MethodOptions, ::_pbi::EnumTypeTraits< ::xtcp_treatment::v1::Role>, 14, false> + role(kRoleFieldNumber, static_cast< ::xtcp_treatment::v1::Role >(0)); +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ [[maybe_unused]] = + (::_pbi::AddDescriptors(&descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto), + ::_pbi::ExtensionSet::RegisterEnumExtension( + &::google::protobuf::MethodOptions::default_instance(), 51002, 14, + false, false, ::xtcp_treatment::v1::Role_internal_data_), + ::std::false_type{}); +#include "google/protobuf/port_undef.inc" diff --git a/gen/cpp/xtcp_treatment/v1/treatment.pb.h b/gen/cpp/xtcp_treatment/v1/treatment.pb.h new file mode 100644 index 000000000..927a8842f --- /dev/null +++ b/gen/cpp/xtcp_treatment/v1/treatment.pb.h @@ -0,0 +1,9696 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment/v1/treatment.proto +// Protobuf C++ Version: 7.36.2 + +#ifndef xtcp_5ftreatment_2fv1_2ftreatment_2eproto_2epb_2eh +#define xtcp_5ftreatment_2fv1_2ftreatment_2eproto_2epb_2eh + +#include +#include +#include +#include + +// clang-format off +#include "google/protobuf/runtime_version.h" +#if PROTOBUF_VERSION != 7036002 +#error "Protobuf C++ gencode is built with an incompatible version of" +#error "Protobuf C++ headers/runtime. See" +#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" +#endif +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/generated_enum_reflection.h" +#include "google/protobuf/unknown_field_set.h" +#include "buf/validate/validate.pb.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/duration.pb.h" +#include "google/protobuf/timestamp.pb.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_xtcp_5ftreatment_2fv1_2ftreatment_2eproto + +// Internal implementation detail -- do not use these members. +struct TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto { + static const ::uint32_t offsets[]; +}; +extern "C" { +extern const ::google::protobuf::internal::DescriptorTable descriptor_table_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +} // extern "C" +namespace xtcp_treatment { +namespace v1 { +enum ApplyStatus : int; +extern const uint32_t ApplyStatus_internal_data_[]; +enum AssignmentMode : int; +extern const uint32_t AssignmentMode_internal_data_[]; +enum ExperimentStatus : int; +extern const uint32_t ExperimentStatus_internal_data_[]; +enum Outcome : int; +extern const uint32_t Outcome_internal_data_[]; +enum Role : int; +extern const uint32_t Role_internal_data_[]; +class ApplicationRecord; +struct ApplicationRecordGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ApplicationRecordGlobalsTypeInternal ApplicationRecord_globals_; +extern const ::google::protobuf::internal::ClassDataFull ApplicationRecord_class_data_; +#else +extern const ApplicationRecordGlobalsTypeInternal ApplicationRecord_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Assignment; +struct AssignmentGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern AssignmentGlobalsTypeInternal Assignment_globals_; +extern const ::google::protobuf::internal::ClassDataFull Assignment_class_data_; +#else +extern const AssignmentGlobalsTypeInternal Assignment_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Capabilities; +struct CapabilitiesGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern CapabilitiesGlobalsTypeInternal Capabilities_globals_; +extern const ::google::protobuf::internal::ClassDataFull Capabilities_class_data_; +#else +extern const CapabilitiesGlobalsTypeInternal Capabilities_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class DesiredState; +struct DesiredStateGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern DesiredStateGlobalsTypeInternal DesiredState_globals_; +extern const ::google::protobuf::internal::ClassDataFull DesiredState_class_data_; +#else +extern const DesiredStateGlobalsTypeInternal DesiredState_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Evidence; +struct EvidenceGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern EvidenceGlobalsTypeInternal Evidence_globals_; +extern const ::google::protobuf::internal::ClassDataFull Evidence_class_data_; +#else +extern const EvidenceGlobalsTypeInternal Evidence_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Experiment; +struct ExperimentGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ExperimentGlobalsTypeInternal Experiment_globals_; +extern const ::google::protobuf::internal::ClassDataFull Experiment_class_data_; +#else +extern const ExperimentGlobalsTypeInternal Experiment_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class ExperimentPolicy; +struct ExperimentPolicyGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern ExperimentPolicyGlobalsTypeInternal ExperimentPolicy_globals_; +extern const ::google::protobuf::internal::ClassDataFull ExperimentPolicy_class_data_; +#else +extern const ExperimentPolicyGlobalsTypeInternal ExperimentPolicy_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class HostEvidence; +struct HostEvidenceGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern HostEvidenceGlobalsTypeInternal HostEvidence_globals_; +extern const ::google::protobuf::internal::ClassDataFull HostEvidence_class_data_; +#else +extern const HostEvidenceGlobalsTypeInternal HostEvidence_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class LocalState; +struct LocalStateGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern LocalStateGlobalsTypeInternal LocalState_globals_; +extern const ::google::protobuf::internal::ClassDataFull LocalState_class_data_; +#else +extern const LocalStateGlobalsTypeInternal LocalState_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Phase; +struct PhaseGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern PhaseGlobalsTypeInternal Phase_globals_; +extern const ::google::protobuf::internal::ClassDataFull Phase_class_data_; +#else +extern const PhaseGlobalsTypeInternal Phase_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class TCPSettings; +struct TCPSettingsGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern TCPSettingsGlobalsTypeInternal TCPSettings_globals_; +extern const ::google::protobuf::internal::ClassDataFull TCPSettings_class_data_; +#else +extern const TCPSettingsGlobalsTypeInternal TCPSettings_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Treatment; +struct TreatmentGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern TreatmentGlobalsTypeInternal Treatment_globals_; +extern const ::google::protobuf::internal::ClassDataFull Treatment_class_data_; +#else +extern const TreatmentGlobalsTypeInternal Treatment_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +} // namespace v1 +} // namespace xtcp_treatment +namespace google { +namespace protobuf { +template <> +internal::EnumTraitsT<::xtcp_treatment::v1::ApplyStatus_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment::v1::ApplyStatus>; +template <> +internal::EnumTraitsT<::xtcp_treatment::v1::AssignmentMode_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment::v1::AssignmentMode>; +template <> +internal::EnumTraitsT<::xtcp_treatment::v1::ExperimentStatus_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment::v1::ExperimentStatus>; +template <> +internal::EnumTraitsT<::xtcp_treatment::v1::Outcome_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment::v1::Outcome>; +template <> +internal::EnumTraitsT<::xtcp_treatment::v1::Role_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment::v1::Role>; +} // namespace protobuf +} // namespace google + +namespace xtcp_treatment { +namespace v1 { +enum Role : int { + ROLE_UNSPECIFIED = 0, + ROLE_AGENT = 1, + ROLE_OPERATOR = 2, + Role_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + Role_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t Role_internal_data_[]; +inline constexpr Role Role_MIN = + static_cast(0); +inline constexpr Role Role_MAX = + static_cast(2); +[[nodiscard]] inline bool Role_IsValid(int value) { + return 0 <= value && value <= 2; +} +inline constexpr int Role_ARRAYSIZE = 2 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +Role_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(Role) { + return Role_descriptor(); +} +template +[[nodiscard]] const ::std::string& Role_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to Role_Name()."); + return Role_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& Role_Name(Role value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool Role_Parse( + ::absl::string_view name, Role* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(Role_descriptor(), name, + value); +} +enum AssignmentMode : int { + ASSIGNMENT_MODE_UNSPECIFIED = 0, + ASSIGNMENT_MODE_TRIAL = 1, + ASSIGNMENT_MODE_STABLE = 2, + ASSIGNMENT_MODE_SUSPENDED = 3, + ASSIGNMENT_MODE_RETIRED = 4, + AssignmentMode_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + AssignmentMode_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t AssignmentMode_internal_data_[]; +inline constexpr AssignmentMode AssignmentMode_MIN = + static_cast(0); +inline constexpr AssignmentMode AssignmentMode_MAX = + static_cast(4); +[[nodiscard]] inline bool AssignmentMode_IsValid(int value) { + return 0 <= value && value <= 4; +} +inline constexpr int AssignmentMode_ARRAYSIZE = 4 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +AssignmentMode_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(AssignmentMode) { + return AssignmentMode_descriptor(); +} +template +[[nodiscard]] const ::std::string& AssignmentMode_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to AssignmentMode_Name()."); + return AssignmentMode_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& AssignmentMode_Name(AssignmentMode value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool AssignmentMode_Parse( + ::absl::string_view name, AssignmentMode* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(AssignmentMode_descriptor(), name, + value); +} +enum ApplyStatus : int { + APPLY_STATUS_UNSPECIFIED = 0, + APPLY_STATUS_PENDING = 1, + APPLY_STATUS_VERIFIED = 2, + APPLY_STATUS_REMOVED = 3, + APPLY_STATUS_EXPIRED = 4, + APPLY_STATUS_FAILED = 5, + ApplyStatus_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + ApplyStatus_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t ApplyStatus_internal_data_[]; +inline constexpr ApplyStatus ApplyStatus_MIN = + static_cast(0); +inline constexpr ApplyStatus ApplyStatus_MAX = + static_cast(5); +[[nodiscard]] inline bool ApplyStatus_IsValid(int value) { + return 0 <= value && value <= 5; +} +inline constexpr int ApplyStatus_ARRAYSIZE = 5 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ApplyStatus_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(ApplyStatus) { + return ApplyStatus_descriptor(); +} +template +[[nodiscard]] const ::std::string& ApplyStatus_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to ApplyStatus_Name()."); + return ApplyStatus_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& ApplyStatus_Name(ApplyStatus value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool ApplyStatus_Parse( + ::absl::string_view name, ApplyStatus* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(ApplyStatus_descriptor(), name, + value); +} +enum Outcome : int { + OUTCOME_UNSPECIFIED = 0, + OUTCOME_BASELINE = 1, + OUTCOME_AWAITING_APPLICATION = 2, + OUTCOME_AWAITING_EXPOSURE = 3, + OUTCOME_INSUFFICIENT_DURATION = 4, + OUTCOME_INSUFFICIENT_DATA = 5, + OUTCOME_INSUFFICIENT_CONTROLS = 6, + OUTCOME_STALE = 7, + OUTCOME_UNAVAILABLE = 8, + OUTCOME_INCONCLUSIVE = 9, + OUTCOME_SAFETY_ONLY = 10, + OUTCOME_FINAL_SAFETY = 11, + OUTCOME_BENEFICIAL = 12, + OUTCOME_HARMFUL = 13, + OUTCOME_EXPIRED = 14, + OUTCOME_STABLE_OBSERVED = 15, + OUTCOME_STABLE_EVIDENCE_INCOMPLETE = 16, + OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED = 17, + OUTCOME_OBSERVING = 18, + Outcome_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + Outcome_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t Outcome_internal_data_[]; +inline constexpr Outcome Outcome_MIN = + static_cast(0); +inline constexpr Outcome Outcome_MAX = + static_cast(18); +[[nodiscard]] inline bool Outcome_IsValid(int value) { + return 0 <= value && value <= 18; +} +inline constexpr int Outcome_ARRAYSIZE = 18 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +Outcome_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(Outcome) { + return Outcome_descriptor(); +} +template +[[nodiscard]] const ::std::string& Outcome_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to Outcome_Name()."); + return Outcome_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& Outcome_Name(Outcome value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool Outcome_Parse( + ::absl::string_view name, Outcome* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(Outcome_descriptor(), name, + value); +} +enum ExperimentStatus : int { + EXPERIMENT_STATUS_UNSPECIFIED = 0, + EXPERIMENT_STATUS_PROPOSED = 1, + EXPERIMENT_STATUS_RUNNING = 2, + EXPERIMENT_STATUS_PAUSED = 3, + EXPERIMENT_STATUS_SUSPENDED = 4, + EXPERIMENT_STATUS_COMPLETE = 5, + EXPERIMENT_STATUS_RETIRED = 6, + EXPERIMENT_STATUS_ROLLED_BACK = 7, + ExperimentStatus_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + ExperimentStatus_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t ExperimentStatus_internal_data_[]; +inline constexpr ExperimentStatus ExperimentStatus_MIN = + static_cast(0); +inline constexpr ExperimentStatus ExperimentStatus_MAX = + static_cast(7); +[[nodiscard]] inline bool ExperimentStatus_IsValid(int value) { + return 0 <= value && value <= 7; +} +inline constexpr int ExperimentStatus_ARRAYSIZE = 7 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ExperimentStatus_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(ExperimentStatus) { + return ExperimentStatus_descriptor(); +} +template +[[nodiscard]] const ::std::string& ExperimentStatus_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to ExperimentStatus_Name()."); + return ExperimentStatus_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& ExperimentStatus_Name(ExperimentStatus value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool ExperimentStatus_Parse( + ::absl::string_view name, ExperimentStatus* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(ExperimentStatus_descriptor(), name, + value); +} +using ::google::protobuf::internal::generated_enum::AbslParseFlag; +using ::google::protobuf::internal::generated_enum::AbslUnparseFlag; + +// =================================================================== + + +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED TCPSettings final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.TCPSettings) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline TCPSettings() : TCPSettings(nullptr) {} + ~TCPSettings() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TCPSettings* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TCPSettings)); + } +#endif + + template + explicit constexpr TCPSettings(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline TCPSettings(const TCPSettings& from) : TCPSettings(nullptr, from) {} + inline TCPSettings(TCPSettings&& from) noexcept : TCPSettings(nullptr, ::std::move(from)) {} + inline TCPSettings& operator=(const TCPSettings& from) { + CopyFrom(from); + return *this; + } + inline TCPSettings& operator=(TCPSettings&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const TCPSettings& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&TCPSettings_globals_); + } + static constexpr int kIndexInFileMessages = 0; + friend void swap(TCPSettings& a, TCPSettings& b) { a.Swap(&b); } + inline void Swap(TCPSettings* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TCPSettings* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] TCPSettings* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const TCPSettings& from); + using Super_::MergeFrom; + void MergeFrom(const TCPSettings& from) { TCPSettings::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TCPSettings* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.TCPSettings"; } + + explicit TCPSettings(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TCPSettings(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TCPSettings& from); + TCPSettings( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TCPSettings&& from) noexcept + : TCPSettings(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kCongestionControlFieldNumber = 1, + kRtoMinMsFieldNumber = 3, + kInitialCongestionWindowFieldNumber = 4, + kInitialReceiveWindowFieldNumber = 5, + kCongestionLockFieldNumber = 2, + kQuickAckFieldNumber = 6, + kEcnFieldNumber = 7, + }; + // optional string congestion_control = 1 [json_name = "congestionControl", (.buf.validate.field) = { + [[nodiscard]] bool has_congestion_control() const; + void clear_congestion_control() ; + [[nodiscard]] const ::std::string& congestion_control() const; + template + void set_congestion_control(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_congestion_control(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_congestion_control(); + void set_allocated_congestion_control(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_congestion_control() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_congestion_control(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_congestion_control(); + + public: + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs", (.buf.validate.field) = { + [[nodiscard]] bool has_rto_min_ms() const; + void clear_rto_min_ms() ; + [[nodiscard]] ::uint32_t rto_min_ms() const; + void set_rto_min_ms(::uint32_t value); + + private: + ::uint32_t _internal_rto_min_ms() const; + void _internal_set_rto_min_ms(::uint32_t value); + + public: + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow", (.buf.validate.field) = { + [[nodiscard]] bool has_initial_congestion_window() const; + void clear_initial_congestion_window() ; + [[nodiscard]] ::uint32_t initial_congestion_window() const; + void set_initial_congestion_window(::uint32_t value); + + private: + ::uint32_t _internal_initial_congestion_window() const; + void _internal_set_initial_congestion_window(::uint32_t value); + + public: + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow", (.buf.validate.field) = { + [[nodiscard]] bool has_initial_receive_window() const; + void clear_initial_receive_window() ; + [[nodiscard]] ::uint32_t initial_receive_window() const; + void set_initial_receive_window(::uint32_t value); + + private: + ::uint32_t _internal_initial_receive_window() const; + void _internal_set_initial_receive_window(::uint32_t value); + + public: + // bool congestion_lock = 2 [json_name = "congestionLock"]; + void clear_congestion_lock() ; + [[nodiscard]] bool congestion_lock() const; + void set_congestion_lock(bool value); + + private: + bool _internal_congestion_lock() const; + void _internal_set_congestion_lock(bool value); + + public: + // optional bool quick_ack = 6 [json_name = "quickAck"]; + [[nodiscard]] bool has_quick_ack() const; + void clear_quick_ack() ; + [[nodiscard]] bool quick_ack() const; + void set_quick_ack(bool value); + + private: + bool _internal_quick_ack() const; + void _internal_set_quick_ack(bool value); + + public: + // optional bool ecn = 7 [json_name = "ecn"]; + [[nodiscard]] bool has_ecn() const; + void clear_ecn() ; + [[nodiscard]] bool ecn() const; + void set_ecn(bool value); + + private: + bool _internal_ecn() const; + void _internal_set_ecn(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.TCPSettings) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 7, + 0, 56, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TCPSettings& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr congestion_control_; + ::uint32_t rto_min_ms_; + ::uint32_t initial_congestion_window_; + ::uint32_t initial_receive_window_; + bool congestion_lock_; + bool quick_ack_; + bool ecn_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED HostEvidence final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.HostEvidence) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline HostEvidence() : HostEvidence(nullptr) {} + ~HostEvidence() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(HostEvidence* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(HostEvidence)); + } +#endif + + template + explicit constexpr HostEvidence(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline HostEvidence(const HostEvidence& from) : HostEvidence(nullptr, from) {} + inline HostEvidence(HostEvidence&& from) noexcept : HostEvidence(nullptr, ::std::move(from)) {} + inline HostEvidence& operator=(const HostEvidence& from) { + CopyFrom(from); + return *this; + } + inline HostEvidence& operator=(HostEvidence&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const HostEvidence& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&HostEvidence_globals_); + } + static constexpr int kIndexInFileMessages = 7; + friend void swap(HostEvidence& a, HostEvidence& b) { a.Swap(&b); } + inline void Swap(HostEvidence* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(HostEvidence* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] HostEvidence* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const HostEvidence& from); + using Super_::MergeFrom; + void MergeFrom(const HostEvidence& from) { HostEvidence::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(HostEvidence* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.HostEvidence"; } + + explicit HostEvidence(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + HostEvidence(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const HostEvidence& from); + HostEvidence( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, HostEvidence&& from) noexcept + : HostEvidence(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kAgentIdFieldNumber = 1, + kSocketsFieldNumber = 2, + kBytesAckedFieldNumber = 3, + kGoodputBpsFieldNumber = 4, + kRetransmissionRatioFieldNumber = 5, + kRttP95MsFieldNumber = 6, + kExposedSocketsFieldNumber = 7, + kUnboundSocketsFieldNumber = 9, + kCollectionHealthyFieldNumber = 8, + }; + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // uint64 sockets = 2 [json_name = "sockets"]; + void clear_sockets() ; + [[nodiscard]] ::uint64_t sockets() const; + void set_sockets(::uint64_t value); + + private: + ::uint64_t _internal_sockets() const; + void _internal_set_sockets(::uint64_t value); + + public: + // uint64 bytes_acked = 3 [json_name = "bytesAcked"]; + void clear_bytes_acked() ; + [[nodiscard]] ::uint64_t bytes_acked() const; + void set_bytes_acked(::uint64_t value); + + private: + ::uint64_t _internal_bytes_acked() const; + void _internal_set_bytes_acked(::uint64_t value); + + public: + // double goodput_bps = 4 [json_name = "goodputBps", (.buf.validate.field) = { + void clear_goodput_bps() ; + [[nodiscard]] double goodput_bps() const; + void set_goodput_bps(double value); + + private: + double _internal_goodput_bps() const; + void _internal_set_goodput_bps(double value); + + public: + // double retransmission_ratio = 5 [json_name = "retransmissionRatio", (.buf.validate.field) = { + void clear_retransmission_ratio() ; + [[nodiscard]] double retransmission_ratio() const; + void set_retransmission_ratio(double value); + + private: + double _internal_retransmission_ratio() const; + void _internal_set_retransmission_ratio(double value); + + public: + // double rtt_p95_ms = 6 [json_name = "rttP95Ms", (.buf.validate.field) = { + void clear_rtt_p95_ms() ; + [[nodiscard]] double rtt_p95_ms() const; + void set_rtt_p95_ms(double value); + + private: + double _internal_rtt_p95_ms() const; + void _internal_set_rtt_p95_ms(double value); + + public: + // uint64 exposed_sockets = 7 [json_name = "exposedSockets"]; + void clear_exposed_sockets() ; + [[nodiscard]] ::uint64_t exposed_sockets() const; + void set_exposed_sockets(::uint64_t value); + + private: + ::uint64_t _internal_exposed_sockets() const; + void _internal_set_exposed_sockets(::uint64_t value); + + public: + // uint64 unbound_sockets = 9 [json_name = "unboundSockets"]; + void clear_unbound_sockets() ; + [[nodiscard]] ::uint64_t unbound_sockets() const; + void set_unbound_sockets(::uint64_t value); + + private: + ::uint64_t _internal_unbound_sockets() const; + void _internal_set_unbound_sockets(::uint64_t value); + + public: + // bool collection_healthy = 8 [json_name = "collectionHealthy"]; + void clear_collection_healthy() ; + [[nodiscard]] bool collection_healthy() const; + void set_collection_healthy(bool value); + + private: + bool _internal_collection_healthy() const; + void _internal_set_collection_healthy(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.HostEvidence) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<4, 9, + 0, 55, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const HostEvidence& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + ::uint64_t sockets_; + ::uint64_t bytes_acked_; + double goodput_bps_; + double retransmission_ratio_; + double rtt_p95_ms_; + ::uint64_t exposed_sockets_; + ::uint64_t unbound_sockets_; + bool collection_healthy_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Capabilities final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.Capabilities) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Capabilities() : Capabilities(nullptr) {} + ~Capabilities() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Capabilities* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Capabilities)); + } +#endif + + template + explicit constexpr Capabilities(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Capabilities(const Capabilities& from) : Capabilities(nullptr, from) {} + inline Capabilities(Capabilities&& from) noexcept : Capabilities(nullptr, ::std::move(from)) {} + inline Capabilities& operator=(const Capabilities& from) { + CopyFrom(from); + return *this; + } + inline Capabilities& operator=(Capabilities&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Capabilities& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Capabilities_globals_); + } + static constexpr int kIndexInFileMessages = 4; + friend void swap(Capabilities& a, Capabilities& b) { a.Swap(&b); } + inline void Swap(Capabilities* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Capabilities* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Capabilities* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Capabilities& from); + using Super_::MergeFrom; + void MergeFrom(const Capabilities& from) { Capabilities::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Capabilities* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.Capabilities"; } + + explicit Capabilities(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Capabilities(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Capabilities& from); + Capabilities( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Capabilities&& from) noexcept + : Capabilities(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kCongestionAlgorithmsFieldNumber = 3, + kBootIdFieldNumber = 1, + kKernelReleaseFieldNumber = 2, + kCollectionIdFieldNumber = 6, + kSimpleHostRoutingFieldNumber = 4, + kActuatorEnabledFieldNumber = 5, + }; + // repeated string congestion_algorithms = 3 [json_name = "congestionAlgorithms", (.buf.validate.field) = { + [[nodiscard]] int congestion_algorithms_size() const; + private: + int _internal_congestion_algorithms_size() const; + + public: + void clear_congestion_algorithms() ; + [[nodiscard]] const ::std::string& congestion_algorithms(int index) const; + ::std::string* PROTOBUF_NONNULL mutable_congestion_algorithms(int index); + template + void set_congestion_algorithms(int index, Arg_&& value, Args_... args); + ::std::string* PROTOBUF_NONNULL add_congestion_algorithms(); + template + void add_congestion_algorithms(Arg_&& value, Args_... args); + [[nodiscard]] const + ::google::protobuf::RepeatedPtrField<::std::string>& + congestion_algorithms() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::std::string>* + PROTOBUF_NONNULL + mutable_congestion_algorithms(); + + private: + const ::google::protobuf::RepeatedPtrField<::std::string>& _internal_congestion_algorithms() const; + ::google::protobuf::RepeatedPtrField<::std::string>* PROTOBUF_NONNULL _internal_mutable_congestion_algorithms(); + + public: + // string boot_id = 1 [json_name = "bootId", (.buf.validate.field) = { + void clear_boot_id() ; + [[nodiscard]] const ::std::string& boot_id() const; + template + void set_boot_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_boot_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_boot_id(); + void set_allocated_boot_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_boot_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_boot_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_boot_id(); + + public: + // string kernel_release = 2 [json_name = "kernelRelease", (.buf.validate.field) = { + void clear_kernel_release() ; + [[nodiscard]] const ::std::string& kernel_release() const; + template + void set_kernel_release(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_kernel_release(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_kernel_release(); + void set_allocated_kernel_release(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_kernel_release() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_kernel_release(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_kernel_release(); + + public: + // string collection_id = 6 [json_name = "collectionId", (.buf.validate.field) = { + void clear_collection_id() ; + [[nodiscard]] const ::std::string& collection_id() const; + template + void set_collection_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_collection_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_collection_id(); + void set_allocated_collection_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_collection_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_collection_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_collection_id(); + + public: + // bool simple_host_routing = 4 [json_name = "simpleHostRouting"]; + void clear_simple_host_routing() ; + [[nodiscard]] bool simple_host_routing() const; + void set_simple_host_routing(bool value); + + private: + bool _internal_simple_host_routing() const; + void _internal_set_simple_host_routing(bool value); + + public: + // bool actuator_enabled = 5 [json_name = "actuatorEnabled"]; + void clear_actuator_enabled() ; + [[nodiscard]] bool actuator_enabled() const; + void set_actuator_enabled(bool value); + + private: + bool _internal_actuator_enabled() const; + void _internal_set_actuator_enabled(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.Capabilities) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 6, + 0, 94, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Capabilities& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField<::std::string> congestion_algorithms_; + ::google::protobuf::internal::ArenaStringPtr boot_id_; + ::google::protobuf::internal::ArenaStringPtr kernel_release_; + ::google::protobuf::internal::ArenaStringPtr collection_id_; + bool simple_host_routing_; + bool actuator_enabled_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Treatment final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.Treatment) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Treatment() : Treatment(nullptr) {} + ~Treatment() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Treatment* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Treatment)); + } +#endif + + template + explicit constexpr Treatment(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Treatment(const Treatment& from) : Treatment(nullptr, from) {} + inline Treatment(Treatment&& from) noexcept : Treatment(nullptr, ::std::move(from)) {} + inline Treatment& operator=(const Treatment& from) { + CopyFrom(from); + return *this; + } + inline Treatment& operator=(Treatment&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Treatment& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Treatment_globals_); + } + static constexpr int kIndexInFileMessages = 1; + friend void swap(Treatment& a, Treatment& b) { a.Swap(&b); } + inline void Swap(Treatment* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Treatment* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Treatment* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Treatment& from); + using Super_::MergeFrom; + void MergeFrom(const Treatment& from) { Treatment::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Treatment* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.Treatment"; } + + explicit Treatment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Treatment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Treatment& from); + Treatment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Treatment&& from) noexcept + : Treatment(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kIdFieldNumber = 1, + kDestinationFieldNumber = 3, + kSettingsFieldNumber = 4, + kRevisionFieldNumber = 2, + kEcnFabricVerifiedFieldNumber = 5, + }; + // string id = 1 [json_name = "id", (.buf.validate.field) = { + void clear_id() ; + [[nodiscard]] const ::std::string& id() const; + template + void set_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_id(); + void set_allocated_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_id(); + + public: + // string destination = 3 [json_name = "destination", (.buf.validate.field) = { + void clear_destination() ; + [[nodiscard]] const ::std::string& destination() const; + template + void set_destination(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_destination(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_destination(); + void set_allocated_destination(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_destination() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_destination(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_destination(); + + public: + // .xtcp_treatment.v1.TCPSettings settings = 4 [json_name = "settings", (.buf.validate.field) = { + [[nodiscard]] bool has_settings() const; + void clear_settings() ; + [[nodiscard]] const ::xtcp_treatment::v1::TCPSettings& settings() const; + [[nodiscard]] ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE release_settings(); + ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NONNULL mutable_settings(); + void set_allocated_settings(::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_settings(::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE unsafe_arena_release_settings(); + + private: + const ::xtcp_treatment::v1::TCPSettings& _internal_settings() const; + ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NONNULL _internal_mutable_settings(); + + public: + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + void clear_revision() ; + [[nodiscard]] ::uint64_t revision() const; + void set_revision(::uint64_t value); + + private: + ::uint64_t _internal_revision() const; + void _internal_set_revision(::uint64_t value); + + public: + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + void clear_ecn_fabric_verified() ; + [[nodiscard]] bool ecn_fabric_verified() const; + void set_ecn_fabric_verified(bool value); + + private: + bool _internal_ecn_fabric_verified() const; + void _internal_set_ecn_fabric_verified(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.Treatment) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 5, + 1, 49, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Treatment& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr id_; + ::google::protobuf::internal::ArenaStringPtr destination_; + ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE settings_; + ::uint64_t revision_; + bool ecn_fabric_verified_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ExperimentPolicy final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ExperimentPolicy) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ExperimentPolicy() : ExperimentPolicy(nullptr) {} + ~ExperimentPolicy() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ExperimentPolicy* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ExperimentPolicy)); + } +#endif + + template + explicit constexpr ExperimentPolicy(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ExperimentPolicy(const ExperimentPolicy& from) : ExperimentPolicy(nullptr, from) {} + inline ExperimentPolicy(ExperimentPolicy&& from) noexcept : ExperimentPolicy(nullptr, ::std::move(from)) {} + inline ExperimentPolicy& operator=(const ExperimentPolicy& from) { + CopyFrom(from); + return *this; + } + inline ExperimentPolicy& operator=(ExperimentPolicy&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ExperimentPolicy& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ExperimentPolicy_globals_); + } + static constexpr int kIndexInFileMessages = 9; + friend void swap(ExperimentPolicy& a, ExperimentPolicy& b) { a.Swap(&b); } + inline void Swap(ExperimentPolicy* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ExperimentPolicy* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ExperimentPolicy* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ExperimentPolicy& from); + using Super_::MergeFrom; + void MergeFrom(const ExperimentPolicy& from) { ExperimentPolicy::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ExperimentPolicy* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ExperimentPolicy"; } + + explicit ExperimentPolicy(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ExperimentPolicy(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ExperimentPolicy& from); + ExperimentPolicy( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ExperimentPolicy&& from) noexcept + : ExperimentPolicy(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kMinimumObservationFieldNumber = 1, + kMaximumPhaseFieldNumber = 2, + kMaximumEvidenceAgeFieldNumber = 9, + kMinimumSocketsPerHostFieldNumber = 3, + kMinimumBytesPerHostFieldNumber = 4, + kMinimumImprovementFieldNumber = 6, + kMaximumRetransmissionIncreaseFieldNumber = 7, + kMaximumRttIncreaseFieldNumber = 8, + kMinimumTreatedHostsFieldNumber = 5, + }; + // .google.protobuf.Duration minimum_observation = 1 [json_name = "minimumObservation", (.buf.validate.field) = { + [[nodiscard]] bool has_minimum_observation() const; + void clear_minimum_observation() ; + [[nodiscard]] const ::google::protobuf::Duration& minimum_observation() const; + [[nodiscard]] ::google::protobuf::Duration* PROTOBUF_NULLABLE release_minimum_observation(); + ::google::protobuf::Duration* PROTOBUF_NONNULL mutable_minimum_observation(); + void set_allocated_minimum_observation(::google::protobuf::Duration* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_minimum_observation(::google::protobuf::Duration* PROTOBUF_NULLABLE value); + ::google::protobuf::Duration* PROTOBUF_NULLABLE unsafe_arena_release_minimum_observation(); + + private: + const ::google::protobuf::Duration& _internal_minimum_observation() const; + ::google::protobuf::Duration* PROTOBUF_NONNULL _internal_mutable_minimum_observation(); + + public: + // .google.protobuf.Duration maximum_phase = 2 [json_name = "maximumPhase", (.buf.validate.field) = { + [[nodiscard]] bool has_maximum_phase() const; + void clear_maximum_phase() ; + [[nodiscard]] const ::google::protobuf::Duration& maximum_phase() const; + [[nodiscard]] ::google::protobuf::Duration* PROTOBUF_NULLABLE release_maximum_phase(); + ::google::protobuf::Duration* PROTOBUF_NONNULL mutable_maximum_phase(); + void set_allocated_maximum_phase(::google::protobuf::Duration* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_maximum_phase(::google::protobuf::Duration* PROTOBUF_NULLABLE value); + ::google::protobuf::Duration* PROTOBUF_NULLABLE unsafe_arena_release_maximum_phase(); + + private: + const ::google::protobuf::Duration& _internal_maximum_phase() const; + ::google::protobuf::Duration* PROTOBUF_NONNULL _internal_mutable_maximum_phase(); + + public: + // .google.protobuf.Duration maximum_evidence_age = 9 [json_name = "maximumEvidenceAge", (.buf.validate.field) = { + [[nodiscard]] bool has_maximum_evidence_age() const; + void clear_maximum_evidence_age() ; + [[nodiscard]] const ::google::protobuf::Duration& maximum_evidence_age() const; + [[nodiscard]] ::google::protobuf::Duration* PROTOBUF_NULLABLE release_maximum_evidence_age(); + ::google::protobuf::Duration* PROTOBUF_NONNULL mutable_maximum_evidence_age(); + void set_allocated_maximum_evidence_age(::google::protobuf::Duration* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_maximum_evidence_age(::google::protobuf::Duration* PROTOBUF_NULLABLE value); + ::google::protobuf::Duration* PROTOBUF_NULLABLE unsafe_arena_release_maximum_evidence_age(); + + private: + const ::google::protobuf::Duration& _internal_maximum_evidence_age() const; + ::google::protobuf::Duration* PROTOBUF_NONNULL _internal_mutable_maximum_evidence_age(); + + public: + // uint64 minimum_sockets_per_host = 3 [json_name = "minimumSocketsPerHost", (.buf.validate.field) = { + void clear_minimum_sockets_per_host() ; + [[nodiscard]] ::uint64_t minimum_sockets_per_host() const; + void set_minimum_sockets_per_host(::uint64_t value); + + private: + ::uint64_t _internal_minimum_sockets_per_host() const; + void _internal_set_minimum_sockets_per_host(::uint64_t value); + + public: + // uint64 minimum_bytes_per_host = 4 [json_name = "minimumBytesPerHost", (.buf.validate.field) = { + void clear_minimum_bytes_per_host() ; + [[nodiscard]] ::uint64_t minimum_bytes_per_host() const; + void set_minimum_bytes_per_host(::uint64_t value); + + private: + ::uint64_t _internal_minimum_bytes_per_host() const; + void _internal_set_minimum_bytes_per_host(::uint64_t value); + + public: + // double minimum_improvement = 6 [json_name = "minimumImprovement", (.buf.validate.field) = { + void clear_minimum_improvement() ; + [[nodiscard]] double minimum_improvement() const; + void set_minimum_improvement(double value); + + private: + double _internal_minimum_improvement() const; + void _internal_set_minimum_improvement(double value); + + public: + // double maximum_retransmission_increase = 7 [json_name = "maximumRetransmissionIncrease", (.buf.validate.field) = { + void clear_maximum_retransmission_increase() ; + [[nodiscard]] double maximum_retransmission_increase() const; + void set_maximum_retransmission_increase(double value); + + private: + double _internal_maximum_retransmission_increase() const; + void _internal_set_maximum_retransmission_increase(double value); + + public: + // double maximum_rtt_increase = 8 [json_name = "maximumRttIncrease", (.buf.validate.field) = { + void clear_maximum_rtt_increase() ; + [[nodiscard]] double maximum_rtt_increase() const; + void set_maximum_rtt_increase(double value); + + private: + double _internal_maximum_rtt_increase() const; + void _internal_set_maximum_rtt_increase(double value); + + public: + // uint32 minimum_treated_hosts = 5 [json_name = "minimumTreatedHosts", (.buf.validate.field) = { + void clear_minimum_treated_hosts() ; + [[nodiscard]] ::uint32_t minimum_treated_hosts() const; + void set_minimum_treated_hosts(::uint32_t value); + + private: + ::uint32_t _internal_minimum_treated_hosts() const; + void _internal_set_minimum_treated_hosts(::uint32_t value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ExperimentPolicy) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<4, 9, + 3, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ExperimentPolicy& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::Duration* PROTOBUF_NULLABLE minimum_observation_; + ::google::protobuf::Duration* PROTOBUF_NULLABLE maximum_phase_; + ::google::protobuf::Duration* PROTOBUF_NULLABLE maximum_evidence_age_; + ::uint64_t minimum_sockets_per_host_; + ::uint64_t minimum_bytes_per_host_; + double minimum_improvement_; + double maximum_retransmission_increase_; + double maximum_rtt_increase_; + ::uint32_t minimum_treated_hosts_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Evidence final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.Evidence) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Evidence() : Evidence(nullptr) {} + ~Evidence() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Evidence* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Evidence)); + } +#endif + + template + explicit constexpr Evidence(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Evidence(const Evidence& from) : Evidence(nullptr, from) {} + inline Evidence(Evidence&& from) noexcept : Evidence(nullptr, ::std::move(from)) {} + inline Evidence& operator=(const Evidence& from) { + CopyFrom(from); + return *this; + } + inline Evidence& operator=(Evidence&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Evidence& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Evidence_globals_); + } + static constexpr int kIndexInFileMessages = 8; + friend void swap(Evidence& a, Evidence& b) { a.Swap(&b); } + inline void Swap(Evidence* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Evidence* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Evidence* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Evidence& from); + using Super_::MergeFrom; + void MergeFrom(const Evidence& from) { Evidence::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Evidence* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.Evidence"; } + + explicit Evidence(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Evidence(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Evidence& from); + Evidence( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Evidence&& from) noexcept + : Evidence(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kHostsFieldNumber = 7, + kIdFieldNumber = 1, + kQueryVersionFieldNumber = 5, + kEnrichmentVersionFieldNumber = 6, + kArtifactSha256FieldNumber = 8, + kAnalyzedAtFieldNumber = 2, + kWindowStartFieldNumber = 3, + kWindowEndFieldNumber = 4, + }; + // repeated .xtcp_treatment.v1.HostEvidence hosts = 7 [json_name = "hosts", (.buf.validate.field) = { + [[nodiscard]] int hosts_size() const; + private: + int _internal_hosts_size() const; + + public: + void clear_hosts() ; + [[nodiscard]] const ::xtcp_treatment::v1::HostEvidence& hosts(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::HostEvidence* PROTOBUF_NONNULL mutable_hosts(int index); + ::xtcp_treatment::v1::HostEvidence* PROTOBUF_NONNULL add_hosts(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>& + hosts() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>* PROTOBUF_NONNULL + mutable_hosts(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>& _internal_hosts() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>* PROTOBUF_NONNULL _internal_mutable_hosts(); + + public: + // string id = 1 [json_name = "id", (.buf.validate.field) = { + void clear_id() ; + [[nodiscard]] const ::std::string& id() const; + template + void set_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_id(); + void set_allocated_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_id(); + + public: + // string query_version = 5 [json_name = "queryVersion", (.buf.validate.field) = { + void clear_query_version() ; + [[nodiscard]] const ::std::string& query_version() const; + template + void set_query_version(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_query_version(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_query_version(); + void set_allocated_query_version(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_query_version() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_query_version(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_query_version(); + + public: + // string enrichment_version = 6 [json_name = "enrichmentVersion", (.buf.validate.field) = { + void clear_enrichment_version() ; + [[nodiscard]] const ::std::string& enrichment_version() const; + template + void set_enrichment_version(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_enrichment_version(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_enrichment_version(); + void set_allocated_enrichment_version(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_enrichment_version() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_enrichment_version(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_enrichment_version(); + + public: + // string artifact_sha256 = 8 [json_name = "artifactSha256", (.buf.validate.field) = { + void clear_artifact_sha256() ; + [[nodiscard]] const ::std::string& artifact_sha256() const; + template + void set_artifact_sha256(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_artifact_sha256(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_artifact_sha256(); + void set_allocated_artifact_sha256(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_artifact_sha256() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_artifact_sha256(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_artifact_sha256(); + + public: + // .google.protobuf.Timestamp analyzed_at = 2 [json_name = "analyzedAt", (.buf.validate.field) = { + [[nodiscard]] bool has_analyzed_at() const; + void clear_analyzed_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& analyzed_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_analyzed_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_analyzed_at(); + void set_allocated_analyzed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_analyzed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_analyzed_at(); + + private: + const ::google::protobuf::Timestamp& _internal_analyzed_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_analyzed_at(); + + public: + // .google.protobuf.Timestamp window_start = 3 [json_name = "windowStart", (.buf.validate.field) = { + [[nodiscard]] bool has_window_start() const; + void clear_window_start() ; + [[nodiscard]] const ::google::protobuf::Timestamp& window_start() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_window_start(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_window_start(); + void set_allocated_window_start(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_window_start(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_window_start(); + + private: + const ::google::protobuf::Timestamp& _internal_window_start() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_window_start(); + + public: + // .google.protobuf.Timestamp window_end = 4 [json_name = "windowEnd", (.buf.validate.field) = { + [[nodiscard]] bool has_window_end() const; + void clear_window_end() ; + [[nodiscard]] const ::google::protobuf::Timestamp& window_end() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_window_end(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_window_end(); + void set_allocated_window_end(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_window_end(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_window_end(); + + private: + const ::google::protobuf::Timestamp& _internal_window_end() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_window_end(); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.Evidence) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 8, + 4, 91, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Evidence& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::HostEvidence > hosts_; + ::google::protobuf::internal::ArenaStringPtr id_; + ::google::protobuf::internal::ArenaStringPtr query_version_; + ::google::protobuf::internal::ArenaStringPtr enrichment_version_; + ::google::protobuf::internal::ArenaStringPtr artifact_sha256_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE analyzed_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE window_start_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE window_end_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Phase final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.Phase) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Phase() : Phase(nullptr) {} + ~Phase() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Phase* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Phase)); + } +#endif + + template + explicit constexpr Phase(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Phase(const Phase& from) : Phase(nullptr, from) {} + inline Phase(Phase&& from) noexcept : Phase(nullptr, ::std::move(from)) {} + inline Phase& operator=(const Phase& from) { + CopyFrom(from); + return *this; + } + inline Phase& operator=(Phase&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Phase& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Phase_globals_); + } + static constexpr int kIndexInFileMessages = 10; + friend void swap(Phase& a, Phase& b) { a.Swap(&b); } + inline void Swap(Phase* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Phase* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Phase* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Phase& from); + using Super_::MergeFrom; + void MergeFrom(const Phase& from) { Phase::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Phase* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.Phase"; } + + explicit Phase(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Phase(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Phase& from); + Phase( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Phase&& from) noexcept + : Phase(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kReviewerFieldNumber = 7, + kReasonFieldNumber = 8, + kIssuedAtFieldNumber = 2, + kObservationStartedAtFieldNumber = 3, + kEvaluatedAtFieldNumber = 4, + kEvidenceFieldNumber = 5, + kTargetHostsFieldNumber = 1, + kOutcomeFieldNumber = 6, + }; + // string reviewer = 7 [json_name = "reviewer", (.buf.validate.field) = { + void clear_reviewer() ; + [[nodiscard]] const ::std::string& reviewer() const; + template + void set_reviewer(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_reviewer(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_reviewer(); + void set_allocated_reviewer(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_reviewer() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_reviewer(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_reviewer(); + + public: + // string reason = 8 [json_name = "reason", (.buf.validate.field) = { + void clear_reason() ; + [[nodiscard]] const ::std::string& reason() const; + template + void set_reason(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_reason(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_reason(); + void set_allocated_reason(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_reason() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_reason(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_reason(); + + public: + // .google.protobuf.Timestamp issued_at = 2 [json_name = "issuedAt"]; + [[nodiscard]] bool has_issued_at() const; + void clear_issued_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& issued_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_issued_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_issued_at(); + void set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_issued_at(); + + private: + const ::google::protobuf::Timestamp& _internal_issued_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_issued_at(); + + public: + // .google.protobuf.Timestamp observation_started_at = 3 [json_name = "observationStartedAt"]; + [[nodiscard]] bool has_observation_started_at() const; + void clear_observation_started_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& observation_started_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_observation_started_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_observation_started_at(); + void set_allocated_observation_started_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_observation_started_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_observation_started_at(); + + private: + const ::google::protobuf::Timestamp& _internal_observation_started_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_observation_started_at(); + + public: + // .google.protobuf.Timestamp evaluated_at = 4 [json_name = "evaluatedAt"]; + [[nodiscard]] bool has_evaluated_at() const; + void clear_evaluated_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& evaluated_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_evaluated_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_evaluated_at(); + void set_allocated_evaluated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_evaluated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_evaluated_at(); + + private: + const ::google::protobuf::Timestamp& _internal_evaluated_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_evaluated_at(); + + public: + // .xtcp_treatment.v1.Evidence evidence = 5 [json_name = "evidence"]; + [[nodiscard]] bool has_evidence() const; + void clear_evidence() ; + [[nodiscard]] const ::xtcp_treatment::v1::Evidence& evidence() const; + [[nodiscard]] ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE release_evidence(); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL mutable_evidence(); + void set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE unsafe_arena_release_evidence(); + + private: + const ::xtcp_treatment::v1::Evidence& _internal_evidence() const; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL _internal_mutable_evidence(); + + public: + // uint32 target_hosts = 1 [json_name = "targetHosts", (.buf.validate.field) = { + void clear_target_hosts() ; + [[nodiscard]] ::uint32_t target_hosts() const; + void set_target_hosts(::uint32_t value); + + private: + ::uint32_t _internal_target_hosts() const; + void _internal_set_target_hosts(::uint32_t value); + + public: + // .xtcp_treatment.v1.Outcome outcome = 6 [json_name = "outcome", (.buf.validate.field) = { + void clear_outcome() ; + [[nodiscard]] ::xtcp_treatment::v1::Outcome outcome() const; + void set_outcome(::xtcp_treatment::v1::Outcome value); + + private: + ::xtcp_treatment::v1::Outcome _internal_outcome() const; + void _internal_set_outcome(::xtcp_treatment::v1::Outcome value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.Phase) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 8, + 4, 54, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Phase& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr reviewer_; + ::google::protobuf::internal::ArenaStringPtr reason_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE issued_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE observation_started_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE evaluated_at_; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE evidence_; + ::uint32_t target_hosts_; + int outcome_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Assignment final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.Assignment) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Assignment() : Assignment(nullptr) {} + ~Assignment() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Assignment* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Assignment)); + } +#endif + + template + explicit constexpr Assignment(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Assignment(const Assignment& from) : Assignment(nullptr, from) {} + inline Assignment(Assignment&& from) noexcept : Assignment(nullptr, ::std::move(from)) {} + inline Assignment& operator=(const Assignment& from) { + CopyFrom(from); + return *this; + } + inline Assignment& operator=(Assignment&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Assignment& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Assignment_globals_); + } + static constexpr int kIndexInFileMessages = 2; + friend void swap(Assignment& a, Assignment& b) { a.Swap(&b); } + inline void Swap(Assignment* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Assignment* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Assignment* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Assignment& from); + using Super_::MergeFrom; + void MergeFrom(const Assignment& from) { Assignment::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Assignment* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.Assignment"; } + + explicit Assignment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Assignment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Assignment& from); + Assignment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Assignment&& from) noexcept + : Assignment(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentIdFieldNumber = 2, + kTreatmentFieldNumber = 3, + kLeaseExpiresAtFieldNumber = 5, + kPredecessorFieldNumber = 6, + kGenerationFieldNumber = 7, + kModeFieldNumber = 4, + }; + // string experiment_id = 2 [json_name = "experimentId", (.buf.validate.field) = { + void clear_experiment_id() ; + [[nodiscard]] const ::std::string& experiment_id() const; + template + void set_experiment_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_experiment_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_experiment_id(); + void set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_experiment_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_experiment_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_experiment_id(); + + public: + // .xtcp_treatment.v1.Treatment treatment = 3 [json_name = "treatment", (.buf.validate.field) = { + [[nodiscard]] bool has_treatment() const; + void clear_treatment() ; + [[nodiscard]] const ::xtcp_treatment::v1::Treatment& treatment() const; + [[nodiscard]] ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE release_treatment(); + ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL mutable_treatment(); + void set_allocated_treatment(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_treatment(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE unsafe_arena_release_treatment(); + + private: + const ::xtcp_treatment::v1::Treatment& _internal_treatment() const; + ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL _internal_mutable_treatment(); + + public: + // .google.protobuf.Timestamp lease_expires_at = 5 [json_name = "leaseExpiresAt"]; + [[nodiscard]] bool has_lease_expires_at() const; + void clear_lease_expires_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& lease_expires_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_lease_expires_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_lease_expires_at(); + void set_allocated_lease_expires_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_lease_expires_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_lease_expires_at(); + + private: + const ::google::protobuf::Timestamp& _internal_lease_expires_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_lease_expires_at(); + + public: + // .xtcp_treatment.v1.Treatment predecessor = 6 [json_name = "predecessor"]; + [[nodiscard]] bool has_predecessor() const; + void clear_predecessor() ; + [[nodiscard]] const ::xtcp_treatment::v1::Treatment& predecessor() const; + [[nodiscard]] ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE release_predecessor(); + ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL mutable_predecessor(); + void set_allocated_predecessor(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_predecessor(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE unsafe_arena_release_predecessor(); + + private: + const ::xtcp_treatment::v1::Treatment& _internal_predecessor() const; + ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL _internal_mutable_predecessor(); + + public: + // uint64 generation = 7 [json_name = "generation", (.buf.validate.field) = { + void clear_generation() ; + [[nodiscard]] ::uint64_t generation() const; + void set_generation(::uint64_t value); + + private: + ::uint64_t _internal_generation() const; + void _internal_set_generation(::uint64_t value); + + public: + // .xtcp_treatment.v1.AssignmentMode mode = 4 [json_name = "mode", (.buf.validate.field) = { + void clear_mode() ; + [[nodiscard]] ::xtcp_treatment::v1::AssignmentMode mode() const; + void set_mode(::xtcp_treatment::v1::AssignmentMode value); + + private: + ::xtcp_treatment::v1::AssignmentMode _internal_mode() const; + void _internal_set_mode(::xtcp_treatment::v1::AssignmentMode value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.Assignment) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 6, + 3, 50, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Assignment& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr experiment_id_; + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE treatment_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE lease_expires_at_; + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE predecessor_; + ::uint64_t generation_; + int mode_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Experiment final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.Experiment) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Experiment() : Experiment(nullptr) {} + ~Experiment() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Experiment* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Experiment)); + } +#endif + + template + explicit constexpr Experiment(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Experiment(const Experiment& from) : Experiment(nullptr, from) {} + inline Experiment(Experiment&& from) noexcept : Experiment(nullptr, ::std::move(from)) {} + inline Experiment& operator=(const Experiment& from) { + CopyFrom(from); + return *this; + } + inline Experiment& operator=(Experiment&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Experiment& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Experiment_globals_); + } + static constexpr int kIndexInFileMessages = 11; + friend void swap(Experiment& a, Experiment& b) { a.Swap(&b); } + inline void Swap(Experiment* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Experiment* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Experiment* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Experiment& from); + using Super_::MergeFrom; + void MergeFrom(const Experiment& from) { Experiment::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Experiment* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.Experiment"; } + + explicit Experiment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Experiment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Experiment& from); + Experiment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Experiment&& from) noexcept + : Experiment(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kCohortOrderFieldNumber = 7, + kPhasesFieldNumber = 8, + kIdFieldNumber = 1, + kLocationFieldNumber = 2, + kHypothesisFieldNumber = 3, + kTreatmentFieldNumber = 4, + kPolicyFieldNumber = 5, + kBaselineFieldNumber = 6, + kProposedAtFieldNumber = 11, + kLatestEvidenceFieldNumber = 12, + kUpdatedAtFieldNumber = 14, + kRevisionFieldNumber = 10, + kStatusFieldNumber = 9, + kLatestOutcomeFieldNumber = 13, + }; + // repeated string cohort_order = 7 [json_name = "cohortOrder", (.buf.validate.field) = { + [[nodiscard]] int cohort_order_size() const; + private: + int _internal_cohort_order_size() const; + + public: + void clear_cohort_order() ; + [[nodiscard]] const ::std::string& cohort_order(int index) const; + ::std::string* PROTOBUF_NONNULL mutable_cohort_order(int index); + template + void set_cohort_order(int index, Arg_&& value, Args_... args); + ::std::string* PROTOBUF_NONNULL add_cohort_order(); + template + void add_cohort_order(Arg_&& value, Args_... args); + [[nodiscard]] const + ::google::protobuf::RepeatedPtrField<::std::string>& + cohort_order() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::std::string>* + PROTOBUF_NONNULL + mutable_cohort_order(); + + private: + const ::google::protobuf::RepeatedPtrField<::std::string>& _internal_cohort_order() const; + ::google::protobuf::RepeatedPtrField<::std::string>* PROTOBUF_NONNULL _internal_mutable_cohort_order(); + + public: + // repeated .xtcp_treatment.v1.Phase phases = 8 [json_name = "phases", (.buf.validate.field) = { + [[nodiscard]] int phases_size() const; + private: + int _internal_phases_size() const; + + public: + void clear_phases() ; + [[nodiscard]] const ::xtcp_treatment::v1::Phase& phases(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::Phase* PROTOBUF_NONNULL mutable_phases(int index); + ::xtcp_treatment::v1::Phase* PROTOBUF_NONNULL add_phases(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>& + phases() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>* PROTOBUF_NONNULL + mutable_phases(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>& _internal_phases() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>* PROTOBUF_NONNULL _internal_mutable_phases(); + + public: + // string id = 1 [json_name = "id", (.buf.validate.field) = { + void clear_id() ; + [[nodiscard]] const ::std::string& id() const; + template + void set_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_id(); + void set_allocated_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_id(); + + public: + // string location = 2 [json_name = "location", (.buf.validate.field) = { + void clear_location() ; + [[nodiscard]] const ::std::string& location() const; + template + void set_location(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_location(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_location(); + void set_allocated_location(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_location() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_location(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_location(); + + public: + // string hypothesis = 3 [json_name = "hypothesis", (.buf.validate.field) = { + void clear_hypothesis() ; + [[nodiscard]] const ::std::string& hypothesis() const; + template + void set_hypothesis(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_hypothesis(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_hypothesis(); + void set_allocated_hypothesis(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_hypothesis() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_hypothesis(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_hypothesis(); + + public: + // .xtcp_treatment.v1.Treatment treatment = 4 [json_name = "treatment", (.buf.validate.field) = { + [[nodiscard]] bool has_treatment() const; + void clear_treatment() ; + [[nodiscard]] const ::xtcp_treatment::v1::Treatment& treatment() const; + [[nodiscard]] ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE release_treatment(); + ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL mutable_treatment(); + void set_allocated_treatment(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_treatment(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE unsafe_arena_release_treatment(); + + private: + const ::xtcp_treatment::v1::Treatment& _internal_treatment() const; + ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL _internal_mutable_treatment(); + + public: + // .xtcp_treatment.v1.ExperimentPolicy policy = 5 [json_name = "policy", (.buf.validate.field) = { + [[nodiscard]] bool has_policy() const; + void clear_policy() ; + [[nodiscard]] const ::xtcp_treatment::v1::ExperimentPolicy& policy() const; + [[nodiscard]] ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE release_policy(); + ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NONNULL mutable_policy(); + void set_allocated_policy(::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_policy(::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE unsafe_arena_release_policy(); + + private: + const ::xtcp_treatment::v1::ExperimentPolicy& _internal_policy() const; + ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NONNULL _internal_mutable_policy(); + + public: + // .xtcp_treatment.v1.Evidence baseline = 6 [json_name = "baseline", (.buf.validate.field) = { + [[nodiscard]] bool has_baseline() const; + void clear_baseline() ; + [[nodiscard]] const ::xtcp_treatment::v1::Evidence& baseline() const; + [[nodiscard]] ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE release_baseline(); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL mutable_baseline(); + void set_allocated_baseline(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_baseline(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE unsafe_arena_release_baseline(); + + private: + const ::xtcp_treatment::v1::Evidence& _internal_baseline() const; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL _internal_mutable_baseline(); + + public: + // .google.protobuf.Timestamp proposed_at = 11 [json_name = "proposedAt"]; + [[nodiscard]] bool has_proposed_at() const; + void clear_proposed_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& proposed_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_proposed_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_proposed_at(); + void set_allocated_proposed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_proposed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_proposed_at(); + + private: + const ::google::protobuf::Timestamp& _internal_proposed_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_proposed_at(); + + public: + // .xtcp_treatment.v1.Evidence latest_evidence = 12 [json_name = "latestEvidence"]; + [[nodiscard]] bool has_latest_evidence() const; + void clear_latest_evidence() ; + [[nodiscard]] const ::xtcp_treatment::v1::Evidence& latest_evidence() const; + [[nodiscard]] ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE release_latest_evidence(); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL mutable_latest_evidence(); + void set_allocated_latest_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_latest_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE unsafe_arena_release_latest_evidence(); + + private: + const ::xtcp_treatment::v1::Evidence& _internal_latest_evidence() const; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL _internal_mutable_latest_evidence(); + + public: + // .google.protobuf.Timestamp updated_at = 14 [json_name = "updatedAt"]; + [[nodiscard]] bool has_updated_at() const; + void clear_updated_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& updated_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_updated_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_updated_at(); + void set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_updated_at(); + + private: + const ::google::protobuf::Timestamp& _internal_updated_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_updated_at(); + + public: + // uint64 revision = 10 [json_name = "revision"]; + void clear_revision() ; + [[nodiscard]] ::uint64_t revision() const; + void set_revision(::uint64_t value); + + private: + ::uint64_t _internal_revision() const; + void _internal_set_revision(::uint64_t value); + + public: + // .xtcp_treatment.v1.ExperimentStatus status = 9 [json_name = "status", (.buf.validate.field) = { + void clear_status() ; + [[nodiscard]] ::xtcp_treatment::v1::ExperimentStatus status() const; + void set_status(::xtcp_treatment::v1::ExperimentStatus value); + + private: + ::xtcp_treatment::v1::ExperimentStatus _internal_status() const; + void _internal_set_status(::xtcp_treatment::v1::ExperimentStatus value); + + public: + // .xtcp_treatment.v1.Outcome latest_outcome = 13 [json_name = "latestOutcome", (.buf.validate.field) = { + void clear_latest_outcome() ; + [[nodiscard]] ::xtcp_treatment::v1::Outcome latest_outcome() const; + void set_latest_outcome(::xtcp_treatment::v1::Outcome value); + + private: + ::xtcp_treatment::v1::Outcome _internal_latest_outcome() const; + void _internal_set_latest_outcome(::xtcp_treatment::v1::Outcome value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.Experiment) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<4, 14, + 7, 77, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Experiment& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField<::std::string> cohort_order_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::Phase > phases_; + ::google::protobuf::internal::ArenaStringPtr id_; + ::google::protobuf::internal::ArenaStringPtr location_; + ::google::protobuf::internal::ArenaStringPtr hypothesis_; + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE treatment_; + ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE policy_; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE baseline_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE proposed_at_; + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE latest_evidence_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE updated_at_; + ::uint64_t revision_; + int status_; + int latest_outcome_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED DesiredState final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.DesiredState) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline DesiredState() : DesiredState(nullptr) {} + ~DesiredState() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(DesiredState* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(DesiredState)); + } +#endif + + template + explicit constexpr DesiredState(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline DesiredState(const DesiredState& from) : DesiredState(nullptr, from) {} + inline DesiredState(DesiredState&& from) noexcept : DesiredState(nullptr, ::std::move(from)) {} + inline DesiredState& operator=(const DesiredState& from) { + CopyFrom(from); + return *this; + } + inline DesiredState& operator=(DesiredState&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const DesiredState& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&DesiredState_globals_); + } + static constexpr int kIndexInFileMessages = 3; + friend void swap(DesiredState& a, DesiredState& b) { a.Swap(&b); } + inline void Swap(DesiredState* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DesiredState* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] DesiredState* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const DesiredState& from); + using Super_::MergeFrom; + void MergeFrom(const DesiredState& from) { DesiredState::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(DesiredState* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.DesiredState"; } + + explicit DesiredState(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + DesiredState(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const DesiredState& from); + DesiredState( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, DesiredState&& from) noexcept + : DesiredState(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kAssignmentsFieldNumber = 4, + kAgentIdFieldNumber = 1, + kIssuedAtFieldNumber = 5, + kRevisionFieldNumber = 2, + kSuspendedFieldNumber = 3, + }; + // repeated .xtcp_treatment.v1.Assignment assignments = 4 [json_name = "assignments", (.buf.validate.field) = { + [[nodiscard]] int assignments_size() const; + private: + int _internal_assignments_size() const; + + public: + void clear_assignments() ; + [[nodiscard]] const ::xtcp_treatment::v1::Assignment& assignments(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL mutable_assignments(int index); + ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL add_assignments(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>& + assignments() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>* PROTOBUF_NONNULL + mutable_assignments(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>& _internal_assignments() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>* PROTOBUF_NONNULL _internal_mutable_assignments(); + + public: + // string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // .google.protobuf.Timestamp issued_at = 5 [json_name = "issuedAt", (.buf.validate.field) = { + [[nodiscard]] bool has_issued_at() const; + void clear_issued_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& issued_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_issued_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_issued_at(); + void set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_issued_at(); + + private: + const ::google::protobuf::Timestamp& _internal_issued_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_issued_at(); + + public: + // uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { + void clear_revision() ; + [[nodiscard]] ::uint64_t revision() const; + void set_revision(::uint64_t value); + + private: + ::uint64_t _internal_revision() const; + void _internal_set_revision(::uint64_t value); + + public: + // bool suspended = 3 [json_name = "suspended"]; + void clear_suspended() ; + [[nodiscard]] bool suspended() const; + void set_suspended(bool value); + + private: + bool _internal_suspended() const; + void _internal_set_suspended(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.DesiredState) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 5, + 2, 47, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const DesiredState& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::Assignment > assignments_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE issued_at_; + ::uint64_t revision_; + bool suspended_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED ApplicationRecord final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.ApplicationRecord) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline ApplicationRecord() : ApplicationRecord(nullptr) {} + ~ApplicationRecord() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ApplicationRecord* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ApplicationRecord)); + } +#endif + + template + explicit constexpr ApplicationRecord(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline ApplicationRecord(const ApplicationRecord& from) : ApplicationRecord(nullptr, from) {} + inline ApplicationRecord(ApplicationRecord&& from) noexcept : ApplicationRecord(nullptr, ::std::move(from)) {} + inline ApplicationRecord& operator=(const ApplicationRecord& from) { + CopyFrom(from); + return *this; + } + inline ApplicationRecord& operator=(ApplicationRecord&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const ApplicationRecord& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&ApplicationRecord_globals_); + } + static constexpr int kIndexInFileMessages = 5; + friend void swap(ApplicationRecord& a, ApplicationRecord& b) { a.Swap(&b); } + inline void Swap(ApplicationRecord* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ApplicationRecord* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] ApplicationRecord* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const ApplicationRecord& from); + using Super_::MergeFrom; + void MergeFrom(const ApplicationRecord& from) { ApplicationRecord::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(ApplicationRecord* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.ApplicationRecord"; } + + explicit ApplicationRecord(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + ApplicationRecord(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ApplicationRecord& from); + ApplicationRecord( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ApplicationRecord&& from) noexcept + : ApplicationRecord(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kErrorFieldNumber = 9, + kInstalledRouteFieldNumber = 10, + kInstalledBootIdFieldNumber = 11, + kAssignmentFieldNumber = 1, + kReceivedAtFieldNumber = 4, + kAttemptedAtFieldNumber = 5, + kAppliedAtFieldNumber = 6, + kVerifiedAtFieldNumber = 7, + kRemovedAtFieldNumber = 8, + kDesiredRevisionFieldNumber = 2, + kStatusFieldNumber = 3, + kExpiredLatchedFieldNumber = 12, + }; + // string error = 9 [json_name = "error", (.buf.validate.field) = { + void clear_error() ; + [[nodiscard]] const ::std::string& error() const; + template + void set_error(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_error(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_error(); + void set_allocated_error(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_error() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_error(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_error(); + + public: + // bytes installed_route = 10 [json_name = "installedRoute", (.buf.validate.field) = { + void clear_installed_route() ; + [[nodiscard]] const ::std::string& installed_route() const; + template + void set_installed_route(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_installed_route(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_installed_route(); + void set_allocated_installed_route(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_installed_route() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_installed_route(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_installed_route(); + + public: + // string installed_boot_id = 11 [json_name = "installedBootId", (.buf.validate.field) = { + void clear_installed_boot_id() ; + [[nodiscard]] const ::std::string& installed_boot_id() const; + template + void set_installed_boot_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_installed_boot_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_installed_boot_id(); + void set_allocated_installed_boot_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_installed_boot_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_installed_boot_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_installed_boot_id(); + + public: + // .xtcp_treatment.v1.Assignment assignment = 1 [json_name = "assignment", (.buf.validate.field) = { + [[nodiscard]] bool has_assignment() const; + void clear_assignment() ; + [[nodiscard]] const ::xtcp_treatment::v1::Assignment& assignment() const; + [[nodiscard]] ::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE release_assignment(); + ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL mutable_assignment(); + void set_allocated_assignment(::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_assignment(::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE unsafe_arena_release_assignment(); + + private: + const ::xtcp_treatment::v1::Assignment& _internal_assignment() const; + ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL _internal_mutable_assignment(); + + public: + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + [[nodiscard]] bool has_received_at() const; + void clear_received_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& received_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_received_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_received_at(); + void set_allocated_received_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_received_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_received_at(); + + private: + const ::google::protobuf::Timestamp& _internal_received_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_received_at(); + + public: + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + [[nodiscard]] bool has_attempted_at() const; + void clear_attempted_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& attempted_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_attempted_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_attempted_at(); + void set_allocated_attempted_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_attempted_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_attempted_at(); + + private: + const ::google::protobuf::Timestamp& _internal_attempted_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_attempted_at(); + + public: + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + [[nodiscard]] bool has_applied_at() const; + void clear_applied_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& applied_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_applied_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_applied_at(); + void set_allocated_applied_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_applied_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_applied_at(); + + private: + const ::google::protobuf::Timestamp& _internal_applied_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_applied_at(); + + public: + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + [[nodiscard]] bool has_verified_at() const; + void clear_verified_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& verified_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_verified_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_verified_at(); + void set_allocated_verified_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_verified_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_verified_at(); + + private: + const ::google::protobuf::Timestamp& _internal_verified_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_verified_at(); + + public: + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + [[nodiscard]] bool has_removed_at() const; + void clear_removed_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& removed_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_removed_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_removed_at(); + void set_allocated_removed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_removed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_removed_at(); + + private: + const ::google::protobuf::Timestamp& _internal_removed_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_removed_at(); + + public: + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + void clear_desired_revision() ; + [[nodiscard]] ::uint64_t desired_revision() const; + void set_desired_revision(::uint64_t value); + + private: + ::uint64_t _internal_desired_revision() const; + void _internal_set_desired_revision(::uint64_t value); + + public: + // .xtcp_treatment.v1.ApplyStatus status = 3 [json_name = "status", (.buf.validate.field) = { + void clear_status() ; + [[nodiscard]] ::xtcp_treatment::v1::ApplyStatus status() const; + void set_status(::xtcp_treatment::v1::ApplyStatus value); + + private: + ::xtcp_treatment::v1::ApplyStatus _internal_status() const; + void _internal_set_status(::xtcp_treatment::v1::ApplyStatus value); + + public: + // bool expired_latched = 12 [json_name = "expiredLatched"]; + void clear_expired_latched() ; + [[nodiscard]] bool expired_latched() const; + void set_expired_latched(bool value); + + private: + bool _internal_expired_latched() const; + void _internal_set_expired_latched(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.ApplicationRecord) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<4, 12, + 6, 74, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const ApplicationRecord& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr error_; + ::google::protobuf::internal::ArenaStringPtr installed_route_; + ::google::protobuf::internal::ArenaStringPtr installed_boot_id_; + ::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE assignment_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE received_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE attempted_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE applied_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE verified_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE removed_at_; + ::uint64_t desired_revision_; + int status_; + bool expired_latched_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED LocalState final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment.v1.LocalState) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline LocalState() : LocalState(nullptr) {} + ~LocalState() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(LocalState* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(LocalState)); + } +#endif + + template + explicit constexpr LocalState(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline LocalState(const LocalState& from) : LocalState(nullptr, from) {} + inline LocalState(LocalState&& from) noexcept : LocalState(nullptr, ::std::move(from)) {} + inline LocalState& operator=(const LocalState& from) { + CopyFrom(from); + return *this; + } + inline LocalState& operator=(LocalState&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const LocalState& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&LocalState_globals_); + } + static constexpr int kIndexInFileMessages = 6; + friend void swap(LocalState& a, LocalState& b) { a.Swap(&b); } + inline void Swap(LocalState* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(LocalState* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] LocalState* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const LocalState& from); + using Super_::MergeFrom; + void MergeFrom(const LocalState& from) { LocalState::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(LocalState* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment.v1.LocalState"; } + + explicit LocalState(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + LocalState(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const LocalState& from); + LocalState( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, LocalState&& from) noexcept + : LocalState(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kRecordsFieldNumber = 4, + kSuspensionReasonFieldNumber = 3, + kDesiredFieldNumber = 1, + kUpdatedAtFieldNumber = 5, + kLocallySuspendedFieldNumber = 2, + }; + // repeated .xtcp_treatment.v1.ApplicationRecord records = 4 [json_name = "records", (.buf.validate.field) = { + [[nodiscard]] int records_size() const; + private: + int _internal_records_size() const; + + public: + void clear_records() ; + [[nodiscard]] const ::xtcp_treatment::v1::ApplicationRecord& records(int index) const; + [[nodiscard]] ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL mutable_records(int index); + ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL add_records(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& + records() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL + mutable_records(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& _internal_records() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL _internal_mutable_records(); + + public: + // string suspension_reason = 3 [json_name = "suspensionReason", (.buf.validate.field) = { + void clear_suspension_reason() ; + [[nodiscard]] const ::std::string& suspension_reason() const; + template + void set_suspension_reason(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_suspension_reason(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_suspension_reason(); + void set_allocated_suspension_reason(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_suspension_reason() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_suspension_reason(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_suspension_reason(); + + public: + // .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; + [[nodiscard]] bool has_desired() const; + void clear_desired() ; + [[nodiscard]] const ::xtcp_treatment::v1::DesiredState& desired() const; + [[nodiscard]] ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE release_desired(); + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL mutable_desired(); + void set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value); + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE unsafe_arena_release_desired(); + + private: + const ::xtcp_treatment::v1::DesiredState& _internal_desired() const; + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL _internal_mutable_desired(); + + public: + // .google.protobuf.Timestamp updated_at = 5 [json_name = "updatedAt"]; + [[nodiscard]] bool has_updated_at() const; + void clear_updated_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& updated_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_updated_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_updated_at(); + void set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_updated_at(); + + private: + const ::google::protobuf::Timestamp& _internal_updated_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_updated_at(); + + public: + // bool locally_suspended = 2 [json_name = "locallySuspended"]; + void clear_locally_suspended() ; + [[nodiscard]] bool locally_suspended() const; + void set_locally_suspended(bool value); + + private: + bool _internal_locally_suspended() const; + void _internal_set_locally_suspended(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment.v1.LocalState) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 5, + 3, 54, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const LocalState& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment::v1::ApplicationRecord > records_; + ::google::protobuf::internal::ArenaStringPtr suspension_reason_; + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE desired_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE updated_at_; + bool locally_suspended_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_2fv1_2ftreatment_2eproto; +}; + +// =================================================================== + + + +inline constexpr int kRoleFieldNumber = 51002; +extern ::google::protobuf::internal::ExtensionIdentifier< + ::google::protobuf::MethodOptions, ::google::protobuf::internal::EnumTypeTraits< ::xtcp_treatment::v1::Role>, 14, false>(role); + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// TCPSettings + +// optional string congestion_control = 1 [json_name = "congestionControl", (.buf.validate.field) = { +inline bool TCPSettings::has_congestion_control() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + return value; +} +inline void TCPSettings::clear_congestion_control() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_control_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& TCPSettings::congestion_control() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.TCPSettings.congestion_control) + return _internal_congestion_control(); +} +template +PROTOBUF_ALWAYS_INLINE void TCPSettings::set_congestion_control(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.congestion_control_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.TCPSettings.congestion_control) +} +inline ::std::string* PROTOBUF_NONNULL TCPSettings::mutable_congestion_control() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_congestion_control(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.TCPSettings.congestion_control) + return _s; +} +inline const ::std::string& TCPSettings::_internal_congestion_control() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.congestion_control_.Get(); +} +inline void TCPSettings::_internal_set_congestion_control(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_control_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL TCPSettings::_internal_mutable_congestion_control() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.congestion_control_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE TCPSettings::release_congestion_control() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.TCPSettings.congestion_control) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.congestion_control_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.congestion_control_.Set("", GetArena()); + } + return released; +} +inline void TCPSettings::set_allocated_congestion_control(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.congestion_control_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.congestion_control_.IsDefault()) { + _impl_.congestion_control_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.TCPSettings.congestion_control) +} + +// bool congestion_lock = 2 [json_name = "congestionLock"]; +inline void TCPSettings::clear_congestion_lock() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_lock_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline bool TCPSettings::congestion_lock() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.TCPSettings.congestion_lock) + return _internal_congestion_lock(); +} +inline void TCPSettings::set_congestion_lock(bool value) { + _internal_set_congestion_lock(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.TCPSettings.congestion_lock) +} +inline bool TCPSettings::_internal_congestion_lock() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.congestion_lock_; +} +inline void TCPSettings::_internal_set_congestion_lock(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_lock_ = value; +} + +// optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs", (.buf.validate.field) = { +inline bool TCPSettings::has_rto_min_ms() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + return value; +} +inline void TCPSettings::clear_rto_min_ms() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rto_min_ms_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline ::uint32_t TCPSettings::rto_min_ms() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.TCPSettings.rto_min_ms) + return _internal_rto_min_ms(); +} +inline void TCPSettings::set_rto_min_ms(::uint32_t value) { + _internal_set_rto_min_ms(value); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.TCPSettings.rto_min_ms) +} +inline ::uint32_t TCPSettings::_internal_rto_min_ms() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.rto_min_ms_; +} +inline void TCPSettings::_internal_set_rto_min_ms(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rto_min_ms_ = value; +} + +// optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow", (.buf.validate.field) = { +inline bool TCPSettings::has_initial_congestion_window() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + return value; +} +inline void TCPSettings::clear_initial_congestion_window() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_congestion_window_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline ::uint32_t TCPSettings::initial_congestion_window() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.TCPSettings.initial_congestion_window) + return _internal_initial_congestion_window(); +} +inline void TCPSettings::set_initial_congestion_window(::uint32_t value) { + _internal_set_initial_congestion_window(value); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.TCPSettings.initial_congestion_window) +} +inline ::uint32_t TCPSettings::_internal_initial_congestion_window() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.initial_congestion_window_; +} +inline void TCPSettings::_internal_set_initial_congestion_window(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_congestion_window_ = value; +} + +// optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow", (.buf.validate.field) = { +inline bool TCPSettings::has_initial_receive_window() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + return value; +} +inline void TCPSettings::clear_initial_receive_window() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_receive_window_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline ::uint32_t TCPSettings::initial_receive_window() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.TCPSettings.initial_receive_window) + return _internal_initial_receive_window(); +} +inline void TCPSettings::set_initial_receive_window(::uint32_t value) { + _internal_set_initial_receive_window(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.TCPSettings.initial_receive_window) +} +inline ::uint32_t TCPSettings::_internal_initial_receive_window() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.initial_receive_window_; +} +inline void TCPSettings::_internal_set_initial_receive_window(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_receive_window_ = value; +} + +// optional bool quick_ack = 6 [json_name = "quickAck"]; +inline bool TCPSettings::has_quick_ack() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U); + return value; +} +inline void TCPSettings::clear_quick_ack() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.quick_ack_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline bool TCPSettings::quick_ack() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.TCPSettings.quick_ack) + return _internal_quick_ack(); +} +inline void TCPSettings::set_quick_ack(bool value) { + _internal_set_quick_ack(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.TCPSettings.quick_ack) +} +inline bool TCPSettings::_internal_quick_ack() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.quick_ack_; +} +inline void TCPSettings::_internal_set_quick_ack(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.quick_ack_ = value; +} + +// optional bool ecn = 7 [json_name = "ecn"]; +inline bool TCPSettings::has_ecn() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U); + return value; +} +inline void TCPSettings::clear_ecn() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline bool TCPSettings::ecn() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.TCPSettings.ecn) + return _internal_ecn(); +} +inline void TCPSettings::set_ecn(bool value) { + _internal_set_ecn(value); + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.TCPSettings.ecn) +} +inline bool TCPSettings::_internal_ecn() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.ecn_; +} +inline void TCPSettings::_internal_set_ecn(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_ = value; +} + +// ------------------------------------------------------------------- + +// Treatment + +// string id = 1 [json_name = "id", (.buf.validate.field) = { +inline void Treatment::clear_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& Treatment::id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Treatment.id) + return _internal_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Treatment::set_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Treatment.id) +} +inline ::std::string* PROTOBUF_NONNULL Treatment::mutable_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Treatment.id) + return _s; +} +inline const ::std::string& Treatment::_internal_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.id_.Get(); +} +inline void Treatment::_internal_set_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Treatment::_internal_mutable_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Treatment::release_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Treatment.id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.id_.Set("", GetArena()); + } + return released; +} +inline void Treatment::set_allocated_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.id_.IsDefault()) { + _impl_.id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Treatment.id) +} + +// uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { +inline void Treatment::clear_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline ::uint64_t Treatment::revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Treatment.revision) + return _internal_revision(); +} +inline void Treatment::set_revision(::uint64_t value) { + _internal_set_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Treatment.revision) +} +inline ::uint64_t Treatment::_internal_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.revision_; +} +inline void Treatment::_internal_set_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = value; +} + +// string destination = 3 [json_name = "destination", (.buf.validate.field) = { +inline void Treatment::clear_destination() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.destination_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& Treatment::destination() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Treatment.destination) + return _internal_destination(); +} +template +PROTOBUF_ALWAYS_INLINE void Treatment::set_destination(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.destination_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Treatment.destination) +} +inline ::std::string* PROTOBUF_NONNULL Treatment::mutable_destination() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_destination(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Treatment.destination) + return _s; +} +inline const ::std::string& Treatment::_internal_destination() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.destination_.Get(); +} +inline void Treatment::_internal_set_destination(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.destination_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Treatment::_internal_mutable_destination() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.destination_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Treatment::release_destination() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Treatment.destination) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.destination_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.destination_.Set("", GetArena()); + } + return released; +} +inline void Treatment::set_allocated_destination(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.destination_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.destination_.IsDefault()) { + _impl_.destination_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Treatment.destination) +} + +// .xtcp_treatment.v1.TCPSettings settings = 4 [json_name = "settings", (.buf.validate.field) = { +inline bool Treatment::has_settings() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.settings_ != nullptr); + return value; +} +inline void Treatment::clear_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.settings_ != nullptr) _impl_.settings_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::xtcp_treatment::v1::TCPSettings& Treatment::_internal_settings() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::TCPSettings* p = _impl_.settings_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::TCPSettings>(&::xtcp_treatment::v1::TCPSettings_globals_); +} +inline const ::xtcp_treatment::v1::TCPSettings& Treatment::settings() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Treatment.settings) + return _internal_settings(); +} +inline void Treatment::unsafe_arena_set_allocated_settings( + ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.settings_); + } + _impl_.settings_ = reinterpret_cast<::xtcp_treatment::v1::TCPSettings*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Treatment.settings) +} +inline ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE Treatment::release_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment::v1::TCPSettings* released = _impl_.settings_; + _impl_.settings_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE Treatment::unsafe_arena_release_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Treatment.settings) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment::v1::TCPSettings* temp = _impl_.settings_; + _impl_.settings_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NONNULL Treatment::_internal_mutable_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.settings_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::TCPSettings>(GetArena()); + _impl_.settings_ = reinterpret_cast<::xtcp_treatment::v1::TCPSettings*>(p); + } + return _impl_.settings_; +} +inline ::xtcp_treatment::v1::TCPSettings* PROTOBUF_NONNULL Treatment::mutable_settings() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment::v1::TCPSettings* _msg = _internal_mutable_settings(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Treatment.settings) + return _msg; +} +inline void Treatment::set_allocated_settings(::xtcp_treatment::v1::TCPSettings* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.settings_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.settings_ = reinterpret_cast<::xtcp_treatment::v1::TCPSettings*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Treatment.settings) +} + +// bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; +inline void Treatment::clear_ecn_fabric_verified() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_fabric_verified_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline bool Treatment::ecn_fabric_verified() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Treatment.ecn_fabric_verified) + return _internal_ecn_fabric_verified(); +} +inline void Treatment::set_ecn_fabric_verified(bool value) { + _internal_set_ecn_fabric_verified(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Treatment.ecn_fabric_verified) +} +inline bool Treatment::_internal_ecn_fabric_verified() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.ecn_fabric_verified_; +} +inline void Treatment::_internal_set_ecn_fabric_verified(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_fabric_verified_ = value; +} + +// ------------------------------------------------------------------- + +// Assignment + +// string experiment_id = 2 [json_name = "experimentId", (.buf.validate.field) = { +inline void Assignment::clear_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& Assignment::experiment_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Assignment.experiment_id) + return _internal_experiment_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Assignment::set_experiment_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.experiment_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Assignment.experiment_id) +} +inline ::std::string* PROTOBUF_NONNULL Assignment::mutable_experiment_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_experiment_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Assignment.experiment_id) + return _s; +} +inline const ::std::string& Assignment::_internal_experiment_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.experiment_id_.Get(); +} +inline void Assignment::_internal_set_experiment_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Assignment::_internal_mutable_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.experiment_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Assignment::release_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Assignment.experiment_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.experiment_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.experiment_id_.Set("", GetArena()); + } + return released; +} +inline void Assignment::set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.experiment_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.experiment_id_.IsDefault()) { + _impl_.experiment_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Assignment.experiment_id) +} + +// .xtcp_treatment.v1.Treatment treatment = 3 [json_name = "treatment", (.buf.validate.field) = { +inline bool Assignment::has_treatment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + PROTOBUF_ASSUME(!value || _impl_.treatment_ != nullptr); + return value; +} +inline void Assignment::clear_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.treatment_ != nullptr) _impl_.treatment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::xtcp_treatment::v1::Treatment& Assignment::_internal_treatment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Treatment* p = _impl_.treatment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Treatment>(&::xtcp_treatment::v1::Treatment_globals_); +} +inline const ::xtcp_treatment::v1::Treatment& Assignment::treatment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Assignment.treatment) + return _internal_treatment(); +} +inline void Assignment::unsafe_arena_set_allocated_treatment( + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.treatment_); + } + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Assignment.treatment) +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE Assignment::release_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment::v1::Treatment* released = _impl_.treatment_; + _impl_.treatment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE Assignment::unsafe_arena_release_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Assignment.treatment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment::v1::Treatment* temp = _impl_.treatment_; + _impl_.treatment_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL Assignment::_internal_mutable_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.treatment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Treatment>(GetArena()); + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(p); + } + return _impl_.treatment_; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL Assignment::mutable_treatment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment::v1::Treatment* _msg = _internal_mutable_treatment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Assignment.treatment) + return _msg; +} +inline void Assignment::set_allocated_treatment(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.treatment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Assignment.treatment) +} + +// .xtcp_treatment.v1.AssignmentMode mode = 4 [json_name = "mode", (.buf.validate.field) = { +inline void Assignment::clear_mode() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.mode_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline ::xtcp_treatment::v1::AssignmentMode Assignment::mode() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Assignment.mode) + return _internal_mode(); +} +inline void Assignment::set_mode(::xtcp_treatment::v1::AssignmentMode value) { + _internal_set_mode(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Assignment.mode) +} +inline ::xtcp_treatment::v1::AssignmentMode Assignment::_internal_mode() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment::v1::AssignmentMode>(_impl_.mode_); +} +inline void Assignment::_internal_set_mode(::xtcp_treatment::v1::AssignmentMode value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.mode_ = value; +} + +// .google.protobuf.Timestamp lease_expires_at = 5 [json_name = "leaseExpiresAt"]; +inline bool Assignment::has_lease_expires_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.lease_expires_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Assignment::_internal_lease_expires_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.lease_expires_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Assignment::lease_expires_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Assignment.lease_expires_at) + return _internal_lease_expires_at(); +} +inline void Assignment::unsafe_arena_set_allocated_lease_expires_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.lease_expires_at_); + } + _impl_.lease_expires_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Assignment.lease_expires_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Assignment::release_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* released = _impl_.lease_expires_at_; + _impl_.lease_expires_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Assignment::unsafe_arena_release_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Assignment.lease_expires_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* temp = _impl_.lease_expires_at_; + _impl_.lease_expires_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Assignment::_internal_mutable_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.lease_expires_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.lease_expires_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.lease_expires_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Assignment::mutable_lease_expires_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_lease_expires_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Assignment.lease_expires_at) + return _msg; +} +inline void Assignment::set_allocated_lease_expires_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.lease_expires_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.lease_expires_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Assignment.lease_expires_at) +} + +// .xtcp_treatment.v1.Treatment predecessor = 6 [json_name = "predecessor"]; +inline bool Assignment::has_predecessor() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.predecessor_ != nullptr); + return value; +} +inline void Assignment::clear_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.predecessor_ != nullptr) _impl_.predecessor_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::xtcp_treatment::v1::Treatment& Assignment::_internal_predecessor() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Treatment* p = _impl_.predecessor_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Treatment>(&::xtcp_treatment::v1::Treatment_globals_); +} +inline const ::xtcp_treatment::v1::Treatment& Assignment::predecessor() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Assignment.predecessor) + return _internal_predecessor(); +} +inline void Assignment::unsafe_arena_set_allocated_predecessor( + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.predecessor_); + } + _impl_.predecessor_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Assignment.predecessor) +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE Assignment::release_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Treatment* released = _impl_.predecessor_; + _impl_.predecessor_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE Assignment::unsafe_arena_release_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Assignment.predecessor) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Treatment* temp = _impl_.predecessor_; + _impl_.predecessor_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL Assignment::_internal_mutable_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.predecessor_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Treatment>(GetArena()); + _impl_.predecessor_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(p); + } + return _impl_.predecessor_; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL Assignment::mutable_predecessor() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Treatment* _msg = _internal_mutable_predecessor(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Assignment.predecessor) + return _msg; +} +inline void Assignment::set_allocated_predecessor(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.predecessor_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.predecessor_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Assignment.predecessor) +} + +// uint64 generation = 7 [json_name = "generation", (.buf.validate.field) = { +inline void Assignment::clear_generation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.generation_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline ::uint64_t Assignment::generation() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Assignment.generation) + return _internal_generation(); +} +inline void Assignment::set_generation(::uint64_t value) { + _internal_set_generation(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Assignment.generation) +} +inline ::uint64_t Assignment::_internal_generation() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.generation_; +} +inline void Assignment::_internal_set_generation(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.generation_ = value; +} + +// ------------------------------------------------------------------- + +// DesiredState + +// string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { +inline void DesiredState::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& DesiredState::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.DesiredState.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void DesiredState::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.DesiredState.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL DesiredState::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.DesiredState.agent_id) + return _s; +} +inline const ::std::string& DesiredState::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void DesiredState::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL DesiredState::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE DesiredState::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.DesiredState.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void DesiredState::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.DesiredState.agent_id) +} + +// uint64 revision = 2 [json_name = "revision", (.buf.validate.field) = { +inline void DesiredState::clear_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline ::uint64_t DesiredState::revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.DesiredState.revision) + return _internal_revision(); +} +inline void DesiredState::set_revision(::uint64_t value) { + _internal_set_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.DesiredState.revision) +} +inline ::uint64_t DesiredState::_internal_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.revision_; +} +inline void DesiredState::_internal_set_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = value; +} + +// bool suspended = 3 [json_name = "suspended"]; +inline void DesiredState::clear_suspended() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspended_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline bool DesiredState::suspended() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.DesiredState.suspended) + return _internal_suspended(); +} +inline void DesiredState::set_suspended(bool value) { + _internal_set_suspended(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.DesiredState.suspended) +} +inline bool DesiredState::_internal_suspended() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.suspended_; +} +inline void DesiredState::_internal_set_suspended(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspended_ = value; +} + +// repeated .xtcp_treatment.v1.Assignment assignments = 4 [json_name = "assignments", (.buf.validate.field) = { +inline int DesiredState::_internal_assignments_size() const { + return _internal_assignments().size(); +} +inline int DesiredState::assignments_size() const { + return _internal_assignments_size(); +} +inline void DesiredState::clear_assignments() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.assignments_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::xtcp_treatment::v1::Assignment& DesiredState::assignments(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.DesiredState.assignments) + return _internal_assignments().Get(index); +} +inline ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL DesiredState::mutable_assignments(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.DesiredState.assignments) + return _internal_mutable_assignments()->Mutable(index); +} +inline ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL DesiredState::add_assignments() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::Assignment* _add = + _internal_mutable_assignments()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.DesiredState.assignments) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>& DesiredState::assignments() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.DesiredState.assignments) + return _internal_assignments(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>* PROTOBUF_NONNULL +DesiredState::mutable_assignments() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.DesiredState.assignments) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_assignments(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>& +DesiredState::_internal_assignments() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.assignments_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Assignment>* PROTOBUF_NONNULL +DesiredState::_internal_mutable_assignments() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.assignments_; +} + +// .google.protobuf.Timestamp issued_at = 5 [json_name = "issuedAt", (.buf.validate.field) = { +inline bool DesiredState::has_issued_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.issued_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& DesiredState::_internal_issued_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.issued_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& DesiredState::issued_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.DesiredState.issued_at) + return _internal_issued_at(); +} +inline void DesiredState::unsafe_arena_set_allocated_issued_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.issued_at_); + } + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.DesiredState.issued_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE DesiredState::release_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* released = _impl_.issued_at_; + _impl_.issued_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE DesiredState::unsafe_arena_release_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.DesiredState.issued_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* temp = _impl_.issued_at_; + _impl_.issued_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL DesiredState::_internal_mutable_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.issued_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.issued_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL DesiredState::mutable_issued_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_issued_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.DesiredState.issued_at) + return _msg; +} +inline void DesiredState::set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.issued_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.DesiredState.issued_at) +} + +// ------------------------------------------------------------------- + +// Capabilities + +// string boot_id = 1 [json_name = "bootId", (.buf.validate.field) = { +inline void Capabilities::clear_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.boot_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& Capabilities::boot_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Capabilities.boot_id) + return _internal_boot_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Capabilities::set_boot_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.boot_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Capabilities.boot_id) +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::mutable_boot_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_boot_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Capabilities.boot_id) + return _s; +} +inline const ::std::string& Capabilities::_internal_boot_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.boot_id_.Get(); +} +inline void Capabilities::_internal_set_boot_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.boot_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::_internal_mutable_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.boot_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Capabilities::release_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Capabilities.boot_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.boot_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.boot_id_.Set("", GetArena()); + } + return released; +} +inline void Capabilities::set_allocated_boot_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.boot_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.boot_id_.IsDefault()) { + _impl_.boot_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Capabilities.boot_id) +} + +// string kernel_release = 2 [json_name = "kernelRelease", (.buf.validate.field) = { +inline void Capabilities::clear_kernel_release() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.kernel_release_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& Capabilities::kernel_release() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Capabilities.kernel_release) + return _internal_kernel_release(); +} +template +PROTOBUF_ALWAYS_INLINE void Capabilities::set_kernel_release(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.kernel_release_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Capabilities.kernel_release) +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::mutable_kernel_release() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_kernel_release(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Capabilities.kernel_release) + return _s; +} +inline const ::std::string& Capabilities::_internal_kernel_release() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.kernel_release_.Get(); +} +inline void Capabilities::_internal_set_kernel_release(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.kernel_release_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::_internal_mutable_kernel_release() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.kernel_release_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Capabilities::release_kernel_release() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Capabilities.kernel_release) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.kernel_release_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.kernel_release_.Set("", GetArena()); + } + return released; +} +inline void Capabilities::set_allocated_kernel_release(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.kernel_release_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.kernel_release_.IsDefault()) { + _impl_.kernel_release_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Capabilities.kernel_release) +} + +// repeated string congestion_algorithms = 3 [json_name = "congestionAlgorithms", (.buf.validate.field) = { +inline int Capabilities::_internal_congestion_algorithms_size() const { + return _internal_congestion_algorithms().size(); +} +inline int Capabilities::congestion_algorithms_size() const { + return _internal_congestion_algorithms_size(); +} +inline void Capabilities::clear_congestion_algorithms() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_algorithms_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::add_congestion_algorithms() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::std::string* _s = + _internal_mutable_congestion_algorithms()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add_mutable:xtcp_treatment.v1.Capabilities.congestion_algorithms) + return _s; +} +inline const ::std::string& Capabilities::congestion_algorithms(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Capabilities.congestion_algorithms) + return _internal_congestion_algorithms().Get(index); +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::mutable_congestion_algorithms(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Capabilities.congestion_algorithms) + return _internal_mutable_congestion_algorithms()->Mutable(index); +} +template +inline void Capabilities::set_congestion_algorithms(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_congestion_algorithms()->Mutable(index), + ::std::forward(value), args... ); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Capabilities.congestion_algorithms) +} +template +inline void Capabilities::add_congestion_algorithms(Arg_&& value, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::google::protobuf::internal::AddToRepeatedPtrField( + ::google::protobuf::MessageLite::internal_visibility(), GetArena(), + *_internal_mutable_congestion_algorithms(), ::std::forward(value), + args... ); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.Capabilities.congestion_algorithms) +} +inline const ::google::protobuf::RepeatedPtrField<::std::string>& Capabilities::congestion_algorithms() + const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.Capabilities.congestion_algorithms) + return _internal_congestion_algorithms(); +} +inline ::google::protobuf::RepeatedPtrField<::std::string>* PROTOBUF_NONNULL +Capabilities::mutable_congestion_algorithms() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.Capabilities.congestion_algorithms) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_congestion_algorithms(); +} +inline const ::google::protobuf::RepeatedPtrField<::std::string>& +Capabilities::_internal_congestion_algorithms() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.congestion_algorithms_; +} +inline ::google::protobuf::RepeatedPtrField<::std::string>* PROTOBUF_NONNULL +Capabilities::_internal_mutable_congestion_algorithms() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.congestion_algorithms_; +} + +// bool simple_host_routing = 4 [json_name = "simpleHostRouting"]; +inline void Capabilities::clear_simple_host_routing() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.simple_host_routing_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline bool Capabilities::simple_host_routing() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Capabilities.simple_host_routing) + return _internal_simple_host_routing(); +} +inline void Capabilities::set_simple_host_routing(bool value) { + _internal_set_simple_host_routing(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Capabilities.simple_host_routing) +} +inline bool Capabilities::_internal_simple_host_routing() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.simple_host_routing_; +} +inline void Capabilities::_internal_set_simple_host_routing(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.simple_host_routing_ = value; +} + +// bool actuator_enabled = 5 [json_name = "actuatorEnabled"]; +inline void Capabilities::clear_actuator_enabled() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.actuator_enabled_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline bool Capabilities::actuator_enabled() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Capabilities.actuator_enabled) + return _internal_actuator_enabled(); +} +inline void Capabilities::set_actuator_enabled(bool value) { + _internal_set_actuator_enabled(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Capabilities.actuator_enabled) +} +inline bool Capabilities::_internal_actuator_enabled() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.actuator_enabled_; +} +inline void Capabilities::_internal_set_actuator_enabled(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.actuator_enabled_ = value; +} + +// string collection_id = 6 [json_name = "collectionId", (.buf.validate.field) = { +inline void Capabilities::clear_collection_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.collection_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::std::string& Capabilities::collection_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Capabilities.collection_id) + return _internal_collection_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Capabilities::set_collection_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + _impl_.collection_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Capabilities.collection_id) +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::mutable_collection_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::std::string* _s = _internal_mutable_collection_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Capabilities.collection_id) + return _s; +} +inline const ::std::string& Capabilities::_internal_collection_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.collection_id_.Get(); +} +inline void Capabilities::_internal_set_collection_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.collection_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Capabilities::_internal_mutable_collection_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.collection_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Capabilities::release_collection_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Capabilities.collection_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000008U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + auto* released = _impl_.collection_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.collection_id_.Set("", GetArena()); + } + return released; +} +inline void Capabilities::set_allocated_collection_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + _impl_.collection_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.collection_id_.IsDefault()) { + _impl_.collection_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Capabilities.collection_id) +} + +// ------------------------------------------------------------------- + +// ApplicationRecord + +// .xtcp_treatment.v1.Assignment assignment = 1 [json_name = "assignment", (.buf.validate.field) = { +inline bool ApplicationRecord::has_assignment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.assignment_ != nullptr); + return value; +} +inline void ApplicationRecord::clear_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.assignment_ != nullptr) _impl_.assignment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::xtcp_treatment::v1::Assignment& ApplicationRecord::_internal_assignment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Assignment* p = _impl_.assignment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Assignment>(&::xtcp_treatment::v1::Assignment_globals_); +} +inline const ::xtcp_treatment::v1::Assignment& ApplicationRecord::assignment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.assignment) + return _internal_assignment(); +} +inline void ApplicationRecord::unsafe_arena_set_allocated_assignment( + ::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.assignment_); + } + _impl_.assignment_ = reinterpret_cast<::xtcp_treatment::v1::Assignment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ApplicationRecord.assignment) +} +inline ::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE ApplicationRecord::release_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Assignment* released = _impl_.assignment_; + _impl_.assignment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE ApplicationRecord::unsafe_arena_release_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.assignment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Assignment* temp = _impl_.assignment_; + _impl_.assignment_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.assignment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Assignment>(GetArena()); + _impl_.assignment_ = reinterpret_cast<::xtcp_treatment::v1::Assignment*>(p); + } + return _impl_.assignment_; +} +inline ::xtcp_treatment::v1::Assignment* PROTOBUF_NONNULL ApplicationRecord::mutable_assignment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment::v1::Assignment* _msg = _internal_mutable_assignment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.assignment) + return _msg; +} +inline void ApplicationRecord::set_allocated_assignment(::xtcp_treatment::v1::Assignment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.assignment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.assignment_ = reinterpret_cast<::xtcp_treatment::v1::Assignment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.assignment) +} + +// uint64 desired_revision = 2 [json_name = "desiredRevision"]; +inline void ApplicationRecord::clear_desired_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.desired_revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000200U); +} +inline ::uint64_t ApplicationRecord::desired_revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.desired_revision) + return _internal_desired_revision(); +} +inline void ApplicationRecord::set_desired_revision(::uint64_t value) { + _internal_set_desired_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000200U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ApplicationRecord.desired_revision) +} +inline ::uint64_t ApplicationRecord::_internal_desired_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.desired_revision_; +} +inline void ApplicationRecord::_internal_set_desired_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.desired_revision_ = value; +} + +// .xtcp_treatment.v1.ApplyStatus status = 3 [json_name = "status", (.buf.validate.field) = { +inline void ApplicationRecord::clear_status() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.status_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000400U); +} +inline ::xtcp_treatment::v1::ApplyStatus ApplicationRecord::status() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.status) + return _internal_status(); +} +inline void ApplicationRecord::set_status(::xtcp_treatment::v1::ApplyStatus value) { + _internal_set_status(value); + SetHasBit(_impl_._has_bits_[0], 0x00000400U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ApplicationRecord.status) +} +inline ::xtcp_treatment::v1::ApplyStatus ApplicationRecord::_internal_status() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment::v1::ApplyStatus>(_impl_.status_); +} +inline void ApplicationRecord::_internal_set_status(::xtcp_treatment::v1::ApplyStatus value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.status_ = value; +} + +// .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; +inline bool ApplicationRecord::has_received_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000010U); + PROTOBUF_ASSUME(!value || _impl_.received_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::_internal_received_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.received_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::received_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.received_at) + return _internal_received_at(); +} +inline void ApplicationRecord::unsafe_arena_set_allocated_received_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.received_at_); + } + _impl_.received_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ApplicationRecord.received_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::release_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* released = _impl_.received_at_; + _impl_.received_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::unsafe_arena_release_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.received_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* temp = _impl_.received_at_; + _impl_.received_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.received_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.received_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.received_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::mutable_received_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_received_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.received_at) + return _msg; +} +inline void ApplicationRecord::set_allocated_received_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.received_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + + _impl_.received_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.received_at) +} + +// .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; +inline bool ApplicationRecord::has_attempted_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U); + PROTOBUF_ASSUME(!value || _impl_.attempted_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::_internal_attempted_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.attempted_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::attempted_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.attempted_at) + return _internal_attempted_at(); +} +inline void ApplicationRecord::unsafe_arena_set_allocated_attempted_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attempted_at_); + } + _impl_.attempted_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ApplicationRecord.attempted_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::release_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* released = _impl_.attempted_at_; + _impl_.attempted_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::unsafe_arena_release_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.attempted_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* temp = _impl_.attempted_at_; + _impl_.attempted_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attempted_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.attempted_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.attempted_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::mutable_attempted_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_attempted_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.attempted_at) + return _msg; +} +inline void ApplicationRecord::set_allocated_attempted_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attempted_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + + _impl_.attempted_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.attempted_at) +} + +// .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; +inline bool ApplicationRecord::has_applied_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U); + PROTOBUF_ASSUME(!value || _impl_.applied_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::_internal_applied_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.applied_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::applied_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.applied_at) + return _internal_applied_at(); +} +inline void ApplicationRecord::unsafe_arena_set_allocated_applied_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.applied_at_); + } + _impl_.applied_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ApplicationRecord.applied_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::release_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* released = _impl_.applied_at_; + _impl_.applied_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::unsafe_arena_release_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.applied_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* temp = _impl_.applied_at_; + _impl_.applied_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.applied_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.applied_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.applied_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::mutable_applied_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_applied_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.applied_at) + return _msg; +} +inline void ApplicationRecord::set_allocated_applied_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.applied_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + + _impl_.applied_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.applied_at) +} + +// .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; +inline bool ApplicationRecord::has_verified_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000080U); + PROTOBUF_ASSUME(!value || _impl_.verified_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::_internal_verified_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.verified_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::verified_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.verified_at) + return _internal_verified_at(); +} +inline void ApplicationRecord::unsafe_arena_set_allocated_verified_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.verified_at_); + } + _impl_.verified_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ApplicationRecord.verified_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::release_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* released = _impl_.verified_at_; + _impl_.verified_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::unsafe_arena_release_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.verified_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* temp = _impl_.verified_at_; + _impl_.verified_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.verified_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.verified_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.verified_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::mutable_verified_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_verified_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.verified_at) + return _msg; +} +inline void ApplicationRecord::set_allocated_verified_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.verified_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + + _impl_.verified_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.verified_at) +} + +// .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; +inline bool ApplicationRecord::has_removed_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000100U); + PROTOBUF_ASSUME(!value || _impl_.removed_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::_internal_removed_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.removed_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& ApplicationRecord::removed_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.removed_at) + return _internal_removed_at(); +} +inline void ApplicationRecord::unsafe_arena_set_allocated_removed_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.removed_at_); + } + _impl_.removed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ApplicationRecord.removed_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::release_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* released = _impl_.removed_at_; + _impl_.removed_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE ApplicationRecord::unsafe_arena_release_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.removed_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* temp = _impl_.removed_at_; + _impl_.removed_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.removed_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.removed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.removed_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL ApplicationRecord::mutable_removed_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_removed_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.removed_at) + return _msg; +} +inline void ApplicationRecord::set_allocated_removed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.removed_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + } + + _impl_.removed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.removed_at) +} + +// string error = 9 [json_name = "error", (.buf.validate.field) = { +inline void ApplicationRecord::clear_error() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.error_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& ApplicationRecord::error() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.error) + return _internal_error(); +} +template +PROTOBUF_ALWAYS_INLINE void ApplicationRecord::set_error(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.error_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ApplicationRecord.error) +} +inline ::std::string* PROTOBUF_NONNULL ApplicationRecord::mutable_error() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_error(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.error) + return _s; +} +inline const ::std::string& ApplicationRecord::_internal_error() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.error_.Get(); +} +inline void ApplicationRecord::_internal_set_error(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.error_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_error() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.error_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ApplicationRecord::release_error() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.error) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.error_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.error_.Set("", GetArena()); + } + return released; +} +inline void ApplicationRecord::set_allocated_error(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.error_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.error_.IsDefault()) { + _impl_.error_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.error) +} + +// bytes installed_route = 10 [json_name = "installedRoute", (.buf.validate.field) = { +inline void ApplicationRecord::clear_installed_route() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_route_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& ApplicationRecord::installed_route() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.installed_route) + return _internal_installed_route(); +} +template +PROTOBUF_ALWAYS_INLINE void ApplicationRecord::set_installed_route(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.installed_route_.SetBytes(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ApplicationRecord.installed_route) +} +inline ::std::string* PROTOBUF_NONNULL ApplicationRecord::mutable_installed_route() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_installed_route(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.installed_route) + return _s; +} +inline const ::std::string& ApplicationRecord::_internal_installed_route() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.installed_route_.Get(); +} +inline void ApplicationRecord::_internal_set_installed_route(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_route_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_installed_route() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.installed_route_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ApplicationRecord::release_installed_route() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.installed_route) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.installed_route_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.installed_route_.Set("", GetArena()); + } + return released; +} +inline void ApplicationRecord::set_allocated_installed_route(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.installed_route_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.installed_route_.IsDefault()) { + _impl_.installed_route_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.installed_route) +} + +// string installed_boot_id = 11 [json_name = "installedBootId", (.buf.validate.field) = { +inline void ApplicationRecord::clear_installed_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_boot_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& ApplicationRecord::installed_boot_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.installed_boot_id) + return _internal_installed_boot_id(); +} +template +PROTOBUF_ALWAYS_INLINE void ApplicationRecord::set_installed_boot_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.installed_boot_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ApplicationRecord.installed_boot_id) +} +inline ::std::string* PROTOBUF_NONNULL ApplicationRecord::mutable_installed_boot_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_installed_boot_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ApplicationRecord.installed_boot_id) + return _s; +} +inline const ::std::string& ApplicationRecord::_internal_installed_boot_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.installed_boot_id_.Get(); +} +inline void ApplicationRecord::_internal_set_installed_boot_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_boot_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL ApplicationRecord::_internal_mutable_installed_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.installed_boot_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE ApplicationRecord::release_installed_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ApplicationRecord.installed_boot_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.installed_boot_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.installed_boot_id_.Set("", GetArena()); + } + return released; +} +inline void ApplicationRecord::set_allocated_installed_boot_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.installed_boot_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.installed_boot_id_.IsDefault()) { + _impl_.installed_boot_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ApplicationRecord.installed_boot_id) +} + +// bool expired_latched = 12 [json_name = "expiredLatched"]; +inline void ApplicationRecord::clear_expired_latched() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expired_latched_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000800U); +} +inline bool ApplicationRecord::expired_latched() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ApplicationRecord.expired_latched) + return _internal_expired_latched(); +} +inline void ApplicationRecord::set_expired_latched(bool value) { + _internal_set_expired_latched(value); + SetHasBit(_impl_._has_bits_[0], 0x00000800U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ApplicationRecord.expired_latched) +} +inline bool ApplicationRecord::_internal_expired_latched() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.expired_latched_; +} +inline void ApplicationRecord::_internal_set_expired_latched(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expired_latched_ = value; +} + +// ------------------------------------------------------------------- + +// LocalState + +// .xtcp_treatment.v1.DesiredState desired = 1 [json_name = "desired"]; +inline bool LocalState::has_desired() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.desired_ != nullptr); + return value; +} +inline void LocalState::clear_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ != nullptr) _impl_.desired_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::xtcp_treatment::v1::DesiredState& LocalState::_internal_desired() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::DesiredState* p = _impl_.desired_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::DesiredState>(&::xtcp_treatment::v1::DesiredState_globals_); +} +inline const ::xtcp_treatment::v1::DesiredState& LocalState::desired() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.LocalState.desired) + return _internal_desired(); +} +inline void LocalState::unsafe_arena_set_allocated_desired( + ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.LocalState.desired) +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE LocalState::release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment::v1::DesiredState* released = _impl_.desired_; + _impl_.desired_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE LocalState::unsafe_arena_release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.LocalState.desired) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment::v1::DesiredState* temp = _impl_.desired_; + _impl_.desired_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL LocalState::_internal_mutable_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::DesiredState>(GetArena()); + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(p); + } + return _impl_.desired_; +} +inline ::xtcp_treatment::v1::DesiredState* PROTOBUF_NONNULL LocalState::mutable_desired() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment::v1::DesiredState* _msg = _internal_mutable_desired(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.LocalState.desired) + return _msg; +} +inline void LocalState::set_allocated_desired(::xtcp_treatment::v1::DesiredState* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.desired_ = reinterpret_cast<::xtcp_treatment::v1::DesiredState*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.LocalState.desired) +} + +// bool locally_suspended = 2 [json_name = "locallySuspended"]; +inline void LocalState::clear_locally_suspended() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.locally_suspended_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline bool LocalState::locally_suspended() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.LocalState.locally_suspended) + return _internal_locally_suspended(); +} +inline void LocalState::set_locally_suspended(bool value) { + _internal_set_locally_suspended(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.LocalState.locally_suspended) +} +inline bool LocalState::_internal_locally_suspended() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.locally_suspended_; +} +inline void LocalState::_internal_set_locally_suspended(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.locally_suspended_ = value; +} + +// string suspension_reason = 3 [json_name = "suspensionReason", (.buf.validate.field) = { +inline void LocalState::clear_suspension_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspension_reason_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& LocalState::suspension_reason() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.LocalState.suspension_reason) + return _internal_suspension_reason(); +} +template +PROTOBUF_ALWAYS_INLINE void LocalState::set_suspension_reason(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.suspension_reason_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.LocalState.suspension_reason) +} +inline ::std::string* PROTOBUF_NONNULL LocalState::mutable_suspension_reason() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_suspension_reason(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.LocalState.suspension_reason) + return _s; +} +inline const ::std::string& LocalState::_internal_suspension_reason() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.suspension_reason_.Get(); +} +inline void LocalState::_internal_set_suspension_reason(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspension_reason_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL LocalState::_internal_mutable_suspension_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.suspension_reason_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE LocalState::release_suspension_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.LocalState.suspension_reason) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.suspension_reason_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.suspension_reason_.Set("", GetArena()); + } + return released; +} +inline void LocalState::set_allocated_suspension_reason(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.suspension_reason_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.suspension_reason_.IsDefault()) { + _impl_.suspension_reason_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.LocalState.suspension_reason) +} + +// repeated .xtcp_treatment.v1.ApplicationRecord records = 4 [json_name = "records", (.buf.validate.field) = { +inline int LocalState::_internal_records_size() const { + return _internal_records().size(); +} +inline int LocalState::records_size() const { + return _internal_records_size(); +} +inline void LocalState::clear_records() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.records_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::xtcp_treatment::v1::ApplicationRecord& LocalState::records(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.LocalState.records) + return _internal_records().Get(index); +} +inline ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL LocalState::mutable_records(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.LocalState.records) + return _internal_mutable_records()->Mutable(index); +} +inline ::xtcp_treatment::v1::ApplicationRecord* PROTOBUF_NONNULL LocalState::add_records() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::ApplicationRecord* _add = + _internal_mutable_records()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.LocalState.records) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& LocalState::records() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.LocalState.records) + return _internal_records(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL +LocalState::mutable_records() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.LocalState.records) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_records(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>& +LocalState::_internal_records() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.records_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::ApplicationRecord>* PROTOBUF_NONNULL +LocalState::_internal_mutable_records() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.records_; +} + +// .google.protobuf.Timestamp updated_at = 5 [json_name = "updatedAt"]; +inline bool LocalState::has_updated_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.updated_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& LocalState::_internal_updated_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.updated_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& LocalState::updated_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.LocalState.updated_at) + return _internal_updated_at(); +} +inline void LocalState::unsafe_arena_set_allocated_updated_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.updated_at_); + } + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.LocalState.updated_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE LocalState::release_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::google::protobuf::Timestamp* released = _impl_.updated_at_; + _impl_.updated_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE LocalState::unsafe_arena_release_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.LocalState.updated_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::google::protobuf::Timestamp* temp = _impl_.updated_at_; + _impl_.updated_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL LocalState::_internal_mutable_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.updated_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.updated_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL LocalState::mutable_updated_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_updated_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.LocalState.updated_at) + return _msg; +} +inline void LocalState::set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.updated_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.LocalState.updated_at) +} + +// ------------------------------------------------------------------- + +// HostEvidence + +// string agent_id = 1 [json_name = "agentId", (.buf.validate.field) = { +inline void HostEvidence::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& HostEvidence::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void HostEvidence::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL HostEvidence::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.HostEvidence.agent_id) + return _s; +} +inline const ::std::string& HostEvidence::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void HostEvidence::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL HostEvidence::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE HostEvidence::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.HostEvidence.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void HostEvidence::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.HostEvidence.agent_id) +} + +// uint64 sockets = 2 [json_name = "sockets"]; +inline void HostEvidence::clear_sockets() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sockets_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline ::uint64_t HostEvidence::sockets() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.sockets) + return _internal_sockets(); +} +inline void HostEvidence::set_sockets(::uint64_t value) { + _internal_set_sockets(value); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.sockets) +} +inline ::uint64_t HostEvidence::_internal_sockets() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.sockets_; +} +inline void HostEvidence::_internal_set_sockets(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.sockets_ = value; +} + +// uint64 bytes_acked = 3 [json_name = "bytesAcked"]; +inline void HostEvidence::clear_bytes_acked() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.bytes_acked_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline ::uint64_t HostEvidence::bytes_acked() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.bytes_acked) + return _internal_bytes_acked(); +} +inline void HostEvidence::set_bytes_acked(::uint64_t value) { + _internal_set_bytes_acked(value); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.bytes_acked) +} +inline ::uint64_t HostEvidence::_internal_bytes_acked() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.bytes_acked_; +} +inline void HostEvidence::_internal_set_bytes_acked(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.bytes_acked_ = value; +} + +// double goodput_bps = 4 [json_name = "goodputBps", (.buf.validate.field) = { +inline void HostEvidence::clear_goodput_bps() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.goodput_bps_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline double HostEvidence::goodput_bps() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.goodput_bps) + return _internal_goodput_bps(); +} +inline void HostEvidence::set_goodput_bps(double value) { + _internal_set_goodput_bps(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.goodput_bps) +} +inline double HostEvidence::_internal_goodput_bps() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.goodput_bps_; +} +inline void HostEvidence::_internal_set_goodput_bps(double value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.goodput_bps_ = value; +} + +// double retransmission_ratio = 5 [json_name = "retransmissionRatio", (.buf.validate.field) = { +inline void HostEvidence::clear_retransmission_ratio() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.retransmission_ratio_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline double HostEvidence::retransmission_ratio() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.retransmission_ratio) + return _internal_retransmission_ratio(); +} +inline void HostEvidence::set_retransmission_ratio(double value) { + _internal_set_retransmission_ratio(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.retransmission_ratio) +} +inline double HostEvidence::_internal_retransmission_ratio() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.retransmission_ratio_; +} +inline void HostEvidence::_internal_set_retransmission_ratio(double value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.retransmission_ratio_ = value; +} + +// double rtt_p95_ms = 6 [json_name = "rttP95Ms", (.buf.validate.field) = { +inline void HostEvidence::clear_rtt_p95_ms() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rtt_p95_ms_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline double HostEvidence::rtt_p95_ms() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.rtt_p95_ms) + return _internal_rtt_p95_ms(); +} +inline void HostEvidence::set_rtt_p95_ms(double value) { + _internal_set_rtt_p95_ms(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.rtt_p95_ms) +} +inline double HostEvidence::_internal_rtt_p95_ms() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.rtt_p95_ms_; +} +inline void HostEvidence::_internal_set_rtt_p95_ms(double value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rtt_p95_ms_ = value; +} + +// uint64 exposed_sockets = 7 [json_name = "exposedSockets"]; +inline void HostEvidence::clear_exposed_sockets() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.exposed_sockets_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline ::uint64_t HostEvidence::exposed_sockets() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.exposed_sockets) + return _internal_exposed_sockets(); +} +inline void HostEvidence::set_exposed_sockets(::uint64_t value) { + _internal_set_exposed_sockets(value); + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.exposed_sockets) +} +inline ::uint64_t HostEvidence::_internal_exposed_sockets() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.exposed_sockets_; +} +inline void HostEvidence::_internal_set_exposed_sockets(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.exposed_sockets_ = value; +} + +// bool collection_healthy = 8 [json_name = "collectionHealthy"]; +inline void HostEvidence::clear_collection_healthy() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.collection_healthy_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); +} +inline bool HostEvidence::collection_healthy() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.collection_healthy) + return _internal_collection_healthy(); +} +inline void HostEvidence::set_collection_healthy(bool value) { + _internal_set_collection_healthy(value); + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.collection_healthy) +} +inline bool HostEvidence::_internal_collection_healthy() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.collection_healthy_; +} +inline void HostEvidence::_internal_set_collection_healthy(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.collection_healthy_ = value; +} + +// uint64 unbound_sockets = 9 [json_name = "unboundSockets"]; +inline void HostEvidence::clear_unbound_sockets() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.unbound_sockets_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +inline ::uint64_t HostEvidence::unbound_sockets() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.HostEvidence.unbound_sockets) + return _internal_unbound_sockets(); +} +inline void HostEvidence::set_unbound_sockets(::uint64_t value) { + _internal_set_unbound_sockets(value); + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.HostEvidence.unbound_sockets) +} +inline ::uint64_t HostEvidence::_internal_unbound_sockets() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.unbound_sockets_; +} +inline void HostEvidence::_internal_set_unbound_sockets(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.unbound_sockets_ = value; +} + +// ------------------------------------------------------------------- + +// Evidence + +// string id = 1 [json_name = "id", (.buf.validate.field) = { +inline void Evidence::clear_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& Evidence::id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.id) + return _internal_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Evidence::set_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Evidence.id) +} +inline ::std::string* PROTOBUF_NONNULL Evidence::mutable_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.id) + return _s; +} +inline const ::std::string& Evidence::_internal_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.id_.Get(); +} +inline void Evidence::_internal_set_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Evidence::_internal_mutable_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Evidence::release_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Evidence.id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.id_.Set("", GetArena()); + } + return released; +} +inline void Evidence::set_allocated_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.id_.IsDefault()) { + _impl_.id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Evidence.id) +} + +// .google.protobuf.Timestamp analyzed_at = 2 [json_name = "analyzedAt", (.buf.validate.field) = { +inline bool Evidence::has_analyzed_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U); + PROTOBUF_ASSUME(!value || _impl_.analyzed_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Evidence::_internal_analyzed_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.analyzed_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Evidence::analyzed_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.analyzed_at) + return _internal_analyzed_at(); +} +inline void Evidence::unsafe_arena_set_allocated_analyzed_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.analyzed_at_); + } + _impl_.analyzed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Evidence.analyzed_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Evidence::release_analyzed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* released = _impl_.analyzed_at_; + _impl_.analyzed_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Evidence::unsafe_arena_release_analyzed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Evidence.analyzed_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* temp = _impl_.analyzed_at_; + _impl_.analyzed_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Evidence::_internal_mutable_analyzed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.analyzed_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.analyzed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.analyzed_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Evidence::mutable_analyzed_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_analyzed_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.analyzed_at) + return _msg; +} +inline void Evidence::set_allocated_analyzed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.analyzed_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + + _impl_.analyzed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Evidence.analyzed_at) +} + +// .google.protobuf.Timestamp window_start = 3 [json_name = "windowStart", (.buf.validate.field) = { +inline bool Evidence::has_window_start() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U); + PROTOBUF_ASSUME(!value || _impl_.window_start_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Evidence::_internal_window_start() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.window_start_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Evidence::window_start() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.window_start) + return _internal_window_start(); +} +inline void Evidence::unsafe_arena_set_allocated_window_start( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.window_start_); + } + _impl_.window_start_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Evidence.window_start) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Evidence::release_window_start() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* released = _impl_.window_start_; + _impl_.window_start_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Evidence::unsafe_arena_release_window_start() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Evidence.window_start) + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* temp = _impl_.window_start_; + _impl_.window_start_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Evidence::_internal_mutable_window_start() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.window_start_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.window_start_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.window_start_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Evidence::mutable_window_start() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_window_start(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.window_start) + return _msg; +} +inline void Evidence::set_allocated_window_start(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.window_start_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + + _impl_.window_start_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Evidence.window_start) +} + +// .google.protobuf.Timestamp window_end = 4 [json_name = "windowEnd", (.buf.validate.field) = { +inline bool Evidence::has_window_end() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000080U); + PROTOBUF_ASSUME(!value || _impl_.window_end_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Evidence::_internal_window_end() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.window_end_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Evidence::window_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.window_end) + return _internal_window_end(); +} +inline void Evidence::unsafe_arena_set_allocated_window_end( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.window_end_); + } + _impl_.window_end_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Evidence.window_end) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Evidence::release_window_end() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* released = _impl_.window_end_; + _impl_.window_end_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Evidence::unsafe_arena_release_window_end() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Evidence.window_end) + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* temp = _impl_.window_end_; + _impl_.window_end_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Evidence::_internal_mutable_window_end() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.window_end_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.window_end_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.window_end_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Evidence::mutable_window_end() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_window_end(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.window_end) + return _msg; +} +inline void Evidence::set_allocated_window_end(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.window_end_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + + _impl_.window_end_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Evidence.window_end) +} + +// string query_version = 5 [json_name = "queryVersion", (.buf.validate.field) = { +inline void Evidence::clear_query_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.query_version_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& Evidence::query_version() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.query_version) + return _internal_query_version(); +} +template +PROTOBUF_ALWAYS_INLINE void Evidence::set_query_version(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.query_version_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Evidence.query_version) +} +inline ::std::string* PROTOBUF_NONNULL Evidence::mutable_query_version() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_query_version(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.query_version) + return _s; +} +inline const ::std::string& Evidence::_internal_query_version() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.query_version_.Get(); +} +inline void Evidence::_internal_set_query_version(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.query_version_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Evidence::_internal_mutable_query_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.query_version_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Evidence::release_query_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Evidence.query_version) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.query_version_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.query_version_.Set("", GetArena()); + } + return released; +} +inline void Evidence::set_allocated_query_version(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.query_version_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.query_version_.IsDefault()) { + _impl_.query_version_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Evidence.query_version) +} + +// string enrichment_version = 6 [json_name = "enrichmentVersion", (.buf.validate.field) = { +inline void Evidence::clear_enrichment_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.enrichment_version_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::std::string& Evidence::enrichment_version() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.enrichment_version) + return _internal_enrichment_version(); +} +template +PROTOBUF_ALWAYS_INLINE void Evidence::set_enrichment_version(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + _impl_.enrichment_version_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Evidence.enrichment_version) +} +inline ::std::string* PROTOBUF_NONNULL Evidence::mutable_enrichment_version() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::std::string* _s = _internal_mutable_enrichment_version(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.enrichment_version) + return _s; +} +inline const ::std::string& Evidence::_internal_enrichment_version() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.enrichment_version_.Get(); +} +inline void Evidence::_internal_set_enrichment_version(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.enrichment_version_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Evidence::_internal_mutable_enrichment_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.enrichment_version_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Evidence::release_enrichment_version() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Evidence.enrichment_version) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000008U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + auto* released = _impl_.enrichment_version_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.enrichment_version_.Set("", GetArena()); + } + return released; +} +inline void Evidence::set_allocated_enrichment_version(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + _impl_.enrichment_version_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.enrichment_version_.IsDefault()) { + _impl_.enrichment_version_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Evidence.enrichment_version) +} + +// repeated .xtcp_treatment.v1.HostEvidence hosts = 7 [json_name = "hosts", (.buf.validate.field) = { +inline int Evidence::_internal_hosts_size() const { + return _internal_hosts().size(); +} +inline int Evidence::hosts_size() const { + return _internal_hosts_size(); +} +inline void Evidence::clear_hosts() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.hosts_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::xtcp_treatment::v1::HostEvidence& Evidence::hosts(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.hosts) + return _internal_hosts().Get(index); +} +inline ::xtcp_treatment::v1::HostEvidence* PROTOBUF_NONNULL Evidence::mutable_hosts(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.hosts) + return _internal_mutable_hosts()->Mutable(index); +} +inline ::xtcp_treatment::v1::HostEvidence* PROTOBUF_NONNULL Evidence::add_hosts() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::HostEvidence* _add = + _internal_mutable_hosts()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.Evidence.hosts) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>& Evidence::hosts() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.Evidence.hosts) + return _internal_hosts(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>* PROTOBUF_NONNULL +Evidence::mutable_hosts() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.Evidence.hosts) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_hosts(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>& +Evidence::_internal_hosts() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.hosts_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::HostEvidence>* PROTOBUF_NONNULL +Evidence::_internal_mutable_hosts() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.hosts_; +} + +// string artifact_sha256 = 8 [json_name = "artifactSha256", (.buf.validate.field) = { +inline void Evidence::clear_artifact_sha256() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.artifact_sha256_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline const ::std::string& Evidence::artifact_sha256() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Evidence.artifact_sha256) + return _internal_artifact_sha256(); +} +template +PROTOBUF_ALWAYS_INLINE void Evidence::set_artifact_sha256(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + _impl_.artifact_sha256_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Evidence.artifact_sha256) +} +inline ::std::string* PROTOBUF_NONNULL Evidence::mutable_artifact_sha256() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + ::std::string* _s = _internal_mutable_artifact_sha256(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Evidence.artifact_sha256) + return _s; +} +inline const ::std::string& Evidence::_internal_artifact_sha256() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.artifact_sha256_.Get(); +} +inline void Evidence::_internal_set_artifact_sha256(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.artifact_sha256_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Evidence::_internal_mutable_artifact_sha256() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.artifact_sha256_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Evidence::release_artifact_sha256() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Evidence.artifact_sha256) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000010U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + auto* released = _impl_.artifact_sha256_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.artifact_sha256_.Set("", GetArena()); + } + return released; +} +inline void Evidence::set_allocated_artifact_sha256(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + _impl_.artifact_sha256_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.artifact_sha256_.IsDefault()) { + _impl_.artifact_sha256_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Evidence.artifact_sha256) +} + +// ------------------------------------------------------------------- + +// ExperimentPolicy + +// .google.protobuf.Duration minimum_observation = 1 [json_name = "minimumObservation", (.buf.validate.field) = { +inline bool ExperimentPolicy::has_minimum_observation() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + PROTOBUF_ASSUME(!value || _impl_.minimum_observation_ != nullptr); + return value; +} +inline const ::google::protobuf::Duration& ExperimentPolicy::_internal_minimum_observation() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Duration* p = _impl_.minimum_observation_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Duration>(&::google::protobuf::Duration_globals_); +} +inline const ::google::protobuf::Duration& ExperimentPolicy::minimum_observation() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.minimum_observation) + return _internal_minimum_observation(); +} +inline void ExperimentPolicy::unsafe_arena_set_allocated_minimum_observation( + ::google::protobuf::Duration* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.minimum_observation_); + } + _impl_.minimum_observation_ = reinterpret_cast<::google::protobuf::Duration*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ExperimentPolicy.minimum_observation) +} +inline ::google::protobuf::Duration* PROTOBUF_NULLABLE ExperimentPolicy::release_minimum_observation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::google::protobuf::Duration* released = _impl_.minimum_observation_; + _impl_.minimum_observation_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Duration* PROTOBUF_NULLABLE ExperimentPolicy::unsafe_arena_release_minimum_observation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ExperimentPolicy.minimum_observation) + + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + ::google::protobuf::Duration* temp = _impl_.minimum_observation_; + _impl_.minimum_observation_ = nullptr; + return temp; +} +inline ::google::protobuf::Duration* PROTOBUF_NONNULL ExperimentPolicy::_internal_mutable_minimum_observation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.minimum_observation_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Duration>(GetArena()); + _impl_.minimum_observation_ = reinterpret_cast<::google::protobuf::Duration*>(p); + } + return _impl_.minimum_observation_; +} +inline ::google::protobuf::Duration* PROTOBUF_NONNULL ExperimentPolicy::mutable_minimum_observation() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::google::protobuf::Duration* _msg = _internal_mutable_minimum_observation(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ExperimentPolicy.minimum_observation) + return _msg; +} +inline void ExperimentPolicy::set_allocated_minimum_observation(::google::protobuf::Duration* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.minimum_observation_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + + _impl_.minimum_observation_ = reinterpret_cast<::google::protobuf::Duration*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ExperimentPolicy.minimum_observation) +} + +// .google.protobuf.Duration maximum_phase = 2 [json_name = "maximumPhase", (.buf.validate.field) = { +inline bool ExperimentPolicy::has_maximum_phase() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + PROTOBUF_ASSUME(!value || _impl_.maximum_phase_ != nullptr); + return value; +} +inline const ::google::protobuf::Duration& ExperimentPolicy::_internal_maximum_phase() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Duration* p = _impl_.maximum_phase_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Duration>(&::google::protobuf::Duration_globals_); +} +inline const ::google::protobuf::Duration& ExperimentPolicy::maximum_phase() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.maximum_phase) + return _internal_maximum_phase(); +} +inline void ExperimentPolicy::unsafe_arena_set_allocated_maximum_phase( + ::google::protobuf::Duration* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.maximum_phase_); + } + _impl_.maximum_phase_ = reinterpret_cast<::google::protobuf::Duration*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ExperimentPolicy.maximum_phase) +} +inline ::google::protobuf::Duration* PROTOBUF_NULLABLE ExperimentPolicy::release_maximum_phase() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::google::protobuf::Duration* released = _impl_.maximum_phase_; + _impl_.maximum_phase_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Duration* PROTOBUF_NULLABLE ExperimentPolicy::unsafe_arena_release_maximum_phase() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ExperimentPolicy.maximum_phase) + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::google::protobuf::Duration* temp = _impl_.maximum_phase_; + _impl_.maximum_phase_ = nullptr; + return temp; +} +inline ::google::protobuf::Duration* PROTOBUF_NONNULL ExperimentPolicy::_internal_mutable_maximum_phase() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.maximum_phase_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Duration>(GetArena()); + _impl_.maximum_phase_ = reinterpret_cast<::google::protobuf::Duration*>(p); + } + return _impl_.maximum_phase_; +} +inline ::google::protobuf::Duration* PROTOBUF_NONNULL ExperimentPolicy::mutable_maximum_phase() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::google::protobuf::Duration* _msg = _internal_mutable_maximum_phase(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ExperimentPolicy.maximum_phase) + return _msg; +} +inline void ExperimentPolicy::set_allocated_maximum_phase(::google::protobuf::Duration* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.maximum_phase_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + + _impl_.maximum_phase_ = reinterpret_cast<::google::protobuf::Duration*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ExperimentPolicy.maximum_phase) +} + +// uint64 minimum_sockets_per_host = 3 [json_name = "minimumSocketsPerHost", (.buf.validate.field) = { +inline void ExperimentPolicy::clear_minimum_sockets_per_host() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_sockets_per_host_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline ::uint64_t ExperimentPolicy::minimum_sockets_per_host() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.minimum_sockets_per_host) + return _internal_minimum_sockets_per_host(); +} +inline void ExperimentPolicy::set_minimum_sockets_per_host(::uint64_t value) { + _internal_set_minimum_sockets_per_host(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ExperimentPolicy.minimum_sockets_per_host) +} +inline ::uint64_t ExperimentPolicy::_internal_minimum_sockets_per_host() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.minimum_sockets_per_host_; +} +inline void ExperimentPolicy::_internal_set_minimum_sockets_per_host(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_sockets_per_host_ = value; +} + +// uint64 minimum_bytes_per_host = 4 [json_name = "minimumBytesPerHost", (.buf.validate.field) = { +inline void ExperimentPolicy::clear_minimum_bytes_per_host() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_bytes_per_host_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline ::uint64_t ExperimentPolicy::minimum_bytes_per_host() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.minimum_bytes_per_host) + return _internal_minimum_bytes_per_host(); +} +inline void ExperimentPolicy::set_minimum_bytes_per_host(::uint64_t value) { + _internal_set_minimum_bytes_per_host(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ExperimentPolicy.minimum_bytes_per_host) +} +inline ::uint64_t ExperimentPolicy::_internal_minimum_bytes_per_host() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.minimum_bytes_per_host_; +} +inline void ExperimentPolicy::_internal_set_minimum_bytes_per_host(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_bytes_per_host_ = value; +} + +// uint32 minimum_treated_hosts = 5 [json_name = "minimumTreatedHosts", (.buf.validate.field) = { +inline void ExperimentPolicy::clear_minimum_treated_hosts() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_treated_hosts_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); +} +inline ::uint32_t ExperimentPolicy::minimum_treated_hosts() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.minimum_treated_hosts) + return _internal_minimum_treated_hosts(); +} +inline void ExperimentPolicy::set_minimum_treated_hosts(::uint32_t value) { + _internal_set_minimum_treated_hosts(value); + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ExperimentPolicy.minimum_treated_hosts) +} +inline ::uint32_t ExperimentPolicy::_internal_minimum_treated_hosts() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.minimum_treated_hosts_; +} +inline void ExperimentPolicy::_internal_set_minimum_treated_hosts(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_treated_hosts_ = value; +} + +// double minimum_improvement = 6 [json_name = "minimumImprovement", (.buf.validate.field) = { +inline void ExperimentPolicy::clear_minimum_improvement() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_improvement_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline double ExperimentPolicy::minimum_improvement() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.minimum_improvement) + return _internal_minimum_improvement(); +} +inline void ExperimentPolicy::set_minimum_improvement(double value) { + _internal_set_minimum_improvement(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ExperimentPolicy.minimum_improvement) +} +inline double ExperimentPolicy::_internal_minimum_improvement() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.minimum_improvement_; +} +inline void ExperimentPolicy::_internal_set_minimum_improvement(double value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.minimum_improvement_ = value; +} + +// double maximum_retransmission_increase = 7 [json_name = "maximumRetransmissionIncrease", (.buf.validate.field) = { +inline void ExperimentPolicy::clear_maximum_retransmission_increase() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.maximum_retransmission_increase_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline double ExperimentPolicy::maximum_retransmission_increase() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.maximum_retransmission_increase) + return _internal_maximum_retransmission_increase(); +} +inline void ExperimentPolicy::set_maximum_retransmission_increase(double value) { + _internal_set_maximum_retransmission_increase(value); + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ExperimentPolicy.maximum_retransmission_increase) +} +inline double ExperimentPolicy::_internal_maximum_retransmission_increase() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.maximum_retransmission_increase_; +} +inline void ExperimentPolicy::_internal_set_maximum_retransmission_increase(double value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.maximum_retransmission_increase_ = value; +} + +// double maximum_rtt_increase = 8 [json_name = "maximumRttIncrease", (.buf.validate.field) = { +inline void ExperimentPolicy::clear_maximum_rtt_increase() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.maximum_rtt_increase_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +inline double ExperimentPolicy::maximum_rtt_increase() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.maximum_rtt_increase) + return _internal_maximum_rtt_increase(); +} +inline void ExperimentPolicy::set_maximum_rtt_increase(double value) { + _internal_set_maximum_rtt_increase(value); + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.ExperimentPolicy.maximum_rtt_increase) +} +inline double ExperimentPolicy::_internal_maximum_rtt_increase() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.maximum_rtt_increase_; +} +inline void ExperimentPolicy::_internal_set_maximum_rtt_increase(double value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.maximum_rtt_increase_ = value; +} + +// .google.protobuf.Duration maximum_evidence_age = 9 [json_name = "maximumEvidenceAge", (.buf.validate.field) = { +inline bool ExperimentPolicy::has_maximum_evidence_age() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.maximum_evidence_age_ != nullptr); + return value; +} +inline const ::google::protobuf::Duration& ExperimentPolicy::_internal_maximum_evidence_age() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Duration* p = _impl_.maximum_evidence_age_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Duration>(&::google::protobuf::Duration_globals_); +} +inline const ::google::protobuf::Duration& ExperimentPolicy::maximum_evidence_age() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.ExperimentPolicy.maximum_evidence_age) + return _internal_maximum_evidence_age(); +} +inline void ExperimentPolicy::unsafe_arena_set_allocated_maximum_evidence_age( + ::google::protobuf::Duration* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.maximum_evidence_age_); + } + _impl_.maximum_evidence_age_ = reinterpret_cast<::google::protobuf::Duration*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.ExperimentPolicy.maximum_evidence_age) +} +inline ::google::protobuf::Duration* PROTOBUF_NULLABLE ExperimentPolicy::release_maximum_evidence_age() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Duration* released = _impl_.maximum_evidence_age_; + _impl_.maximum_evidence_age_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Duration* PROTOBUF_NULLABLE ExperimentPolicy::unsafe_arena_release_maximum_evidence_age() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.ExperimentPolicy.maximum_evidence_age) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Duration* temp = _impl_.maximum_evidence_age_; + _impl_.maximum_evidence_age_ = nullptr; + return temp; +} +inline ::google::protobuf::Duration* PROTOBUF_NONNULL ExperimentPolicy::_internal_mutable_maximum_evidence_age() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.maximum_evidence_age_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Duration>(GetArena()); + _impl_.maximum_evidence_age_ = reinterpret_cast<::google::protobuf::Duration*>(p); + } + return _impl_.maximum_evidence_age_; +} +inline ::google::protobuf::Duration* PROTOBUF_NONNULL ExperimentPolicy::mutable_maximum_evidence_age() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Duration* _msg = _internal_mutable_maximum_evidence_age(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.ExperimentPolicy.maximum_evidence_age) + return _msg; +} +inline void ExperimentPolicy::set_allocated_maximum_evidence_age(::google::protobuf::Duration* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.maximum_evidence_age_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.maximum_evidence_age_ = reinterpret_cast<::google::protobuf::Duration*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.ExperimentPolicy.maximum_evidence_age) +} + +// ------------------------------------------------------------------- + +// Phase + +// uint32 target_hosts = 1 [json_name = "targetHosts", (.buf.validate.field) = { +inline void Phase::clear_target_hosts() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.target_hosts_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline ::uint32_t Phase::target_hosts() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.target_hosts) + return _internal_target_hosts(); +} +inline void Phase::set_target_hosts(::uint32_t value) { + _internal_set_target_hosts(value); + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Phase.target_hosts) +} +inline ::uint32_t Phase::_internal_target_hosts() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.target_hosts_; +} +inline void Phase::_internal_set_target_hosts(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.target_hosts_ = value; +} + +// .google.protobuf.Timestamp issued_at = 2 [json_name = "issuedAt"]; +inline bool Phase::has_issued_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.issued_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Phase::_internal_issued_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.issued_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Phase::issued_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.issued_at) + return _internal_issued_at(); +} +inline void Phase::unsafe_arena_set_allocated_issued_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.issued_at_); + } + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Phase.issued_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Phase::release_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* released = _impl_.issued_at_; + _impl_.issued_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Phase::unsafe_arena_release_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Phase.issued_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* temp = _impl_.issued_at_; + _impl_.issued_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Phase::_internal_mutable_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.issued_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.issued_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Phase::mutable_issued_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_issued_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Phase.issued_at) + return _msg; +} +inline void Phase::set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.issued_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Phase.issued_at) +} + +// .google.protobuf.Timestamp observation_started_at = 3 [json_name = "observationStartedAt"]; +inline bool Phase::has_observation_started_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.observation_started_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Phase::_internal_observation_started_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.observation_started_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Phase::observation_started_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.observation_started_at) + return _internal_observation_started_at(); +} +inline void Phase::unsafe_arena_set_allocated_observation_started_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.observation_started_at_); + } + _impl_.observation_started_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Phase.observation_started_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Phase::release_observation_started_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::google::protobuf::Timestamp* released = _impl_.observation_started_at_; + _impl_.observation_started_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Phase::unsafe_arena_release_observation_started_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Phase.observation_started_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::google::protobuf::Timestamp* temp = _impl_.observation_started_at_; + _impl_.observation_started_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Phase::_internal_mutable_observation_started_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.observation_started_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.observation_started_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.observation_started_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Phase::mutable_observation_started_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_observation_started_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Phase.observation_started_at) + return _msg; +} +inline void Phase::set_allocated_observation_started_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.observation_started_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.observation_started_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Phase.observation_started_at) +} + +// .google.protobuf.Timestamp evaluated_at = 4 [json_name = "evaluatedAt"]; +inline bool Phase::has_evaluated_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000010U); + PROTOBUF_ASSUME(!value || _impl_.evaluated_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Phase::_internal_evaluated_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.evaluated_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Phase::evaluated_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.evaluated_at) + return _internal_evaluated_at(); +} +inline void Phase::unsafe_arena_set_allocated_evaluated_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evaluated_at_); + } + _impl_.evaluated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Phase.evaluated_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Phase::release_evaluated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* released = _impl_.evaluated_at_; + _impl_.evaluated_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Phase::unsafe_arena_release_evaluated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Phase.evaluated_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* temp = _impl_.evaluated_at_; + _impl_.evaluated_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Phase::_internal_mutable_evaluated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evaluated_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.evaluated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.evaluated_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Phase::mutable_evaluated_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_evaluated_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Phase.evaluated_at) + return _msg; +} +inline void Phase::set_allocated_evaluated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evaluated_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + + _impl_.evaluated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Phase.evaluated_at) +} + +// .xtcp_treatment.v1.Evidence evidence = 5 [json_name = "evidence"]; +inline bool Phase::has_evidence() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U); + PROTOBUF_ASSUME(!value || _impl_.evidence_ != nullptr); + return value; +} +inline void Phase::clear_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evidence_ != nullptr) _impl_.evidence_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline const ::xtcp_treatment::v1::Evidence& Phase::_internal_evidence() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Evidence* p = _impl_.evidence_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Evidence>(&::xtcp_treatment::v1::Evidence_globals_); +} +inline const ::xtcp_treatment::v1::Evidence& Phase::evidence() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.evidence) + return _internal_evidence(); +} +inline void Phase::unsafe_arena_set_allocated_evidence( + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evidence_); + } + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Phase.evidence) +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE Phase::release_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::xtcp_treatment::v1::Evidence* released = _impl_.evidence_; + _impl_.evidence_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE Phase::unsafe_arena_release_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Phase.evidence) + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::xtcp_treatment::v1::Evidence* temp = _impl_.evidence_; + _impl_.evidence_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL Phase::_internal_mutable_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.evidence_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Evidence>(GetArena()); + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(p); + } + return _impl_.evidence_; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL Phase::mutable_evidence() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + ::xtcp_treatment::v1::Evidence* _msg = _internal_mutable_evidence(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Phase.evidence) + return _msg; +} +inline void Phase::set_allocated_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.evidence_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + + _impl_.evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Phase.evidence) +} + +// .xtcp_treatment.v1.Outcome outcome = 6 [json_name = "outcome", (.buf.validate.field) = { +inline void Phase::clear_outcome() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.outcome_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +inline ::xtcp_treatment::v1::Outcome Phase::outcome() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.outcome) + return _internal_outcome(); +} +inline void Phase::set_outcome(::xtcp_treatment::v1::Outcome value) { + _internal_set_outcome(value); + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Phase.outcome) +} +inline ::xtcp_treatment::v1::Outcome Phase::_internal_outcome() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment::v1::Outcome>(_impl_.outcome_); +} +inline void Phase::_internal_set_outcome(::xtcp_treatment::v1::Outcome value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.outcome_ = value; +} + +// string reviewer = 7 [json_name = "reviewer", (.buf.validate.field) = { +inline void Phase::clear_reviewer() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reviewer_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& Phase::reviewer() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.reviewer) + return _internal_reviewer(); +} +template +PROTOBUF_ALWAYS_INLINE void Phase::set_reviewer(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.reviewer_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Phase.reviewer) +} +inline ::std::string* PROTOBUF_NONNULL Phase::mutable_reviewer() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_reviewer(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Phase.reviewer) + return _s; +} +inline const ::std::string& Phase::_internal_reviewer() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.reviewer_.Get(); +} +inline void Phase::_internal_set_reviewer(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reviewer_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Phase::_internal_mutable_reviewer() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.reviewer_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Phase::release_reviewer() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Phase.reviewer) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.reviewer_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.reviewer_.Set("", GetArena()); + } + return released; +} +inline void Phase::set_allocated_reviewer(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.reviewer_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.reviewer_.IsDefault()) { + _impl_.reviewer_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Phase.reviewer) +} + +// string reason = 8 [json_name = "reason", (.buf.validate.field) = { +inline void Phase::clear_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reason_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& Phase::reason() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Phase.reason) + return _internal_reason(); +} +template +PROTOBUF_ALWAYS_INLINE void Phase::set_reason(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.reason_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Phase.reason) +} +inline ::std::string* PROTOBUF_NONNULL Phase::mutable_reason() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_reason(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Phase.reason) + return _s; +} +inline const ::std::string& Phase::_internal_reason() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.reason_.Get(); +} +inline void Phase::_internal_set_reason(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.reason_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Phase::_internal_mutable_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.reason_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Phase::release_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Phase.reason) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.reason_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.reason_.Set("", GetArena()); + } + return released; +} +inline void Phase::set_allocated_reason(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.reason_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.reason_.IsDefault()) { + _impl_.reason_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Phase.reason) +} + +// ------------------------------------------------------------------- + +// Experiment + +// string id = 1 [json_name = "id", (.buf.validate.field) = { +inline void Experiment::clear_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& Experiment::id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.id) + return _internal_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Experiment::set_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Experiment.id) +} +inline ::std::string* PROTOBUF_NONNULL Experiment::mutable_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.id) + return _s; +} +inline const ::std::string& Experiment::_internal_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.id_.Get(); +} +inline void Experiment::_internal_set_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Experiment::_internal_mutable_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Experiment::release_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.id_.Set("", GetArena()); + } + return released; +} +inline void Experiment::set_allocated_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.id_.IsDefault()) { + _impl_.id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.id) +} + +// string location = 2 [json_name = "location", (.buf.validate.field) = { +inline void Experiment::clear_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::std::string& Experiment::location() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.location) + return _internal_location(); +} +template +PROTOBUF_ALWAYS_INLINE void Experiment::set_location(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + _impl_.location_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Experiment.location) +} +inline ::std::string* PROTOBUF_NONNULL Experiment::mutable_location() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::std::string* _s = _internal_mutable_location(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.location) + return _s; +} +inline const ::std::string& Experiment::_internal_location() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.location_.Get(); +} +inline void Experiment::_internal_set_location(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Experiment::_internal_mutable_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.location_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Experiment::release_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.location) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000008U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + auto* released = _impl_.location_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.location_.Set("", GetArena()); + } + return released; +} +inline void Experiment::set_allocated_location(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + _impl_.location_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.location_.IsDefault()) { + _impl_.location_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.location) +} + +// string hypothesis = 3 [json_name = "hypothesis", (.buf.validate.field) = { +inline void Experiment::clear_hypothesis() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.hypothesis_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline const ::std::string& Experiment::hypothesis() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.hypothesis) + return _internal_hypothesis(); +} +template +PROTOBUF_ALWAYS_INLINE void Experiment::set_hypothesis(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + _impl_.hypothesis_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Experiment.hypothesis) +} +inline ::std::string* PROTOBUF_NONNULL Experiment::mutable_hypothesis() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + ::std::string* _s = _internal_mutable_hypothesis(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.hypothesis) + return _s; +} +inline const ::std::string& Experiment::_internal_hypothesis() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.hypothesis_.Get(); +} +inline void Experiment::_internal_set_hypothesis(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.hypothesis_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Experiment::_internal_mutable_hypothesis() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.hypothesis_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Experiment::release_hypothesis() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.hypothesis) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000010U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + auto* released = _impl_.hypothesis_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.hypothesis_.Set("", GetArena()); + } + return released; +} +inline void Experiment::set_allocated_hypothesis(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + _impl_.hypothesis_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.hypothesis_.IsDefault()) { + _impl_.hypothesis_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.hypothesis) +} + +// .xtcp_treatment.v1.Treatment treatment = 4 [json_name = "treatment", (.buf.validate.field) = { +inline bool Experiment::has_treatment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U); + PROTOBUF_ASSUME(!value || _impl_.treatment_ != nullptr); + return value; +} +inline void Experiment::clear_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.treatment_ != nullptr) _impl_.treatment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline const ::xtcp_treatment::v1::Treatment& Experiment::_internal_treatment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Treatment* p = _impl_.treatment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Treatment>(&::xtcp_treatment::v1::Treatment_globals_); +} +inline const ::xtcp_treatment::v1::Treatment& Experiment::treatment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.treatment) + return _internal_treatment(); +} +inline void Experiment::unsafe_arena_set_allocated_treatment( + ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.treatment_); + } + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Experiment.treatment) +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE Experiment::release_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::xtcp_treatment::v1::Treatment* released = _impl_.treatment_; + _impl_.treatment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE Experiment::unsafe_arena_release_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.treatment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::xtcp_treatment::v1::Treatment* temp = _impl_.treatment_; + _impl_.treatment_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL Experiment::_internal_mutable_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.treatment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Treatment>(GetArena()); + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(p); + } + return _impl_.treatment_; +} +inline ::xtcp_treatment::v1::Treatment* PROTOBUF_NONNULL Experiment::mutable_treatment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + ::xtcp_treatment::v1::Treatment* _msg = _internal_mutable_treatment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.treatment) + return _msg; +} +inline void Experiment::set_allocated_treatment(::xtcp_treatment::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.treatment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment::v1::Treatment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.treatment) +} + +// .xtcp_treatment.v1.ExperimentPolicy policy = 5 [json_name = "policy", (.buf.validate.field) = { +inline bool Experiment::has_policy() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U); + PROTOBUF_ASSUME(!value || _impl_.policy_ != nullptr); + return value; +} +inline void Experiment::clear_policy() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.policy_ != nullptr) _impl_.policy_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline const ::xtcp_treatment::v1::ExperimentPolicy& Experiment::_internal_policy() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::ExperimentPolicy* p = _impl_.policy_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::ExperimentPolicy>(&::xtcp_treatment::v1::ExperimentPolicy_globals_); +} +inline const ::xtcp_treatment::v1::ExperimentPolicy& Experiment::policy() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.policy) + return _internal_policy(); +} +inline void Experiment::unsafe_arena_set_allocated_policy( + ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.policy_); + } + _impl_.policy_ = reinterpret_cast<::xtcp_treatment::v1::ExperimentPolicy*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Experiment.policy) +} +inline ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE Experiment::release_policy() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::xtcp_treatment::v1::ExperimentPolicy* released = _impl_.policy_; + _impl_.policy_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE Experiment::unsafe_arena_release_policy() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.policy) + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::xtcp_treatment::v1::ExperimentPolicy* temp = _impl_.policy_; + _impl_.policy_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NONNULL Experiment::_internal_mutable_policy() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.policy_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::ExperimentPolicy>(GetArena()); + _impl_.policy_ = reinterpret_cast<::xtcp_treatment::v1::ExperimentPolicy*>(p); + } + return _impl_.policy_; +} +inline ::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NONNULL Experiment::mutable_policy() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + ::xtcp_treatment::v1::ExperimentPolicy* _msg = _internal_mutable_policy(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.policy) + return _msg; +} +inline void Experiment::set_allocated_policy(::xtcp_treatment::v1::ExperimentPolicy* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.policy_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + + _impl_.policy_ = reinterpret_cast<::xtcp_treatment::v1::ExperimentPolicy*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.policy) +} + +// .xtcp_treatment.v1.Evidence baseline = 6 [json_name = "baseline", (.buf.validate.field) = { +inline bool Experiment::has_baseline() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000080U); + PROTOBUF_ASSUME(!value || _impl_.baseline_ != nullptr); + return value; +} +inline void Experiment::clear_baseline() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.baseline_ != nullptr) _impl_.baseline_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +inline const ::xtcp_treatment::v1::Evidence& Experiment::_internal_baseline() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Evidence* p = _impl_.baseline_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Evidence>(&::xtcp_treatment::v1::Evidence_globals_); +} +inline const ::xtcp_treatment::v1::Evidence& Experiment::baseline() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.baseline) + return _internal_baseline(); +} +inline void Experiment::unsafe_arena_set_allocated_baseline( + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.baseline_); + } + _impl_.baseline_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Experiment.baseline) +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE Experiment::release_baseline() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::xtcp_treatment::v1::Evidence* released = _impl_.baseline_; + _impl_.baseline_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE Experiment::unsafe_arena_release_baseline() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.baseline) + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::xtcp_treatment::v1::Evidence* temp = _impl_.baseline_; + _impl_.baseline_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL Experiment::_internal_mutable_baseline() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.baseline_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Evidence>(GetArena()); + _impl_.baseline_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(p); + } + return _impl_.baseline_; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL Experiment::mutable_baseline() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + ::xtcp_treatment::v1::Evidence* _msg = _internal_mutable_baseline(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.baseline) + return _msg; +} +inline void Experiment::set_allocated_baseline(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.baseline_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + + _impl_.baseline_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.baseline) +} + +// repeated string cohort_order = 7 [json_name = "cohortOrder", (.buf.validate.field) = { +inline int Experiment::_internal_cohort_order_size() const { + return _internal_cohort_order().size(); +} +inline int Experiment::cohort_order_size() const { + return _internal_cohort_order_size(); +} +inline void Experiment::clear_cohort_order() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.cohort_order_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline ::std::string* PROTOBUF_NONNULL Experiment::add_cohort_order() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::std::string* _s = + _internal_mutable_cohort_order()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add_mutable:xtcp_treatment.v1.Experiment.cohort_order) + return _s; +} +inline const ::std::string& Experiment::cohort_order(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.cohort_order) + return _internal_cohort_order().Get(index); +} +inline ::std::string* PROTOBUF_NONNULL Experiment::mutable_cohort_order(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.cohort_order) + return _internal_mutable_cohort_order()->Mutable(index); +} +template +inline void Experiment::set_cohort_order(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_cohort_order()->Mutable(index), + ::std::forward(value), args... ); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Experiment.cohort_order) +} +template +inline void Experiment::add_cohort_order(Arg_&& value, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::google::protobuf::internal::AddToRepeatedPtrField( + ::google::protobuf::MessageLite::internal_visibility(), GetArena(), + *_internal_mutable_cohort_order(), ::std::forward(value), + args... ); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.Experiment.cohort_order) +} +inline const ::google::protobuf::RepeatedPtrField<::std::string>& Experiment::cohort_order() + const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.Experiment.cohort_order) + return _internal_cohort_order(); +} +inline ::google::protobuf::RepeatedPtrField<::std::string>* PROTOBUF_NONNULL +Experiment::mutable_cohort_order() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.Experiment.cohort_order) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_cohort_order(); +} +inline const ::google::protobuf::RepeatedPtrField<::std::string>& +Experiment::_internal_cohort_order() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.cohort_order_; +} +inline ::google::protobuf::RepeatedPtrField<::std::string>* PROTOBUF_NONNULL +Experiment::_internal_mutable_cohort_order() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.cohort_order_; +} + +// repeated .xtcp_treatment.v1.Phase phases = 8 [json_name = "phases", (.buf.validate.field) = { +inline int Experiment::_internal_phases_size() const { + return _internal_phases().size(); +} +inline int Experiment::phases_size() const { + return _internal_phases_size(); +} +inline void Experiment::clear_phases() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.phases_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::xtcp_treatment::v1::Phase& Experiment::phases(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.phases) + return _internal_phases().Get(index); +} +inline ::xtcp_treatment::v1::Phase* PROTOBUF_NONNULL Experiment::mutable_phases(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.phases) + return _internal_mutable_phases()->Mutable(index); +} +inline ::xtcp_treatment::v1::Phase* PROTOBUF_NONNULL Experiment::add_phases() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment::v1::Phase* _add = + _internal_mutable_phases()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_add:xtcp_treatment.v1.Experiment.phases) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>& Experiment::phases() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment.v1.Experiment.phases) + return _internal_phases(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>* PROTOBUF_NONNULL +Experiment::mutable_phases() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment.v1.Experiment.phases) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_phases(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>& +Experiment::_internal_phases() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.phases_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment::v1::Phase>* PROTOBUF_NONNULL +Experiment::_internal_mutable_phases() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.phases_; +} + +// .xtcp_treatment.v1.ExperimentStatus status = 9 [json_name = "status", (.buf.validate.field) = { +inline void Experiment::clear_status() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.status_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00001000U); +} +inline ::xtcp_treatment::v1::ExperimentStatus Experiment::status() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.status) + return _internal_status(); +} +inline void Experiment::set_status(::xtcp_treatment::v1::ExperimentStatus value) { + _internal_set_status(value); + SetHasBit(_impl_._has_bits_[0], 0x00001000U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Experiment.status) +} +inline ::xtcp_treatment::v1::ExperimentStatus Experiment::_internal_status() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment::v1::ExperimentStatus>(_impl_.status_); +} +inline void Experiment::_internal_set_status(::xtcp_treatment::v1::ExperimentStatus value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.status_ = value; +} + +// uint64 revision = 10 [json_name = "revision"]; +inline void Experiment::clear_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000800U); +} +inline ::uint64_t Experiment::revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.revision) + return _internal_revision(); +} +inline void Experiment::set_revision(::uint64_t value) { + _internal_set_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000800U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Experiment.revision) +} +inline ::uint64_t Experiment::_internal_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.revision_; +} +inline void Experiment::_internal_set_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = value; +} + +// .google.protobuf.Timestamp proposed_at = 11 [json_name = "proposedAt"]; +inline bool Experiment::has_proposed_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000100U); + PROTOBUF_ASSUME(!value || _impl_.proposed_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Experiment::_internal_proposed_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.proposed_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Experiment::proposed_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.proposed_at) + return _internal_proposed_at(); +} +inline void Experiment::unsafe_arena_set_allocated_proposed_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.proposed_at_); + } + _impl_.proposed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Experiment.proposed_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Experiment::release_proposed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* released = _impl_.proposed_at_; + _impl_.proposed_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Experiment::unsafe_arena_release_proposed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.proposed_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* temp = _impl_.proposed_at_; + _impl_.proposed_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Experiment::_internal_mutable_proposed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.proposed_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.proposed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.proposed_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Experiment::mutable_proposed_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_proposed_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.proposed_at) + return _msg; +} +inline void Experiment::set_allocated_proposed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.proposed_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + } + + _impl_.proposed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.proposed_at) +} + +// .xtcp_treatment.v1.Evidence latest_evidence = 12 [json_name = "latestEvidence"]; +inline bool Experiment::has_latest_evidence() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000200U); + PROTOBUF_ASSUME(!value || _impl_.latest_evidence_ != nullptr); + return value; +} +inline void Experiment::clear_latest_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.latest_evidence_ != nullptr) _impl_.latest_evidence_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000200U); +} +inline const ::xtcp_treatment::v1::Evidence& Experiment::_internal_latest_evidence() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment::v1::Evidence* p = _impl_.latest_evidence_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment::v1::Evidence>(&::xtcp_treatment::v1::Evidence_globals_); +} +inline const ::xtcp_treatment::v1::Evidence& Experiment::latest_evidence() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.latest_evidence) + return _internal_latest_evidence(); +} +inline void Experiment::unsafe_arena_set_allocated_latest_evidence( + ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.latest_evidence_); + } + _impl_.latest_evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000200U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000200U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Experiment.latest_evidence) +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE Experiment::release_latest_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000200U); + ::xtcp_treatment::v1::Evidence* released = _impl_.latest_evidence_; + _impl_.latest_evidence_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE Experiment::unsafe_arena_release_latest_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.latest_evidence) + + ClearHasBit(_impl_._has_bits_[0], 0x00000200U); + ::xtcp_treatment::v1::Evidence* temp = _impl_.latest_evidence_; + _impl_.latest_evidence_ = nullptr; + return temp; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL Experiment::_internal_mutable_latest_evidence() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.latest_evidence_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment::v1::Evidence>(GetArena()); + _impl_.latest_evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(p); + } + return _impl_.latest_evidence_; +} +inline ::xtcp_treatment::v1::Evidence* PROTOBUF_NONNULL Experiment::mutable_latest_evidence() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000200U); + ::xtcp_treatment::v1::Evidence* _msg = _internal_mutable_latest_evidence(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.latest_evidence) + return _msg; +} +inline void Experiment::set_allocated_latest_evidence(::xtcp_treatment::v1::Evidence* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.latest_evidence_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000200U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000200U); + } + + _impl_.latest_evidence_ = reinterpret_cast<::xtcp_treatment::v1::Evidence*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.latest_evidence) +} + +// .xtcp_treatment.v1.Outcome latest_outcome = 13 [json_name = "latestOutcome", (.buf.validate.field) = { +inline void Experiment::clear_latest_outcome() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.latest_outcome_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00002000U); +} +inline ::xtcp_treatment::v1::Outcome Experiment::latest_outcome() const { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.latest_outcome) + return _internal_latest_outcome(); +} +inline void Experiment::set_latest_outcome(::xtcp_treatment::v1::Outcome value) { + _internal_set_latest_outcome(value); + SetHasBit(_impl_._has_bits_[0], 0x00002000U); + // @@protoc_insertion_point(field_set:xtcp_treatment.v1.Experiment.latest_outcome) +} +inline ::xtcp_treatment::v1::Outcome Experiment::_internal_latest_outcome() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment::v1::Outcome>(_impl_.latest_outcome_); +} +inline void Experiment::_internal_set_latest_outcome(::xtcp_treatment::v1::Outcome value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.latest_outcome_ = value; +} + +// .google.protobuf.Timestamp updated_at = 14 [json_name = "updatedAt"]; +inline bool Experiment::has_updated_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000400U); + PROTOBUF_ASSUME(!value || _impl_.updated_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Experiment::_internal_updated_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.updated_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Experiment::updated_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment.v1.Experiment.updated_at) + return _internal_updated_at(); +} +inline void Experiment::unsafe_arena_set_allocated_updated_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.updated_at_); + } + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000400U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000400U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment.v1.Experiment.updated_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Experiment::release_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000400U); + ::google::protobuf::Timestamp* released = _impl_.updated_at_; + _impl_.updated_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Experiment::unsafe_arena_release_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment.v1.Experiment.updated_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000400U); + ::google::protobuf::Timestamp* temp = _impl_.updated_at_; + _impl_.updated_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Experiment::_internal_mutable_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.updated_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.updated_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Experiment::mutable_updated_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000400U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_updated_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment.v1.Experiment.updated_at) + return _msg; +} +inline void Experiment::set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.updated_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000400U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000400U); + } + + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment.v1.Experiment.updated_at) +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment + + +namespace google { +namespace protobuf { + +template <> +struct is_proto_enum<::xtcp_treatment::v1::Role> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment::v1::Role>() { + return ::xtcp_treatment::v1::Role_descriptor(); +} +template <> +struct is_proto_enum<::xtcp_treatment::v1::AssignmentMode> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment::v1::AssignmentMode>() { + return ::xtcp_treatment::v1::AssignmentMode_descriptor(); +} +template <> +struct is_proto_enum<::xtcp_treatment::v1::ApplyStatus> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment::v1::ApplyStatus>() { + return ::xtcp_treatment::v1::ApplyStatus_descriptor(); +} +template <> +struct is_proto_enum<::xtcp_treatment::v1::Outcome> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment::v1::Outcome>() { + return ::xtcp_treatment::v1::Outcome_descriptor(); +} +template <> +struct is_proto_enum<::xtcp_treatment::v1::ExperimentStatus> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment::v1::ExperimentStatus>() { + return ::xtcp_treatment::v1::ExperimentStatus_descriptor(); +} + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" +// clang-format on + +#endif // xtcp_5ftreatment_2fv1_2ftreatment_2eproto_2epb_2eh diff --git a/gen/cpp/xtcp_treatment_journal/v1/journal.grpc.pb.cc b/gen/cpp/xtcp_treatment_journal/v1/journal.grpc.pb.cc new file mode 100644 index 000000000..5762ceb25 --- /dev/null +++ b/gen/cpp/xtcp_treatment_journal/v1/journal.grpc.pb.cc @@ -0,0 +1,29 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment_journal/v1/journal.proto + +#include "xtcp_treatment_journal/v1/journal.pb.h" +#include "xtcp_treatment_journal/v1/journal.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace xtcp_treatment_journal { +namespace v1 { + +} // namespace xtcp_treatment_journal +} // namespace v1 +#include + diff --git a/gen/cpp/xtcp_treatment_journal/v1/journal.grpc.pb.h b/gen/cpp/xtcp_treatment_journal/v1/journal.grpc.pb.h new file mode 100644 index 000000000..8bb9b7a8b --- /dev/null +++ b/gen/cpp/xtcp_treatment_journal/v1/journal.grpc.pb.h @@ -0,0 +1,59 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: xtcp_treatment_journal/v1/journal.proto +// Original file comments: +// +// xTCP - treatment journal +// +// The host-side intent journal of the route treatment agent: the desired +// state last accepted from the controller, the local hold, and one record per +// assignment with the exact kernel route bytes that were installed. It is a +// FILE FORMAT, read and written only on the host by the agent, the watchdog +// and the local treatmentctl commands, and never an RPC payload. +// +// It is a separate proto package from xtcp_treatment.v1 on purpose: the host +// side (pkg/treatment/reconcile, the watchdog) must be able to read and write +// the journal without linking the gRPC service stubs that share a Go package +// with the RPC messages. The messages below therefore repeat the treatment +// shape rather than importing it; pkg/treatment/reconcile converts them to +// and from the domain types, and the domain validators run on every load. +// +// Values of the two enums mirror xtcp_treatment.v1 one-for-one and the domain +// enums in pkg/treatment; reconcile's tests pin the correspondence. +// +// See docs/tcp-controller.md, "Persistence, restart and withdrawal". +// +#ifndef GRPC_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto__INCLUDED +#define GRPC_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto__INCLUDED + +#include "xtcp_treatment_journal/v1/journal.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xtcp_treatment_journal { +namespace v1 { + +} // namespace v1 +} // namespace xtcp_treatment_journal + + +#include +#endif // GRPC_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto__INCLUDED diff --git a/gen/cpp/xtcp_treatment_journal/v1/journal.pb.cc b/gen/cpp/xtcp_treatment_journal/v1/journal.pb.cc new file mode 100644 index 000000000..9eb3f910c --- /dev/null +++ b/gen/cpp/xtcp_treatment_journal/v1/journal.pb.cc @@ -0,0 +1,3959 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment_journal/v1/journal.proto +// Protobuf C++ Version: 7.36.2 + +#include "xtcp_treatment_journal/v1/journal.pb.h" + +#include +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/internal_visibility.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; +#ifdef PROTOBUF_MESSAGE_GLOBALS +namespace { +PROTOBUF_CONSTINIT ::google::protobuf::internal::ReflectionData + file_reflection_data[] = { + // ::xtcp_treatment_journal::v1::TCPSettings + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment_journal::v1::Treatment + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment_journal::v1::Assignment + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment_journal::v1::Desired + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment_journal::v1::Record + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, /* tracker*/ nullptr,}, + // ::xtcp_treatment_journal::v1::Journal + {&::_pbi::kDescriptorMethods, &::descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, /* tracker*/ nullptr,}, +}; +} // namespace +#endif +namespace xtcp_treatment_journal { +namespace v1 { +class TCPSettings::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_._has_bits_); +}; + +constexpr TCPSettings::ParseTableT_ TCPSettings::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_._has_bits_), + 0, // no _extensions_ + 7, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967168, // skipmap + offsetof(ParseTableT_, field_entries), + 7, // num_field_entries + 0, // num_aux_entries + offsetof(ParseTableT_, field_names), // no aux_entries + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::TCPSettings>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // optional string congestion_control = 1 [json_name = "congestionControl"]; + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_control_)}}, + // bool congestion_lock = 2 [json_name = "congestionLock"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {16, 4, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_lock_)}}, + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TCPSettings, _impl_.rto_min_ms_), 1>(), + {24, 1, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.rto_min_ms_)}}, + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TCPSettings, _impl_.initial_congestion_window_), 2>(), + {32, 2, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_congestion_window_)}}, + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(TCPSettings, _impl_.initial_receive_window_), 3>(), + {40, 3, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_receive_window_)}}, + // optional bool quick_ack = 6 [json_name = "quickAck"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {48, 5, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.quick_ack_)}}, + // optional bool ecn = 7 [json_name = "ecn"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {56, 6, 0, + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.ecn_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // optional string congestion_control = 1 [json_name = "congestionControl"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_control_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bool congestion_lock = 2 [json_name = "congestionLock"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.congestion_lock_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.rto_min_ms_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_congestion_window_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.initial_receive_window_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt32)}, + // optional bool quick_ack = 6 [json_name = "quickAck"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.quick_ack_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional bool ecn = 7 [json_name = "ecn"]; + {PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.ecn_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + // no aux_entries + {{ + "\45\22\0\0\0\0\0\0" + "xtcp_treatment_journal.v1.TCPSettings" + "congestion_control" + }}, + }; +} + + +inline constexpr TCPSettings::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : congestion_control_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + rto_min_ms_{0u}, + initial_congestion_window_{0u}, + initial_receive_window_{0u}, + congestion_lock_{false}, + quick_ack_{false}, + ecn_{false} {} + +template +constexpr TCPSettings::TCPSettings(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL TCPSettings::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) TCPSettings(arena); +} +constexpr auto TCPSettings::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(TCPSettings), alignof(TCPSettings)); +} +constexpr auto TCPSettings::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &TCPSettings::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &TCPSettings::SharedDtor, + Super_::GetClearImpl(), &TCPSettings::ByteSizeLong, + &TCPSettings::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[0], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct TCPSettingsGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr TCPSettingsGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + TCPSettings_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(TCPSettings::InternalGenerateClassData_( + _default, &TCPSettings_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~TCPSettingsGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) TCPSettings _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(TCPSettingsGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST TCPSettingsGlobalsTypeInternal TCPSettings_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* TCPSettings_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return TCPSettings_globals_.GetClassData(); +#else + return TCPSettings_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Treatment::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Treatment, _impl_._has_bits_); +}; + +constexpr Treatment::ParseTableT_ Treatment::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Treatment, _impl_._has_bits_), + 0, // no _extensions_ + 5, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967264, // skipmap + offsetof(ParseTableT_, field_entries), + 5, // num_field_entries + 1, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Treatment>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string id = 1 [json_name = "id"]; + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.id_)}}, + // uint64 revision = 2 [json_name = "revision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Treatment, _impl_.revision_), 3>(), + {16, 3, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.revision_)}}, + // string destination = 3 [json_name = "destination"]; + {::_pbi::TcParser::FastUS1, + {26, 1, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.destination_)}}, + // .xtcp_treatment_journal.v1.TCPSettings settings = 4 [json_name = "settings"]; + {::_pbi::TcParser::FastMtS1, + {34, 2, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.settings_)}}, + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {40, 4, 0, + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.ecn_fabric_verified_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string id = 1 [json_name = "id"]; + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // uint64 revision = 2 [json_name = "revision"]; + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.revision_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // string destination = 3 [json_name = "destination"]; + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.destination_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment_journal.v1.TCPSettings settings = 4 [json_name = "settings"]; + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.settings_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + {PROTOBUF_FIELD_OFFSET(Treatment, _impl_.ecn_fabric_verified_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::TCPSettings>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment_journal::v1::TCPSettings_globals_}, + #endif + }}, + {{ + "\43\2\0\13\0\0\0\0" + "xtcp_treatment_journal.v1.Treatment" + "id" + "destination" + }}, + }; +} + + +inline constexpr Treatment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + destination_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + settings_{nullptr}, + revision_{::uint64_t{0u}}, + ecn_fabric_verified_{false} {} + +template +constexpr Treatment::Treatment(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Treatment::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Treatment(arena); +} +constexpr auto Treatment::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Treatment), alignof(Treatment)); +} +constexpr auto Treatment::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Treatment::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Treatment::SharedDtor, + Super_::GetClearImpl(), &Treatment::ByteSizeLong, + &Treatment::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Treatment, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[1], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct TreatmentGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr TreatmentGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Treatment_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Treatment::InternalGenerateClassData_( + _default, &Treatment_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~TreatmentGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Treatment _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(TreatmentGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST TreatmentGlobalsTypeInternal Treatment_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Treatment_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Treatment_globals_.GetClassData(); +#else + return Treatment_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Assignment::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Assignment, _impl_._has_bits_); +}; + +constexpr Assignment::ParseTableT_ Assignment::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Assignment, _impl_._has_bits_), + 0, // no _extensions_ + 6, 56, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967232, // skipmap + offsetof(ParseTableT_, field_entries), + 6, // num_field_entries + 3, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Assignment>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string experiment_id = 1 [json_name = "experimentId"]; + {::_pbi::TcParser::FastUS1, + {10, 0, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.experiment_id_)}}, + // .xtcp_treatment_journal.v1.Treatment treatment = 2 [json_name = "treatment"]; + {::_pbi::TcParser::FastMtS1, + {18, 1, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.treatment_)}}, + // .xtcp_treatment_journal.v1.AssignmentMode mode = 3 [json_name = "mode"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Assignment, _impl_.mode_), 5>(), + {24, 5, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.mode_)}}, + // .google.protobuf.Timestamp lease_expires_at = 4 [json_name = "leaseExpiresAt"]; + {::_pbi::TcParser::FastMtS1, + {34, 2, 1, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.lease_expires_at_)}}, + // .xtcp_treatment_journal.v1.Treatment predecessor = 5 [json_name = "predecessor"]; + {::_pbi::TcParser::FastMtS1, + {42, 3, 2, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.predecessor_)}}, + // uint64 generation = 6 [json_name = "generation"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Assignment, _impl_.generation_), 4>(), + {48, 4, 0, + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.generation_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string experiment_id = 1 [json_name = "experimentId"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.experiment_id_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment_journal.v1.Treatment treatment = 2 [json_name = "treatment"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.treatment_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment_journal.v1.AssignmentMode mode = 3 [json_name = "mode"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.mode_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .google.protobuf.Timestamp lease_expires_at = 4 [json_name = "leaseExpiresAt"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.lease_expires_at_), _Internal::kHasBitsOffset + 2, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .xtcp_treatment_journal.v1.Treatment predecessor = 5 [json_name = "predecessor"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.predecessor_), _Internal::kHasBitsOffset + 3, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint64 generation = 6 [json_name = "generation"]; + {PROTOBUF_FIELD_OFFSET(Assignment, _impl_.generation_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Treatment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment_journal::v1::Treatment_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Treatment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment_journal::v1::Treatment_globals_}, + #endif + }}, + {{ + "\44\15\0\0\0\0\0\0" + "xtcp_treatment_journal.v1.Assignment" + "experiment_id" + }}, + }; +} + + +inline constexpr Assignment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : experiment_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + treatment_{nullptr}, + lease_expires_at_{nullptr}, + predecessor_{nullptr}, + generation_{::uint64_t{0u}}, + mode_{static_cast< ::xtcp_treatment_journal::v1::AssignmentMode >(0)} {} + +template +constexpr Assignment::Assignment(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Assignment::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Assignment(arena); +} +constexpr auto Assignment::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Assignment), alignof(Assignment)); +} +constexpr auto Assignment::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Assignment::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Assignment::SharedDtor, + Super_::GetClearImpl(), &Assignment::ByteSizeLong, + &Assignment::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Assignment, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[2], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct AssignmentGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr AssignmentGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Assignment_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Assignment::InternalGenerateClassData_( + _default, &Assignment_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~AssignmentGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Assignment _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(AssignmentGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST AssignmentGlobalsTypeInternal Assignment_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Assignment_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Assignment_globals_.GetClassData(); +#else + return Assignment_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Record::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Record, _impl_._has_bits_); +}; + +constexpr Record::ParseTableT_ Record::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Record, _impl_._has_bits_), + 0, // no _extensions_ + 12, 120, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294963200, // skipmap + offsetof(ParseTableT_, field_entries), + 12, // num_field_entries + 6, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Record>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // .xtcp_treatment_journal.v1.Assignment assignment = 1 [json_name = "assignment"]; + {::_pbi::TcParser::FastMtS1, + {10, 3, 0, + PROTOBUF_FIELD_OFFSET(Record, _impl_.assignment_)}}, + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Record, _impl_.desired_revision_), 9>(), + {16, 9, 0, + PROTOBUF_FIELD_OFFSET(Record, _impl_.desired_revision_)}}, + // .xtcp_treatment_journal.v1.ApplyStatus status = 3 [json_name = "status"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Record, _impl_.status_), 10>(), + {24, 10, 0, + PROTOBUF_FIELD_OFFSET(Record, _impl_.status_)}}, + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + {::_pbi::TcParser::FastMtS1, + {34, 4, 1, + PROTOBUF_FIELD_OFFSET(Record, _impl_.received_at_)}}, + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + {::_pbi::TcParser::FastMtS1, + {42, 5, 2, + PROTOBUF_FIELD_OFFSET(Record, _impl_.attempted_at_)}}, + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + {::_pbi::TcParser::FastMtS1, + {50, 6, 3, + PROTOBUF_FIELD_OFFSET(Record, _impl_.applied_at_)}}, + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + {::_pbi::TcParser::FastMtS1, + {58, 7, 4, + PROTOBUF_FIELD_OFFSET(Record, _impl_.verified_at_)}}, + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + {::_pbi::TcParser::FastMtS1, + {66, 8, 5, + PROTOBUF_FIELD_OFFSET(Record, _impl_.removed_at_)}}, + // string error = 9 [json_name = "error"]; + {::_pbi::TcParser::FastUS1, + {74, 0, 0, + PROTOBUF_FIELD_OFFSET(Record, _impl_.error_)}}, + // bytes installed_route = 10 [json_name = "installedRoute"]; + {::_pbi::TcParser::FastBS1, + {82, 1, 0, + PROTOBUF_FIELD_OFFSET(Record, _impl_.installed_route_)}}, + // string installed_boot_id = 11 [json_name = "installedBootId"]; + {::_pbi::TcParser::FastUS1, + {90, 2, 0, + PROTOBUF_FIELD_OFFSET(Record, _impl_.installed_boot_id_)}}, + // bool expired_latched = 12 [json_name = "expiredLatched"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {96, 11, 0, + PROTOBUF_FIELD_OFFSET(Record, _impl_.expired_latched_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // .xtcp_treatment_journal.v1.Assignment assignment = 1 [json_name = "assignment"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.assignment_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.desired_revision_), _Internal::kHasBitsOffset + 9, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // .xtcp_treatment_journal.v1.ApplyStatus status = 3 [json_name = "status"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.status_), _Internal::kHasBitsOffset + 10, 0, (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.received_at_), _Internal::kHasBitsOffset + 4, 1, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.attempted_at_), _Internal::kHasBitsOffset + 5, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.applied_at_), _Internal::kHasBitsOffset + 6, 3, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.verified_at_), _Internal::kHasBitsOffset + 7, 4, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.removed_at_), _Internal::kHasBitsOffset + 8, 5, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // string error = 9 [json_name = "error"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.error_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bytes installed_route = 10 [json_name = "installedRoute"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.installed_route_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)}, + // string installed_boot_id = 11 [json_name = "installedBootId"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.installed_boot_id_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // bool expired_latched = 12 [json_name = "expiredLatched"]; + {PROTOBUF_FIELD_OFFSET(Record, _impl_.expired_latched_), _Internal::kHasBitsOffset + 11, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Assignment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment_journal::v1::Assignment_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + }}, + {{ + "\40\0\0\0\0\0\0\0\0\5\0\21\0\0\0\0" + "xtcp_treatment_journal.v1.Record" + "error" + "installed_boot_id" + }}, + }; +} + + +inline constexpr Record::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : error_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + installed_route_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + installed_boot_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + assignment_{nullptr}, + received_at_{nullptr}, + attempted_at_{nullptr}, + applied_at_{nullptr}, + verified_at_{nullptr}, + removed_at_{nullptr}, + desired_revision_{::uint64_t{0u}}, + status_{static_cast< ::xtcp_treatment_journal::v1::ApplyStatus >(0)}, + expired_latched_{false} {} + +template +constexpr Record::Record(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Record::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Record(arena); +} +constexpr auto Record::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Record), alignof(Record)); +} +constexpr auto Record::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Record::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Record::SharedDtor, + Super_::GetClearImpl(), &Record::ByteSizeLong, + &Record::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Record, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[4], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct RecordGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr RecordGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Record_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Record::InternalGenerateClassData_( + _default, &Record_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~RecordGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Record _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(RecordGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST RecordGlobalsTypeInternal Record_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Record_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Record_globals_.GetClassData(); +#else + return Record_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Desired::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Desired, _impl_._has_bits_); +}; + +constexpr Desired::ParseTableT_ Desired::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Desired, _impl_._has_bits_), + 0, // no _extensions_ + 4, 24, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294967280, // skipmap + offsetof(ParseTableT_, field_entries), + 4, // num_field_entries + 2, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Desired>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // repeated .xtcp_treatment_journal.v1.Assignment assignments = 4 [json_name = "assignments"]; + {::_pbi::TcParser::FastMtR1, + {34, 0, 1, + PROTOBUF_FIELD_OFFSET(Desired, _impl_.assignments_)}}, + // uint64 revision = 1 [json_name = "revision"]; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Desired, _impl_.revision_), 2>(), + {8, 2, 0, + PROTOBUF_FIELD_OFFSET(Desired, _impl_.revision_)}}, + // bool suspended = 2 [json_name = "suspended"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {16, 3, 0, + PROTOBUF_FIELD_OFFSET(Desired, _impl_.suspended_)}}, + // .google.protobuf.Timestamp issued_at = 3 [json_name = "issuedAt"]; + {::_pbi::TcParser::FastMtS1, + {26, 1, 0, + PROTOBUF_FIELD_OFFSET(Desired, _impl_.issued_at_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // uint64 revision = 1 [json_name = "revision"]; + {PROTOBUF_FIELD_OFFSET(Desired, _impl_.revision_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUInt64)}, + // bool suspended = 2 [json_name = "suspended"]; + {PROTOBUF_FIELD_OFFSET(Desired, _impl_.suspended_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // .google.protobuf.Timestamp issued_at = 3 [json_name = "issuedAt"]; + {PROTOBUF_FIELD_OFFSET(Desired, _impl_.issued_at_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .xtcp_treatment_journal.v1.Assignment assignments = 4 [json_name = "assignments"]; + {PROTOBUF_FIELD_OFFSET(Desired, _impl_.assignments_), _Internal::kHasBitsOffset + 0, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Assignment>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment_journal::v1::Assignment_globals_}, + #endif + }}, + {{ + }}, + }; +} + + +inline constexpr Desired::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : assignments_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment_journal::v1::Desired, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_.assignments_)>() + } + , + issued_at_{nullptr}, + revision_{::uint64_t{0u}}, + suspended_{false} {} + +template +constexpr Desired::Desired(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Desired::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Desired(arena); +} +constexpr auto Desired::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Desired), alignof(Desired)); +} +constexpr auto Desired::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Desired::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Desired::SharedDtor, + Super_::GetClearImpl(), &Desired::ByteSizeLong, + &Desired::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Desired, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[3], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct DesiredGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr DesiredGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Desired_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Desired::InternalGenerateClassData_( + _default, &Desired_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~DesiredGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Desired _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(DesiredGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST DesiredGlobalsTypeInternal Desired_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Desired_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Desired_globals_.GetClassData(); +#else + return Desired_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +class Journal::_Internal { + public: + using HasBits = decltype(::std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Journal, _impl_._has_bits_); +}; + +constexpr Journal::ParseTableT_ Journal::InternalGenerateParseTable_(const ::_pbi::ClassData* class_data) { + return ParseTableT_{ + { + PROTOBUF_FIELD_OFFSET(Journal, _impl_._has_bits_), + 0, // no _extensions_ + 9, 120, // max_field_number, fast_idx_mask + offsetof(ParseTableT_, field_lookup_table), + 4294966784, // skipmap + offsetof(ParseTableT_, field_entries), + 9, // num_field_entries + 3, // num_aux_entries + offsetof(ParseTableT_, aux_entries), + class_data, + nullptr, // post_loop_handler + ::_pbi::TcParser::MpUnknownFields, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Journal>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // string agent_id = 1 [json_name = "agentId"]; + {::_pbi::TcParser::FastUS1, + {10, 1, 0, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.agent_id_)}}, + // string location = 2 [json_name = "location"]; + {::_pbi::TcParser::FastUS1, + {18, 2, 0, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.location_)}}, + // string boot_id = 3 [json_name = "bootId"]; + {::_pbi::TcParser::FastUS1, + {26, 3, 0, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.boot_id_)}}, + // .xtcp_treatment_journal.v1.Desired desired = 4 [json_name = "desired"]; + {::_pbi::TcParser::FastMtS1, + {34, 6, 0, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.desired_)}}, + // bool locally_suspended = 5 [json_name = "locallySuspended"]; + {::_pbi::TcParser::SingularVarintNoZag1(), + {40, 8, 0, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.locally_suspended_)}}, + // string suspension_reason = 6 [json_name = "suspensionReason"]; + {::_pbi::TcParser::FastUS1, + {50, 4, 0, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.suspension_reason_)}}, + // repeated .xtcp_treatment_journal.v1.Record records = 7 [json_name = "records"]; + {::_pbi::TcParser::FastMtR1, + {58, 0, 1, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.records_)}}, + // .google.protobuf.Timestamp updated_at = 8 [json_name = "updatedAt"]; + {::_pbi::TcParser::FastMtS1, + {66, 7, 2, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.updated_at_)}}, + // string collection_id = 9 [json_name = "collectionId"]; + {::_pbi::TcParser::FastUS1, + {74, 5, 0, + PROTOBUF_FIELD_OFFSET(Journal, _impl_.collection_id_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // string agent_id = 1 [json_name = "agentId"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.agent_id_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string location = 2 [json_name = "location"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.location_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string boot_id = 3 [json_name = "bootId"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.boot_id_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .xtcp_treatment_journal.v1.Desired desired = 4 [json_name = "desired"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.desired_), _Internal::kHasBitsOffset + 6, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // bool locally_suspended = 5 [json_name = "locallySuspended"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.locally_suspended_), _Internal::kHasBitsOffset + 8, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // string suspension_reason = 6 [json_name = "suspensionReason"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.suspension_reason_), _Internal::kHasBitsOffset + 4, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // repeated .xtcp_treatment_journal.v1.Record records = 7 [json_name = "records"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.records_), _Internal::kHasBitsOffset + 0, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // .google.protobuf.Timestamp updated_at = 8 [json_name = "updatedAt"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.updated_at_), _Internal::kHasBitsOffset + 7, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // string collection_id = 9 [json_name = "collectionId"]; + {PROTOBUF_FIELD_OFFSET(Journal, _impl_.collection_id_), _Internal::kHasBitsOffset + 5, 0, (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + }}, + {{ + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Desired>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment_journal::v1::Desired_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::xtcp_treatment_journal::v1::Record>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::xtcp_treatment_journal::v1::Record_globals_}, + #endif + #ifndef PROTOBUF_MESSAGE_GLOBALS + {::_pbi::TcParser::GetTable<::google::protobuf::Timestamp>()}, + #else + {::_pbi::FieldAuxMessageGlobals(), &::google::protobuf::Timestamp_globals_}, + #endif + }}, + {{ + "\41\10\10\7\0\0\21\0\0\15\0\0\0\0\0\0" + "xtcp_treatment_journal.v1.Journal" + "agent_id" + "location" + "boot_id" + "suspension_reason" + "collection_id" + }}, + }; +} + + +inline constexpr Journal::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + ::_pbi::ConstantInitialized) noexcept + : records_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment_journal::v1::Journal, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.records_)>() + } + , + agent_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + location_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + boot_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + suspension_reason_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + collection_id_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + desired_{nullptr}, + updated_at_{nullptr}, + locally_suspended_{false} {} + +template +constexpr Journal::Journal(::_pbi::ConstantInitialized, + const ::_pbi::ClassData* PROTOBUF_NONNULL class_data) + : Super_( +#if defined(PROTOBUF_CUSTOM_VTABLE) + class_data +#endif // PROTOBUF_CUSTOM_VTABLE + ), + _impl_(internal_visibility(), ::_pbi::ConstantInitialized()) { +} +inline void* PROTOBUF_NONNULL Journal::PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) { + return ::new (mem) Journal(arena); +} +constexpr auto Journal::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Journal), alignof(Journal)); +} +constexpr auto Journal::InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* tc_table) { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &prototype, +#ifndef PROTOBUF_MESSAGE_GLOBALS + &_table_.header, +#else + tc_table, +#endif + nullptr, // IsInitialized + &Journal::MergeImpl, + Super_::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Journal::SharedDtor, + Super_::GetClearImpl(), &Journal::ByteSizeLong, + &Journal::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Journal, _impl_._cached_size_), + false, + }, +#ifdef PROTOBUF_MESSAGE_GLOBALS + &file_reflection_data[5], +#else // !PROTOBUF_MESSAGE_GLOBALS + &::_pbi::kDescriptorMethods, + &descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + nullptr, // tracker +#endif // PROTOBUF_MESSAGE_GLOBALS + }; +} +struct JournalGlobalsTypeInternal : ::_pbi::MessageGlobalsBase { + constexpr JournalGlobalsTypeInternal() + : +#ifndef PROTOBUF_MESSAGE_GLOBALS + _default(::_pbi::ConstantInitialized{}, + Journal_class_data_.base()) +#else // !PROTOBUF_MESSAGE_GLOBALS + MessageGlobalsBase(Journal::InternalGenerateClassData_( + _default, &Journal_globals_._table.header)), + _default(::_pbi::ConstantInitialized{}, GetClassData()), + _table(::_pbi::PrivateAccess::GenerateParseTable( + GetClassData())) +#endif // PROTOBUF_MESSAGE_GLOBALS + { + } + ~JournalGlobalsTypeInternal() {} + union { + alignas(::_pbi::kMaxMessageAlignment) Journal _default; + }; +#ifdef PROTOBUF_MESSAGE_GLOBALS + decltype(::_pbi::PrivateAccess::GenerateParseTable( + ::std::declval())) _table; +#endif +}; +#ifdef PROTOBUF_MESSAGE_GLOBALS +static_assert(PROTOBUF_FIELD_OFFSET(JournalGlobalsTypeInternal, _default) == + ::_pbi::MessageGlobalsBase::OffsetToDefault()); +#endif // PROTOBUF_MESSAGE_GLOBALS + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PROTOBUF_MESSAGE_GLOBALS_CONST JournalGlobalsTypeInternal Journal_globals_ + PROTOBUF_MESSAGE_GLOBALS_SECTION(.data.rel.ro); +#if defined(PROTOBUF_CUSTOM_VTABLE) +namespace { +const ::_pbi::ClassData* Journal_get_class_data() { +#ifdef PROTOBUF_MESSAGE_GLOBALS + return Journal_globals_.GetClassData(); +#else + return Journal_class_data_.base(); +#endif // PROTOBUF_MESSAGE_GLOBALS +} +} // namespace +#endif // PROTOBUF_CUSTOM_VTABLE +} // namespace v1 +} // namespace xtcp_treatment_journal +static const ::_pb::EnumDescriptor* PROTOBUF_NONNULL + file_level_enum_descriptors_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto[2]; +static constexpr const ::_pb::ServiceDescriptor* PROTOBUF_NONNULL* PROTOBUF_NULLABLE + file_level_service_descriptors_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto = nullptr; +const ::uint32_t + TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_._has_bits_), + 10, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_.congestion_control_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_.congestion_lock_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_.rto_min_ms_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_.initial_congestion_window_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_.initial_receive_window_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_.quick_ack_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::TCPSettings, _impl_.ecn_), + 0, + 4, + 1, + 2, + 3, + 5, + 6, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Treatment, _impl_._has_bits_), + 8, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Treatment, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Treatment, _impl_.revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Treatment, _impl_.destination_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Treatment, _impl_.settings_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Treatment, _impl_.ecn_fabric_verified_), + 0, + 3, + 1, + 2, + 4, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Assignment, _impl_._has_bits_), + 9, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Assignment, _impl_.experiment_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Assignment, _impl_.treatment_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Assignment, _impl_.mode_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Assignment, _impl_.lease_expires_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Assignment, _impl_.predecessor_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Assignment, _impl_.generation_), + 0, + 1, + 5, + 2, + 3, + 4, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_._has_bits_), + 7, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_.revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_.suspended_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_.issued_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_.assignments_), + 2, + 3, + 1, + 0, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_._has_bits_), + 15, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.assignment_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.desired_revision_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.status_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.received_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.attempted_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.applied_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.verified_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.removed_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.error_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.installed_route_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.installed_boot_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Record, _impl_.expired_latched_), + 3, + 9, + 10, + 4, + 5, + 6, + 7, + 8, + 0, + 1, + 2, + 11, + 0x081, // bitmap + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_._has_bits_), + 12, // hasbit index offset + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.agent_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.boot_id_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.desired_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.locally_suspended_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.suspension_reason_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.records_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.updated_at_), + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.collection_id_), + 1, + 2, + 3, + 6, + 8, + 4, + 0, + 7, + 5, +}; + +static const ::_pbi::MigrationSchema + schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + {0, sizeof(::xtcp_treatment_journal::v1::TCPSettings)}, + {17, sizeof(::xtcp_treatment_journal::v1::Treatment)}, + {30, sizeof(::xtcp_treatment_journal::v1::Assignment)}, + {45, sizeof(::xtcp_treatment_journal::v1::Desired)}, + {56, sizeof(::xtcp_treatment_journal::v1::Record)}, + {83, sizeof(::xtcp_treatment_journal::v1::Journal)}, +}; +static const ::_pbi::MessageGlobalsBase* PROTOBUF_NONNULL const + file_message_globals[] = { + &::xtcp_treatment_journal::v1::TCPSettings_globals_, + &::xtcp_treatment_journal::v1::Treatment_globals_, + &::xtcp_treatment_journal::v1::Assignment_globals_, + &::xtcp_treatment_journal::v1::Desired_globals_, + &::xtcp_treatment_journal::v1::Record_globals_, + &::xtcp_treatment_journal::v1::Journal_globals_, +}; +const char descriptor_table_protodef_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + "\n\'xtcp_treatment_journal/v1/journal.prot" + "o\022\031xtcp_treatment_journal.v1\032\037google/pro" + "tobuf/timestamp.proto\"\267\003\n\013TCPSettings\0222\n" + "\022congestion_control\030\001 \001(\tH\000R\021congestionC" + "ontrol\210\001\001\022\'\n\017congestion_lock\030\002 \001(\010R\016cong" + "estionLock\022!\n\nrto_min_ms\030\003 \001(\rH\001R\010rtoMin" + "Ms\210\001\001\022\?\n\031initial_congestion_window\030\004 \001(\r" + "H\002R\027initialCongestionWindow\210\001\001\0229\n\026initia" + "l_receive_window\030\005 \001(\rH\003R\024initialReceive" + "Window\210\001\001\022 \n\tquick_ack\030\006 \001(\010H\004R\010quickAck" + "\210\001\001\022\025\n\003ecn\030\007 \001(\010H\005R\003ecn\210\001\001B\025\n\023_congestio" + "n_controlB\r\n\013_rto_min_msB\034\n\032_initial_con" + "gestion_windowB\031\n\027_initial_receive_windo" + "wB\014\n\n_quick_ackB\006\n\004_ecn\"\315\001\n\tTreatment\022\016\n" + "\002id\030\001 \001(\tR\002id\022\032\n\010revision\030\002 \001(\004R\010revisio" + "n\022 \n\013destination\030\003 \001(\tR\013destination\022B\n\010s" + "ettings\030\004 \001(\0132&.xtcp_treatment_journal.v" + "1.TCPSettingsR\010settings\022.\n\023ecn_fabric_ve" + "rified\030\005 \001(\010R\021ecnFabricVerified\"\342\002\n\nAssi" + "gnment\022#\n\rexperiment_id\030\001 \001(\tR\014experimen" + "tId\022B\n\ttreatment\030\002 \001(\0132$.xtcp_treatment_" + "journal.v1.TreatmentR\ttreatment\022=\n\004mode\030" + "\003 \001(\0162).xtcp_treatment_journal.v1.Assign" + "mentModeR\004mode\022D\n\020lease_expires_at\030\004 \001(\013" + "2\032.google.protobuf.TimestampR\016leaseExpir" + "esAt\022F\n\013predecessor\030\005 \001(\0132$.xtcp_treatme" + "nt_journal.v1.TreatmentR\013predecessor\022\036\n\n" + "generation\030\006 \001(\004R\ngeneration\"\305\001\n\007Desired" + "\022\032\n\010revision\030\001 \001(\004R\010revision\022\034\n\tsuspende" + "d\030\002 \001(\010R\tsuspended\0227\n\tissued_at\030\003 \001(\0132\032." + "google.protobuf.TimestampR\010issuedAt\022G\n\013a" + "ssignments\030\004 \003(\0132%.xtcp_treatment_journa" + "l.v1.AssignmentR\013assignments\"\375\004\n\006Record\022" + "E\n\nassignment\030\001 \001(\0132%.xtcp_treatment_jou" + "rnal.v1.AssignmentR\nassignment\022)\n\020desire" + "d_revision\030\002 \001(\004R\017desiredRevision\022>\n\006sta" + "tus\030\003 \001(\0162&.xtcp_treatment_journal.v1.Ap" + "plyStatusR\006status\022;\n\013received_at\030\004 \001(\0132\032" + ".google.protobuf.TimestampR\nreceivedAt\022=" + "\n\014attempted_at\030\005 \001(\0132\032.google.protobuf.T" + "imestampR\013attemptedAt\0229\n\napplied_at\030\006 \001(" + "\0132\032.google.protobuf.TimestampR\tappliedAt" + "\022;\n\013verified_at\030\007 \001(\0132\032.google.protobuf." + "TimestampR\nverifiedAt\0229\n\nremoved_at\030\010 \001(" + "\0132\032.google.protobuf.TimestampR\tremovedAt" + "\022\024\n\005error\030\t \001(\tR\005error\022\'\n\017installed_rout" + "e\030\n \001(\014R\016installedRoute\022*\n\021installed_boo" + "t_id\030\013 \001(\tR\017installedBootId\022\'\n\017expired_l" + "atched\030\014 \001(\010R\016expiredLatched\"\216\003\n\007Journal" + "\022\031\n\010agent_id\030\001 \001(\tR\007agentId\022\032\n\010location\030" + "\002 \001(\tR\010location\022\027\n\007boot_id\030\003 \001(\tR\006bootId" + "\022<\n\007desired\030\004 \001(\0132\".xtcp_treatment_journ" + "al.v1.DesiredR\007desired\022+\n\021locally_suspen" + "ded\030\005 \001(\010R\020locallySuspended\022+\n\021suspensio" + "n_reason\030\006 \001(\tR\020suspensionReason\022;\n\007reco" + "rds\030\007 \003(\0132!.xtcp_treatment_journal.v1.Re" + "cordR\007records\0229\n\nupdated_at\030\010 \001(\0132\032.goog" + "le.protobuf.TimestampR\tupdatedAt\022#\n\rcoll" + "ection_id\030\t \001(\tR\014collectionId*\244\001\n\016Assign" + "mentMode\022\037\n\033ASSIGNMENT_MODE_UNSPECIFIED\020" + "\000\022\031\n\025ASSIGNMENT_MODE_TRIAL\020\001\022\032\n\026ASSIGNME" + "NT_MODE_STABLE\020\002\022\035\n\031ASSIGNMENT_MODE_SUSP" + "ENDED\020\003\022\033\n\027ASSIGNMENT_MODE_RETIRED\020\004*\255\001\n" + "\013ApplyStatus\022\034\n\030APPLY_STATUS_UNSPECIFIED" + "\020\000\022\030\n\024APPLY_STATUS_PENDING\020\001\022\031\n\025APPLY_ST" + "ATUS_VERIFIED\020\002\022\030\n\024APPLY_STATUS_REMOVED\020" + "\003\022\030\n\024APPLY_STATUS_EXPIRED\020\004\022\027\n\023APPLY_STA" + "TUS_FAILED\020\005B\352\001\n\035com.xtcp_treatment_jour" + "nal.v1B\014JournalProtoP\001Z>github.com/rando" + "mizedcoder/xtcp2/gen/go/xtcp_treatment_j" + "ournal\242\002\003XXX\252\002\027XtcpTreatmentJournal.V1\312\002" + "\027XtcpTreatmentJournal\\V1\342\002#XtcpTreatment" + "Journal\\V1\\GPBMetadata\352\002\030XtcpTreatmentJo" + "urnal::V1b\006proto3" +}; +static const ::_pbi::DescriptorTable* PROTOBUF_NONNULL const + descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto_deps[1] = { + &::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto, +}; +static ::absl::once_flag descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto_once; +PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto = { + false, + false, + 2937, + descriptor_table_protodef_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + "xtcp_treatment_journal/v1/journal.proto", + &descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto_once, + descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto_deps, + 1, + 6, + schemas, + file_message_globals, + TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto::offsets, + file_level_enum_descriptors_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, + file_level_service_descriptors_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto, +}; +namespace xtcp_treatment_journal { +namespace v1 { +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +AssignmentMode_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto[0]; +} +PROTOBUF_CONSTINIT const uint32_t AssignmentMode_internal_data_[] = { + 327680u, 0u, }; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ApplyStatus_descriptor() { + ::google::protobuf::internal::AssignDescriptors(&descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto); + return file_level_enum_descriptors_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto[1]; +} +PROTOBUF_CONSTINIT const uint32_t ApplyStatus_internal_data_[] = { + 393216u, 0u, }; +// =================================================================== + +TCPSettings::TCPSettings(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, TCPSettings_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment_journal.v1.TCPSettings) +} +PROTOBUF_NDEBUG_INLINE TCPSettings::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment_journal::v1::TCPSettings& from_msg) + : _has_bits_{from._has_bits_}, + congestion_control_(arena, from.congestion_control_) {} + +TCPSettings::TCPSettings( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const TCPSettings& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, TCPSettings_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + TCPSettings* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, rto_min_ms_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, rto_min_ms_), + offsetof(Impl_, ecn_) - + offsetof(Impl_, rto_min_ms_) + + sizeof(Impl_::ecn_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment_journal.v1.TCPSettings) +} +PROTOBUF_NDEBUG_INLINE TCPSettings::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : congestion_control_(arena) {} + +inline void TCPSettings::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, rto_min_ms_), + 0, + offsetof(Impl_, ecn_) - + offsetof(Impl_, rto_min_ms_) + + sizeof(Impl_::ecn_)); +} +TCPSettings::~TCPSettings() { + // @@protoc_insertion_point(destructor:xtcp_treatment_journal.v1.TCPSettings) + SharedDtor(*this); +} +inline void TCPSettings::SharedDtor(MessageLite& self) { + TCPSettings& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.congestion_control_.Destroy(); + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull TCPSettings_class_data_ = + TCPSettings::InternalGenerateClassData_(TCPSettings_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TCPSettings::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TCPSettings_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(TCPSettings_class_data_.tc_table); + return TCPSettings_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +TCPSettings::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&TCPSettings_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&TCPSettings_globals_)); + return TCPSettings_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const TCPSettings::ParseTableT_ + TCPSettings::_table_ = + TCPSettings::InternalGenerateParseTable_(TCPSettings_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void TCPSettings::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment_journal.v1.TCPSettings) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.congestion_control_.ClearNonDefaultToEmpty(); + } + if (BatchCheckHasBit(cached_has_bits, 0x0000007eU)) { + ::memset(&this_._impl_.rto_min_ms_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.ecn_) - + reinterpret_cast(&this_._impl_.rto_min_ms_)) + + sizeof(_impl_.ecn_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL TCPSettings::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const TCPSettings& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL TCPSettings::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const TCPSettings& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment_journal.v1.TCPSettings) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string congestion_control = 1 [json_name = "congestionControl"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + const ::std::string& _s = this_._internal_congestion_control(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.TCPSettings.congestion_control"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // bool congestion_lock = 2 [json_name = "congestionLock"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_congestion_lock() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_congestion_lock(), target); + } + } + + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 3, this_._internal_rto_min_ms(), target); + } + + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 4, this_._internal_initial_congestion_window(), target); + } + + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray( + 5, this_._internal_initial_receive_window(), target); + } + + // optional bool quick_ack = 6 [json_name = "quickAck"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_quick_ack(), target); + } + + // optional bool ecn = 7 [json_name = "ecn"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 7, this_._internal_ecn(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment_journal.v1.TCPSettings) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t TCPSettings::ByteSizeLong(const MessageLite& base) { + const TCPSettings& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t TCPSettings::ByteSizeLong() const { + const TCPSettings& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment_journal.v1.TCPSettings) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + total_size += ::absl::popcount(0x00000060U & cached_has_bits) * 2; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + // optional string congestion_control = 1 [json_name = "congestionControl"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_congestion_control()); + } + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_rto_min_ms()); + } + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_initial_congestion_window()); + } + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne( + this_._internal_initial_receive_window()); + } + // bool congestion_lock = 2 [json_name = "congestionLock"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_congestion_lock() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void TCPSettings::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment_journal.v1.TCPSettings) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000007fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_set_congestion_control(from._internal_congestion_control()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + _this->_impl_.rto_min_ms_ = from._impl_.rto_min_ms_; + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + _this->_impl_.initial_congestion_window_ = from._impl_.initial_congestion_window_; + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + _this->_impl_.initial_receive_window_ = from._impl_.initial_receive_window_; + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_congestion_lock() != 0) { + _this->_impl_.congestion_lock_ = from._impl_.congestion_lock_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + _this->_impl_.quick_ack_ = from._impl_.quick_ack_; + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + _this->_impl_.ecn_ = from._impl_.ecn_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void TCPSettings::CopyFrom(const TCPSettings& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment_journal.v1.TCPSettings) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void TCPSettings::InternalSwap(TCPSettings* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.congestion_control_, &other->_impl_.congestion_control_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.ecn_) + + sizeof(TCPSettings::_impl_.ecn_) + - PROTOBUF_FIELD_OFFSET(TCPSettings, _impl_.rto_min_ms_)>( + reinterpret_cast(&_impl_.rto_min_ms_), + reinterpret_cast(&other->_impl_.rto_min_ms_)); +} + +::google::protobuf::Metadata TCPSettings::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +Treatment::Treatment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Treatment_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment_journal.v1.Treatment) +} +PROTOBUF_NDEBUG_INLINE Treatment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment_journal::v1::Treatment& from_msg) + : _has_bits_{from._has_bits_}, + id_(arena, from.id_), + destination_(arena, from.destination_) {} + +Treatment::Treatment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Treatment& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Treatment_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Treatment* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.settings_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.settings_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, revision_), + offsetof(Impl_, ecn_fabric_verified_) - + offsetof(Impl_, revision_) + + sizeof(Impl_::ecn_fabric_verified_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment_journal.v1.Treatment) +} +PROTOBUF_NDEBUG_INLINE Treatment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : id_(arena), + destination_(arena) {} + +inline void Treatment::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, settings_), + 0, + offsetof(Impl_, ecn_fabric_verified_) - + offsetof(Impl_, settings_) + + sizeof(Impl_::ecn_fabric_verified_)); +} +Treatment::~Treatment() { + // @@protoc_insertion_point(destructor:xtcp_treatment_journal.v1.Treatment) + SharedDtor(*this); +} +inline void Treatment::SharedDtor(MessageLite& self) { + Treatment& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.id_.Destroy(); + this_._impl_.destination_.Destroy(); + delete this_._impl_.settings_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Treatment_class_data_ = + Treatment::InternalGenerateClassData_(Treatment_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Treatment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Treatment_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Treatment_class_data_.tc_table); + return Treatment_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Treatment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Treatment_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Treatment_globals_)); + return Treatment_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Treatment::ParseTableT_ + Treatment::_table_ = + Treatment::InternalGenerateParseTable_(Treatment_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Treatment::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment_journal.v1.Treatment) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000007U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.destination_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.settings_ != nullptr); + this_._impl_.settings_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000018U)) { + ::memset(&this_._impl_.revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.ecn_fabric_verified_) - + reinterpret_cast(&this_._impl_.revision_)) + + sizeof(_impl_.ecn_fabric_verified_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Treatment::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Treatment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Treatment::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Treatment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment_journal.v1.Treatment) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string id = 1 [json_name = "id"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_id().empty()) { + const ::std::string& _s = this_._internal_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Treatment.id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // uint64 revision = 2 [json_name = "revision"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_revision(), target); + } + } + + // string destination = 3 [json_name = "destination"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_destination().empty()) { + const ::std::string& _s = this_._internal_destination(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Treatment.destination"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + } + + // .xtcp_treatment_journal.v1.TCPSettings settings = 4 [json_name = "settings"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.settings_, this_._impl_.settings_->GetCachedSize(), target, + stream); + } + + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_ecn_fabric_verified() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_ecn_fabric_verified(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment_journal.v1.Treatment) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Treatment::ByteSizeLong(const MessageLite& base) { + const Treatment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Treatment::ByteSizeLong() const { + const Treatment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment_journal.v1.Treatment) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + // string id = 1 [json_name = "id"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_id()); + } + } + // string destination = 3 [json_name = "destination"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_destination().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_destination()); + } + } + // .xtcp_treatment_journal.v1.TCPSettings settings = 4 [json_name = "settings"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.settings_); + } + // uint64 revision = 2 [json_name = "revision"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_revision()); + } + } + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_ecn_fabric_verified() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Treatment::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment_journal.v1.Treatment) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000001fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_id().empty()) { + _this->_internal_set_id(from._internal_id()); + } else { + if (_this->_impl_.id_.IsDefault()) { + _this->_internal_set_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_destination().empty()) { + _this->_internal_set_destination(from._internal_destination()); + } else { + if (_this->_impl_.destination_.IsDefault()) { + _this->_internal_set_destination(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.settings_ != nullptr); + if (_this->_impl_.settings_ == nullptr) { + _this->_impl_.settings_ = Super_::CopyConstruct(arena, *from._impl_.settings_); + } else { + _this->_impl_.settings_->MergeFrom(*from._impl_.settings_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (from._internal_revision() != 0) { + _this->_impl_.revision_ = from._impl_.revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_ecn_fabric_verified() != 0) { + _this->_impl_.ecn_fabric_verified_ = from._impl_.ecn_fabric_verified_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Treatment::CopyFrom(const Treatment& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment_journal.v1.Treatment) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Treatment::InternalSwap(Treatment* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.id_, &other->_impl_.id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.destination_, &other->_impl_.destination_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Treatment, _impl_.ecn_fabric_verified_) + + sizeof(Treatment::_impl_.ecn_fabric_verified_) + - PROTOBUF_FIELD_OFFSET(Treatment, _impl_.settings_)>( + reinterpret_cast(&_impl_.settings_), + reinterpret_cast(&other->_impl_.settings_)); +} + +::google::protobuf::Metadata Treatment::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Assignment::clear_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.lease_expires_at_ != nullptr) _impl_.lease_expires_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +Assignment::Assignment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Assignment_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment_journal.v1.Assignment) +} +PROTOBUF_NDEBUG_INLINE Assignment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment_journal::v1::Assignment& from_msg) + : _has_bits_{from._has_bits_}, + experiment_id_(arena, from.experiment_id_) {} + +Assignment::Assignment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Assignment& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Assignment_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Assignment* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.treatment_ = (CheckHasBit(cached_has_bits, 0x00000002U)) + ? Super_::CopyConstruct(arena, *from._impl_.treatment_) + : nullptr; + _impl_.lease_expires_at_ = (CheckHasBit(cached_has_bits, 0x00000004U)) + ? Super_::CopyConstruct(arena, *from._impl_.lease_expires_at_) + : nullptr; + _impl_.predecessor_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.predecessor_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, generation_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, generation_), + offsetof(Impl_, mode_) - + offsetof(Impl_, generation_) + + sizeof(Impl_::mode_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment_journal.v1.Assignment) +} +PROTOBUF_NDEBUG_INLINE Assignment::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : experiment_id_(arena) {} + +inline void Assignment::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, treatment_), + 0, + offsetof(Impl_, mode_) - + offsetof(Impl_, treatment_) + + sizeof(Impl_::mode_)); +} +Assignment::~Assignment() { + // @@protoc_insertion_point(destructor:xtcp_treatment_journal.v1.Assignment) + SharedDtor(*this); +} +inline void Assignment::SharedDtor(MessageLite& self) { + Assignment& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.experiment_id_.Destroy(); + delete this_._impl_.treatment_; + delete this_._impl_.lease_expires_at_; + delete this_._impl_.predecessor_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Assignment_class_data_ = + Assignment::InternalGenerateClassData_(Assignment_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Assignment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Assignment_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Assignment_class_data_.tc_table); + return Assignment_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Assignment::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Assignment_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Assignment_globals_)); + return Assignment_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Assignment::ParseTableT_ + Assignment::_table_ = + Assignment::InternalGenerateParseTable_(Assignment_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Assignment::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment_journal.v1.Assignment) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.experiment_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(this_._impl_.treatment_ != nullptr); + this_._impl_.treatment_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(this_._impl_.lease_expires_at_ != nullptr); + this_._impl_.lease_expires_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.predecessor_ != nullptr); + this_._impl_.predecessor_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000030U)) { + ::memset(&this_._impl_.generation_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.mode_) - + reinterpret_cast(&this_._impl_.generation_)) + + sizeof(_impl_.mode_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Assignment::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Assignment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Assignment::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Assignment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment_journal.v1.Assignment) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string experiment_id = 1 [json_name = "experimentId"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + const ::std::string& _s = this_._internal_experiment_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Assignment.experiment_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // .xtcp_treatment_journal.v1.Treatment treatment = 2 [json_name = "treatment"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.treatment_, this_._impl_.treatment_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment_journal.v1.AssignmentMode mode = 3 [json_name = "mode"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_mode() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_mode(), target); + } + } + + // .google.protobuf.Timestamp lease_expires_at = 4 [json_name = "leaseExpiresAt"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.lease_expires_at_, this_._impl_.lease_expires_at_->GetCachedSize(), target, + stream); + } + + // .xtcp_treatment_journal.v1.Treatment predecessor = 5 [json_name = "predecessor"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.predecessor_, this_._impl_.predecessor_->GetCachedSize(), target, + stream); + } + + // uint64 generation = 6 [json_name = "generation"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_generation() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 6, this_._internal_generation(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment_journal.v1.Assignment) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Assignment::ByteSizeLong(const MessageLite& base) { + const Assignment& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Assignment::ByteSizeLong() const { + const Assignment& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment_journal.v1.Assignment) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + // string experiment_id = 1 [json_name = "experimentId"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_experiment_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_experiment_id()); + } + } + // .xtcp_treatment_journal.v1.Treatment treatment = 2 [json_name = "treatment"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.treatment_); + } + // .google.protobuf.Timestamp lease_expires_at = 4 [json_name = "leaseExpiresAt"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.lease_expires_at_); + } + // .xtcp_treatment_journal.v1.Treatment predecessor = 5 [json_name = "predecessor"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.predecessor_); + } + // uint64 generation = 6 [json_name = "generation"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (this_._internal_generation() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_generation()); + } + } + // .xtcp_treatment_journal.v1.AssignmentMode mode = 3 [json_name = "mode"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (this_._internal_mode() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_mode()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Assignment::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment_journal.v1.Assignment) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000003fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_experiment_id().empty()) { + _this->_internal_set_experiment_id(from._internal_experiment_id()); + } else { + if (_this->_impl_.experiment_id_.IsDefault()) { + _this->_internal_set_experiment_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(from._impl_.treatment_ != nullptr); + if (_this->_impl_.treatment_ == nullptr) { + _this->_impl_.treatment_ = Super_::CopyConstruct(arena, *from._impl_.treatment_); + } else { + _this->_impl_.treatment_->MergeFrom(*from._impl_.treatment_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + ABSL_DCHECK(from._impl_.lease_expires_at_ != nullptr); + if (_this->_impl_.lease_expires_at_ == nullptr) { + _this->_impl_.lease_expires_at_ = Super_::CopyConstruct(arena, *from._impl_.lease_expires_at_); + } else { + _this->_impl_.lease_expires_at_->MergeFrom(*from._impl_.lease_expires_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.predecessor_ != nullptr); + if (_this->_impl_.predecessor_ == nullptr) { + _this->_impl_.predecessor_ = Super_::CopyConstruct(arena, *from._impl_.predecessor_); + } else { + _this->_impl_.predecessor_->MergeFrom(*from._impl_.predecessor_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (from._internal_generation() != 0) { + _this->_impl_.generation_ = from._impl_.generation_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (from._internal_mode() != 0) { + _this->_impl_.mode_ = from._impl_.mode_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Assignment::CopyFrom(const Assignment& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment_journal.v1.Assignment) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Assignment::InternalSwap(Assignment* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.experiment_id_, &other->_impl_.experiment_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Assignment, _impl_.mode_) + + sizeof(Assignment::_impl_.mode_) + - PROTOBUF_FIELD_OFFSET(Assignment, _impl_.treatment_)>( + reinterpret_cast(&_impl_.treatment_), + reinterpret_cast(&other->_impl_.treatment_)); +} + +::google::protobuf::Metadata Assignment::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Desired::clear_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.issued_at_ != nullptr) _impl_.issued_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +Desired::Desired(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Desired_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment_journal.v1.Desired) +} +PROTOBUF_NDEBUG_INLINE Desired::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment_journal::v1::Desired& from_msg) + : _has_bits_{from._has_bits_}, + assignments_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment_journal::v1::Desired, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_.assignments_)>() + , arena, from.assignments_ + } + {} + +Desired::Desired( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Desired& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Desired_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Desired* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.issued_at_ = (CheckHasBit(cached_has_bits, 0x00000002U)) + ? Super_::CopyConstruct(arena, *from._impl_.issued_at_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, revision_), + offsetof(Impl_, suspended_) - + offsetof(Impl_, revision_) + + sizeof(Impl_::suspended_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment_journal.v1.Desired) +} +PROTOBUF_NDEBUG_INLINE Desired::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : assignments_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment_journal::v1::Desired, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Desired, _impl_.assignments_)>() + } + {} + +inline void Desired::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, issued_at_), + 0, + offsetof(Impl_, suspended_) - + offsetof(Impl_, issued_at_) + + sizeof(Impl_::suspended_)); +} +Desired::~Desired() { + // @@protoc_insertion_point(destructor:xtcp_treatment_journal.v1.Desired) + SharedDtor(*this); +} +inline void Desired::SharedDtor(MessageLite& self) { + Desired& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.issued_at_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Desired_class_data_ = + Desired::InternalGenerateClassData_(Desired_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Desired::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Desired_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Desired_class_data_.tc_table); + return Desired_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Desired::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Desired_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Desired_globals_)); + return Desired_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Desired::ParseTableT_ + Desired::_table_ = + Desired::InternalGenerateParseTable_(Desired_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Desired::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment_journal.v1.Desired) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x00000003U)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.assignments_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(this_._impl_.issued_at_ != nullptr); + this_._impl_.issued_at_->Clear(); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x0000000cU)) { + ::memset(&this_._impl_.revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.suspended_) - + reinterpret_cast(&this_._impl_.revision_)) + + sizeof(_impl_.suspended_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Desired::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Desired& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Desired::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Desired& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment_journal.v1.Desired) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // uint64 revision = 1 [json_name = "revision"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (this_._internal_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 1, this_._internal_revision(), target); + } + } + + // bool suspended = 2 [json_name = "suspended"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_suspended() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_suspended(), target); + } + } + + // .google.protobuf.Timestamp issued_at = 3 [json_name = "issuedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.issued_at_, this_._impl_.issued_at_->GetCachedSize(), target, + stream); + } + + // repeated .xtcp_treatment_journal.v1.Assignment assignments = 4 [json_name = "assignments"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_assignments_size()); + i < n; i++) { + const auto& repfield = this_._internal_assignments().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment_journal.v1.Desired) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Desired::ByteSizeLong(const MessageLite& base) { + const Desired& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Desired::ByteSizeLong() const { + const Desired& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment_journal.v1.Desired) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + // repeated .xtcp_treatment_journal.v1.Assignment assignments = 4 [json_name = "assignments"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_assignments_size(); + for (const auto& msg : this_._internal_assignments()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // .google.protobuf.Timestamp issued_at = 3 [json_name = "issuedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.issued_at_); + } + // uint64 revision = 1 [json_name = "revision"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (this_._internal_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_revision()); + } + } + // bool suspended = 2 [json_name = "suspended"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (this_._internal_suspended() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Desired::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment_journal.v1.Desired) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x0000000fU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_assignments()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_assignments()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + ABSL_DCHECK(from._impl_.issued_at_ != nullptr); + if (_this->_impl_.issued_at_ == nullptr) { + _this->_impl_.issued_at_ = Super_::CopyConstruct(arena, *from._impl_.issued_at_); + } else { + _this->_impl_.issued_at_->MergeFrom(*from._impl_.issued_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (from._internal_revision() != 0) { + _this->_impl_.revision_ = from._impl_.revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (from._internal_suspended() != 0) { + _this->_impl_.suspended_ = from._impl_.suspended_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Desired::CopyFrom(const Desired& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment_journal.v1.Desired) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Desired::InternalSwap(Desired* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.assignments_.InternalSwap(&other->_impl_.assignments_); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Desired, _impl_.suspended_) + + sizeof(Desired::_impl_.suspended_) + - PROTOBUF_FIELD_OFFSET(Desired, _impl_.issued_at_)>( + reinterpret_cast(&_impl_.issued_at_), + reinterpret_cast(&other->_impl_.issued_at_)); +} + +::google::protobuf::Metadata Desired::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Record::clear_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.received_at_ != nullptr) _impl_.received_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +void Record::clear_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attempted_at_ != nullptr) _impl_.attempted_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +void Record::clear_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.applied_at_ != nullptr) _impl_.applied_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +void Record::clear_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.verified_at_ != nullptr) _impl_.verified_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +void Record::clear_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.removed_at_ != nullptr) _impl_.removed_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); +} +Record::Record(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Record_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment_journal.v1.Record) +} +PROTOBUF_NDEBUG_INLINE Record::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment_journal::v1::Record& from_msg) + : _has_bits_{from._has_bits_}, + error_(arena, from.error_), + installed_route_(arena, from.installed_route_), + installed_boot_id_(arena, from.installed_boot_id_) {} + +Record::Record( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Record& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Record_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Record* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.assignment_ = (CheckHasBit(cached_has_bits, 0x00000008U)) + ? Super_::CopyConstruct(arena, *from._impl_.assignment_) + : nullptr; + _impl_.received_at_ = (CheckHasBit(cached_has_bits, 0x00000010U)) + ? Super_::CopyConstruct(arena, *from._impl_.received_at_) + : nullptr; + _impl_.attempted_at_ = (CheckHasBit(cached_has_bits, 0x00000020U)) + ? Super_::CopyConstruct(arena, *from._impl_.attempted_at_) + : nullptr; + _impl_.applied_at_ = (CheckHasBit(cached_has_bits, 0x00000040U)) + ? Super_::CopyConstruct(arena, *from._impl_.applied_at_) + : nullptr; + _impl_.verified_at_ = (CheckHasBit(cached_has_bits, 0x00000080U)) + ? Super_::CopyConstruct(arena, *from._impl_.verified_at_) + : nullptr; + _impl_.removed_at_ = (CheckHasBit(cached_has_bits, 0x00000100U)) + ? Super_::CopyConstruct(arena, *from._impl_.removed_at_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, desired_revision_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, desired_revision_), + offsetof(Impl_, expired_latched_) - + offsetof(Impl_, desired_revision_) + + sizeof(Impl_::expired_latched_)); + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment_journal.v1.Record) +} +PROTOBUF_NDEBUG_INLINE Record::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : error_(arena), + installed_route_(arena), + installed_boot_id_(arena) {} + +inline void Record::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, assignment_), + 0, + offsetof(Impl_, expired_latched_) - + offsetof(Impl_, assignment_) + + sizeof(Impl_::expired_latched_)); +} +Record::~Record() { + // @@protoc_insertion_point(destructor:xtcp_treatment_journal.v1.Record) + SharedDtor(*this); +} +inline void Record::SharedDtor(MessageLite& self) { + Record& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.error_.Destroy(); + this_._impl_.installed_route_.Destroy(); + this_._impl_.installed_boot_id_.Destroy(); + delete this_._impl_.assignment_; + delete this_._impl_.received_at_; + delete this_._impl_.attempted_at_; + delete this_._impl_.applied_at_; + delete this_._impl_.verified_at_; + delete this_._impl_.removed_at_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Record_class_data_ = + Record::InternalGenerateClassData_(Record_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Record::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Record_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Record_class_data_.tc_table); + return Record_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Record::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Record_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Record_globals_)); + return Record_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Record::ParseTableT_ + Record::_table_ = + Record::InternalGenerateParseTable_(Record_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Record::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment_journal.v1.Record) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + this_._impl_.error_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.installed_route_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.installed_boot_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(this_._impl_.assignment_ != nullptr); + this_._impl_.assignment_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + ABSL_DCHECK(this_._impl_.received_at_ != nullptr); + this_._impl_.received_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(this_._impl_.attempted_at_ != nullptr); + this_._impl_.attempted_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(this_._impl_.applied_at_ != nullptr); + this_._impl_.applied_at_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(this_._impl_.verified_at_ != nullptr); + this_._impl_.verified_at_->Clear(); + } + } + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + ABSL_DCHECK(this_._impl_.removed_at_ != nullptr); + this_._impl_.removed_at_->Clear(); + } + if (BatchCheckHasBit(cached_has_bits, 0x00000e00U)) { + ::memset(&this_._impl_.desired_revision_, 0, + static_cast<::size_t>( + reinterpret_cast(&this_._impl_.expired_latched_) - + reinterpret_cast(&this_._impl_.desired_revision_)) + + sizeof(_impl_.expired_latched_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Record::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Record& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Record::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Record& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment_journal.v1.Record) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // .xtcp_treatment_journal.v1.Assignment assignment = 1 [json_name = "assignment"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.assignment_, this_._impl_.assignment_->GetCachedSize(), target, + stream); + } + + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + if (this_._internal_desired_revision() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_desired_revision(), target); + } + } + + // .xtcp_treatment_journal.v1.ApplyStatus status = 3 [json_name = "status"]; + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + if (this_._internal_status() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_status(), target); + } + } + + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.received_at_, this_._impl_.received_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.attempted_at_, this_._impl_.attempted_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.applied_at_, this_._impl_.applied_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, *this_._impl_.verified_at_, this_._impl_.verified_at_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.removed_at_, this_._impl_.removed_at_->GetCachedSize(), target, + stream); + } + + // string error = 9 [json_name = "error"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_error().empty()) { + const ::std::string& _s = this_._internal_error(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Record.error"); + target = stream->WriteStringMaybeAliased(9, _s, target); + } + } + + // bytes installed_route = 10 [json_name = "installedRoute"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_installed_route().empty()) { + const ::std::string& _s = this_._internal_installed_route(); + target = stream->WriteBytesMaybeAliased(10, _s, target); + } + } + + // string installed_boot_id = 11 [json_name = "installedBootId"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_installed_boot_id().empty()) { + const ::std::string& _s = this_._internal_installed_boot_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Record.installed_boot_id"); + target = stream->WriteStringMaybeAliased(11, _s, target); + } + } + + // bool expired_latched = 12 [json_name = "expiredLatched"]; + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (this_._internal_expired_latched() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 12, this_._internal_expired_latched(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment_journal.v1.Record) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Record::ByteSizeLong(const MessageLite& base) { + const Record& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Record::ByteSizeLong() const { + const Record& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment_journal.v1.Record) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // string error = 9 [json_name = "error"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!this_._internal_error().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_error()); + } + } + // bytes installed_route = 10 [json_name = "installedRoute"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_installed_route().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( + this_._internal_installed_route()); + } + } + // string installed_boot_id = 11 [json_name = "installedBootId"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_installed_boot_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_installed_boot_id()); + } + } + // .xtcp_treatment_journal.v1.Assignment assignment = 1 [json_name = "assignment"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.assignment_); + } + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.received_at_); + } + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.attempted_at_); + } + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.applied_at_); + } + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.verified_at_); + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000f00U)) { + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.removed_at_); + } + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + if (this_._internal_desired_revision() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_desired_revision()); + } + } + // .xtcp_treatment_journal.v1.ApplyStatus status = 3 [json_name = "status"]; + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + if (this_._internal_status() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_status()); + } + } + // bool expired_latched = 12 [json_name = "expiredLatched"]; + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (this_._internal_expired_latched() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Record::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment_journal.v1.Record) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + if (!from._internal_error().empty()) { + _this->_internal_set_error(from._internal_error()); + } else { + if (_this->_impl_.error_.IsDefault()) { + _this->_internal_set_error(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_installed_route().empty()) { + _this->_internal_set_installed_route(from._internal_installed_route()); + } else { + if (_this->_impl_.installed_route_.IsDefault()) { + _this->_internal_set_installed_route(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_installed_boot_id().empty()) { + _this->_internal_set_installed_boot_id(from._internal_installed_boot_id()); + } else { + if (_this->_impl_.installed_boot_id_.IsDefault()) { + _this->_internal_set_installed_boot_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + ABSL_DCHECK(from._impl_.assignment_ != nullptr); + if (_this->_impl_.assignment_ == nullptr) { + _this->_impl_.assignment_ = Super_::CopyConstruct(arena, *from._impl_.assignment_); + } else { + _this->_impl_.assignment_->MergeFrom(*from._impl_.assignment_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + ABSL_DCHECK(from._impl_.received_at_ != nullptr); + if (_this->_impl_.received_at_ == nullptr) { + _this->_impl_.received_at_ = Super_::CopyConstruct(arena, *from._impl_.received_at_); + } else { + _this->_impl_.received_at_->MergeFrom(*from._impl_.received_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + ABSL_DCHECK(from._impl_.attempted_at_ != nullptr); + if (_this->_impl_.attempted_at_ == nullptr) { + _this->_impl_.attempted_at_ = Super_::CopyConstruct(arena, *from._impl_.attempted_at_); + } else { + _this->_impl_.attempted_at_->MergeFrom(*from._impl_.attempted_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(from._impl_.applied_at_ != nullptr); + if (_this->_impl_.applied_at_ == nullptr) { + _this->_impl_.applied_at_ = Super_::CopyConstruct(arena, *from._impl_.applied_at_); + } else { + _this->_impl_.applied_at_->MergeFrom(*from._impl_.applied_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(from._impl_.verified_at_ != nullptr); + if (_this->_impl_.verified_at_ == nullptr) { + _this->_impl_.verified_at_ = Super_::CopyConstruct(arena, *from._impl_.verified_at_); + } else { + _this->_impl_.verified_at_->MergeFrom(*from._impl_.verified_at_); + } + } + } + if (BatchCheckHasBit(cached_has_bits, 0x00000f00U)) { + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + ABSL_DCHECK(from._impl_.removed_at_ != nullptr); + if (_this->_impl_.removed_at_ == nullptr) { + _this->_impl_.removed_at_ = Super_::CopyConstruct(arena, *from._impl_.removed_at_); + } else { + _this->_impl_.removed_at_->MergeFrom(*from._impl_.removed_at_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000200U)) { + if (from._internal_desired_revision() != 0) { + _this->_impl_.desired_revision_ = from._impl_.desired_revision_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000400U)) { + if (from._internal_status() != 0) { + _this->_impl_.status_ = from._impl_.status_; + } + } + if (CheckHasBit(cached_has_bits, 0x00000800U)) { + if (from._internal_expired_latched() != 0) { + _this->_impl_.expired_latched_ = from._impl_.expired_latched_; + } + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Record::CopyFrom(const Record& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment_journal.v1.Record) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Record::InternalSwap(Record* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.error_, &other->_impl_.error_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.installed_route_, &other->_impl_.installed_route_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.installed_boot_id_, &other->_impl_.installed_boot_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Record, _impl_.expired_latched_) + + sizeof(Record::_impl_.expired_latched_) + - PROTOBUF_FIELD_OFFSET(Record, _impl_.assignment_)>( + reinterpret_cast(&_impl_.assignment_), + reinterpret_cast(&other->_impl_.assignment_)); +} + +::google::protobuf::Metadata Record::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// =================================================================== + +void Journal::clear_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.updated_at_ != nullptr) _impl_.updated_at_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); +} +Journal::Journal(::google::protobuf::Arena* PROTOBUF_NULLABLE arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Journal_get_class_data()) { +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:xtcp_treatment_journal.v1.Journal) +} +PROTOBUF_NDEBUG_INLINE Journal::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + [[maybe_unused]] const ::xtcp_treatment_journal::v1::Journal& from_msg) + : _has_bits_{from._has_bits_}, + records_ { + visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment_journal::v1::Journal, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.records_)>() + , arena, from.records_ + } + , + agent_id_(arena, from.agent_id_), + location_(arena, from.location_), + boot_id_(arena, from.boot_id_), + suspension_reason_(arena, from.suspension_reason_), + collection_id_(arena, from.collection_id_) {} + +Journal::Journal( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, + const Journal& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Super_(arena, Journal_get_class_data()) { + +#else // PROTOBUF_CUSTOM_VTABLE + : Super_(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE + Journal* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.desired_ = (CheckHasBit(cached_has_bits, 0x00000040U)) + ? Super_::CopyConstruct(arena, *from._impl_.desired_) + : nullptr; + _impl_.updated_at_ = (CheckHasBit(cached_has_bits, 0x00000080U)) + ? Super_::CopyConstruct(arena, *from._impl_.updated_at_) + : nullptr; + _impl_.locally_suspended_ = from._impl_.locally_suspended_; + + // @@protoc_insertion_point(copy_constructor:xtcp_treatment_journal.v1.Journal) +} +PROTOBUF_NDEBUG_INLINE Journal::Impl_::Impl_( + [[maybe_unused]] ::google::protobuf::internal::InternalVisibility visibility, + [[maybe_unused]] ::google::protobuf::Arena* PROTOBUF_NULLABLE arena) + : records_ { visibility, ::_pbi::InternalMetadataOffset::Build< + ::xtcp_treatment_journal::v1::Journal, + PROTOBUF_FIELD_OFFSET(::xtcp_treatment_journal::v1::Journal, _impl_.records_)>() + } + , + agent_id_(arena), + location_(arena), + boot_id_(arena), + suspension_reason_(arena), + collection_id_(arena) {} + +inline void Journal::SharedCtor(::_pb::Arena* PROTOBUF_NULLABLE arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, desired_), + 0, + offsetof(Impl_, locally_suspended_) - + offsetof(Impl_, desired_) + + sizeof(Impl_::locally_suspended_)); +} +Journal::~Journal() { + // @@protoc_insertion_point(destructor:xtcp_treatment_journal.v1.Journal) + SharedDtor(*this); +} +inline void Journal::SharedDtor(MessageLite& self) { + Journal& this_ = static_cast(self); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.agent_id_.Destroy(); + this_._impl_.location_.Destroy(); + this_._impl_.boot_id_.Destroy(); + this_._impl_.suspension_reason_.Destroy(); + this_._impl_.collection_id_.Destroy(); + delete this_._impl_.desired_; + delete this_._impl_.updated_at_; + this_._impl_.~Impl_(); +} + +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const + ::google::protobuf::internal::ClassDataFull Journal_class_data_ = + Journal::InternalGenerateClassData_(Journal_globals_._default); + +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Journal::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Journal_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Journal_class_data_.tc_table); + return Journal_class_data_.base(); +} +#else +PROTOBUF_ATTRIBUTE_WEAK const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL +Journal::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Journal_globals_); + ::google::protobuf::internal::PrefetchToLocalCache( + ::google::protobuf::internal::MessageGlobalsBase::ToParseTableBase(&Journal_globals_)); + return Journal_globals_.GetClassData(); +} +#endif // !PROTOBUF_MESSAGE_GLOBALS +#ifndef PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_CONSTINIT +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const Journal::ParseTableT_ + Journal::_table_ = + Journal::InternalGenerateParseTable_(Journal_class_data_.base()); +#endif // !PROTOBUF_MESSAGE_GLOBALS +PROTOBUF_NOINLINE void Journal::Clear() { + auto& this_ [[maybe_unused]] = *this; + // @@protoc_insertion_point(message_clear_start:xtcp_treatment_journal.v1.Journal) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _impl_.records_.Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + this_._impl_.agent_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + this_._impl_.location_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + this_._impl_.boot_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + this_._impl_.suspension_reason_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + this_._impl_.collection_id_.ClearNonDefaultToEmpty(); + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(this_._impl_.desired_ != nullptr); + this_._impl_.desired_->Clear(); + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(this_._impl_.updated_at_ != nullptr); + this_._impl_.updated_at_->Clear(); + } + } + this_._impl_.locally_suspended_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::uint8_t* PROTOBUF_NONNULL Journal::_InternalSerialize( + const ::google::protobuf::MessageLite& base, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) { + const Journal& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::uint8_t* PROTOBUF_NONNULL Journal::_InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + const Journal& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + this_.CheckHasBitConsistency(); + } + // @@protoc_insertion_point(serialize_to_array_start:xtcp_treatment_journal.v1.Journal) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // string agent_id = 1 [json_name = "agentId"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + const ::std::string& _s = this_._internal_agent_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Journal.agent_id"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string location = 2 [json_name = "location"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_location().empty()) { + const ::std::string& _s = this_._internal_location(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Journal.location"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + // string boot_id = 3 [json_name = "bootId"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_boot_id().empty()) { + const ::std::string& _s = this_._internal_boot_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Journal.boot_id"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + } + + // .xtcp_treatment_journal.v1.Desired desired = 4 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.desired_, this_._impl_.desired_->GetCachedSize(), target, + stream); + } + + // bool locally_suspended = 5 [json_name = "locallySuspended"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (this_._internal_locally_suspended() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_locally_suspended(), target); + } + } + + // string suspension_reason = 6 [json_name = "suspensionReason"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_suspension_reason().empty()) { + const ::std::string& _s = this_._internal_suspension_reason(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Journal.suspension_reason"); + target = stream->WriteStringMaybeAliased(6, _s, target); + } + } + + // repeated .xtcp_treatment_journal.v1.Record records = 7 [json_name = "records"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + for (unsigned i = 0, n = static_cast( + this_._internal_records_size()); + i < n; i++) { + const auto& repfield = this_._internal_records().Get(i); + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, repfield, repfield.GetCachedSize(), target, + stream); + } + } + + // .google.protobuf.Timestamp updated_at = 8 [json_name = "updatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.updated_at_, this_._impl_.updated_at_->GetCachedSize(), target, + stream); + } + + // string collection_id = 9 [json_name = "collectionId"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (!this_._internal_collection_id().empty()) { + const ::std::string& _s = this_._internal_collection_id(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "xtcp_treatment_journal.v1.Journal.collection_id"); + target = stream->WriteStringMaybeAliased(9, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:xtcp_treatment_journal.v1.Journal) + return target; +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +::size_t Journal::ByteSizeLong(const MessageLite& base) { + const Journal& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE +::size_t Journal::ByteSizeLong() const { + const Journal& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:xtcp_treatment_journal.v1.Journal) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits [[maybe_unused]] = 0; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + // repeated .xtcp_treatment_journal.v1.Record records = 7 [json_name = "records"]; + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + total_size += 1UL * this_._internal_records_size(); + for (const auto& msg : this_._internal_records()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // string agent_id = 1 [json_name = "agentId"]; + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!this_._internal_agent_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_agent_id()); + } + } + // string location = 2 [json_name = "location"]; + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!this_._internal_location().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_location()); + } + } + // string boot_id = 3 [json_name = "bootId"]; + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!this_._internal_boot_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_boot_id()); + } + } + // string suspension_reason = 6 [json_name = "suspensionReason"]; + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!this_._internal_suspension_reason().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_suspension_reason()); + } + } + // string collection_id = 9 [json_name = "collectionId"]; + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (!this_._internal_collection_id().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_collection_id()); + } + } + // .xtcp_treatment_journal.v1.Desired desired = 4 [json_name = "desired"]; + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.desired_); + } + // .google.protobuf.Timestamp updated_at = 8 [json_name = "updatedAt"]; + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.updated_at_); + } + } + { + // bool locally_suspended = 5 [json_name = "locallySuspended"]; + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (this_._internal_locally_suspended() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); +} + +void Journal::MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + if constexpr (::_pbi::DebugHardenCheckHasBitConsistency()) { + from.CheckHasBitConsistency(); + } + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:xtcp_treatment_journal.v1.Journal) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (BatchCheckHasBit(cached_has_bits, 0x000000ffU)) { + if (CheckHasBit(cached_has_bits, 0x00000001U)) { + _this->_internal_mutable_records()->InternalMergeFromWithArena( + ::google::protobuf::MessageLite::internal_visibility(), arena, + from._internal_records()); + } + if (CheckHasBit(cached_has_bits, 0x00000002U)) { + if (!from._internal_agent_id().empty()) { + _this->_internal_set_agent_id(from._internal_agent_id()); + } else { + if (_this->_impl_.agent_id_.IsDefault()) { + _this->_internal_set_agent_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000004U)) { + if (!from._internal_location().empty()) { + _this->_internal_set_location(from._internal_location()); + } else { + if (_this->_impl_.location_.IsDefault()) { + _this->_internal_set_location(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000008U)) { + if (!from._internal_boot_id().empty()) { + _this->_internal_set_boot_id(from._internal_boot_id()); + } else { + if (_this->_impl_.boot_id_.IsDefault()) { + _this->_internal_set_boot_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000010U)) { + if (!from._internal_suspension_reason().empty()) { + _this->_internal_set_suspension_reason(from._internal_suspension_reason()); + } else { + if (_this->_impl_.suspension_reason_.IsDefault()) { + _this->_internal_set_suspension_reason(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000020U)) { + if (!from._internal_collection_id().empty()) { + _this->_internal_set_collection_id(from._internal_collection_id()); + } else { + if (_this->_impl_.collection_id_.IsDefault()) { + _this->_internal_set_collection_id(""); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000040U)) { + ABSL_DCHECK(from._impl_.desired_ != nullptr); + if (_this->_impl_.desired_ == nullptr) { + _this->_impl_.desired_ = Super_::CopyConstruct(arena, *from._impl_.desired_); + } else { + _this->_impl_.desired_->MergeFrom(*from._impl_.desired_); + } + } + if (CheckHasBit(cached_has_bits, 0x00000080U)) { + ABSL_DCHECK(from._impl_.updated_at_ != nullptr); + if (_this->_impl_.updated_at_ == nullptr) { + _this->_impl_.updated_at_ = Super_::CopyConstruct(arena, *from._impl_.updated_at_); + } else { + _this->_impl_.updated_at_->MergeFrom(*from._impl_.updated_at_); + } + } + } + if (CheckHasBit(cached_has_bits, 0x00000100U)) { + if (from._internal_locally_suspended() != 0) { + _this->_impl_.locally_suspended_ = from._impl_.locally_suspended_; + } + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); +} + +void Journal::CopyFrom(const Journal& from) { + // @@protoc_insertion_point(class_specific_copy_from_start:xtcp_treatment_journal.v1.Journal) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + + +void Journal::InternalSwap(Journal* PROTOBUF_RESTRICT PROTOBUF_NONNULL other) { + using ::std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.records_.InternalSwap(&other->_impl_.records_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.agent_id_, &other->_impl_.agent_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.location_, &other->_impl_.location_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.boot_id_, &other->_impl_.boot_id_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.suspension_reason_, &other->_impl_.suspension_reason_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.collection_id_, &other->_impl_.collection_id_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Journal, _impl_.locally_suspended_) + + sizeof(Journal::_impl_.locally_suspended_) + - PROTOBUF_FIELD_OFFSET(Journal, _impl_.desired_)>( + reinterpret_cast(&_impl_.desired_), + reinterpret_cast(&other->_impl_.desired_)); +} + +::google::protobuf::Metadata Journal::GetMetadata() const { + return Super_::GetMetadataImpl(GetClassData()->full()); +} +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment_journal +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type + _static_init2_ [[maybe_unused]] = + (::_pbi::AddDescriptors(&descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto), + ::std::false_type{}); +#include "google/protobuf/port_undef.inc" diff --git a/gen/cpp/xtcp_treatment_journal/v1/journal.pb.h b/gen/cpp/xtcp_treatment_journal/v1/journal.pb.h new file mode 100644 index 000000000..22e236bd3 --- /dev/null +++ b/gen/cpp/xtcp_treatment_journal/v1/journal.pb.h @@ -0,0 +1,4602 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: xtcp_treatment_journal/v1/journal.proto +// Protobuf C++ Version: 7.36.2 + +#ifndef xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto_2epb_2eh +#define xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto_2epb_2eh + +#include +#include +#include +#include + +// clang-format off +#include "google/protobuf/runtime_version.h" +#if PROTOBUF_VERSION != 7036002 +#error "Protobuf C++ gencode is built with an incompatible version of" +#error "Protobuf C++ headers/runtime. See" +#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" +#endif +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/generated_enum_reflection.h" +#include "google/protobuf/unknown_field_set.h" +#include "google/protobuf/timestamp.pb.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto + +// Internal implementation detail -- do not use these members. +struct TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto { + static const ::uint32_t offsets[]; +}; +extern "C" { +extern const ::google::protobuf::internal::DescriptorTable descriptor_table_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto; +} // extern "C" +namespace xtcp_treatment_journal { +namespace v1 { +enum ApplyStatus : int; +extern const uint32_t ApplyStatus_internal_data_[]; +enum AssignmentMode : int; +extern const uint32_t AssignmentMode_internal_data_[]; +class Assignment; +struct AssignmentGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern AssignmentGlobalsTypeInternal Assignment_globals_; +extern const ::google::protobuf::internal::ClassDataFull Assignment_class_data_; +#else +extern const AssignmentGlobalsTypeInternal Assignment_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Desired; +struct DesiredGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern DesiredGlobalsTypeInternal Desired_globals_; +extern const ::google::protobuf::internal::ClassDataFull Desired_class_data_; +#else +extern const DesiredGlobalsTypeInternal Desired_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Journal; +struct JournalGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern JournalGlobalsTypeInternal Journal_globals_; +extern const ::google::protobuf::internal::ClassDataFull Journal_class_data_; +#else +extern const JournalGlobalsTypeInternal Journal_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Record; +struct RecordGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern RecordGlobalsTypeInternal Record_globals_; +extern const ::google::protobuf::internal::ClassDataFull Record_class_data_; +#else +extern const RecordGlobalsTypeInternal Record_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class TCPSettings; +struct TCPSettingsGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern TCPSettingsGlobalsTypeInternal TCPSettings_globals_; +extern const ::google::protobuf::internal::ClassDataFull TCPSettings_class_data_; +#else +extern const TCPSettingsGlobalsTypeInternal TCPSettings_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +class Treatment; +struct TreatmentGlobalsTypeInternal; +#ifndef PROTOBUF_MESSAGE_GLOBALS +extern TreatmentGlobalsTypeInternal Treatment_globals_; +extern const ::google::protobuf::internal::ClassDataFull Treatment_class_data_; +#else +extern const TreatmentGlobalsTypeInternal Treatment_globals_; +#endif // PROTOBUF_MESSAGE_GLOBALS +} // namespace v1 +} // namespace xtcp_treatment_journal +namespace google { +namespace protobuf { +template <> +internal::EnumTraitsT<::xtcp_treatment_journal::v1::ApplyStatus_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment_journal::v1::ApplyStatus>; +template <> +internal::EnumTraitsT<::xtcp_treatment_journal::v1::AssignmentMode_internal_data_> + internal::EnumTraitsImpl::value<::xtcp_treatment_journal::v1::AssignmentMode>; +} // namespace protobuf +} // namespace google + +namespace xtcp_treatment_journal { +namespace v1 { +enum AssignmentMode : int { + ASSIGNMENT_MODE_UNSPECIFIED = 0, + ASSIGNMENT_MODE_TRIAL = 1, + ASSIGNMENT_MODE_STABLE = 2, + ASSIGNMENT_MODE_SUSPENDED = 3, + ASSIGNMENT_MODE_RETIRED = 4, + AssignmentMode_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + AssignmentMode_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t AssignmentMode_internal_data_[]; +inline constexpr AssignmentMode AssignmentMode_MIN = + static_cast(0); +inline constexpr AssignmentMode AssignmentMode_MAX = + static_cast(4); +[[nodiscard]] inline bool AssignmentMode_IsValid(int value) { + return 0 <= value && value <= 4; +} +inline constexpr int AssignmentMode_ARRAYSIZE = 4 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +AssignmentMode_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(AssignmentMode) { + return AssignmentMode_descriptor(); +} +template +[[nodiscard]] const ::std::string& AssignmentMode_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to AssignmentMode_Name()."); + return AssignmentMode_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& AssignmentMode_Name(AssignmentMode value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool AssignmentMode_Parse( + ::absl::string_view name, AssignmentMode* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(AssignmentMode_descriptor(), name, + value); +} +enum ApplyStatus : int { + APPLY_STATUS_UNSPECIFIED = 0, + APPLY_STATUS_PENDING = 1, + APPLY_STATUS_VERIFIED = 2, + APPLY_STATUS_REMOVED = 3, + APPLY_STATUS_EXPIRED = 4, + APPLY_STATUS_FAILED = 5, + ApplyStatus_INT_MIN_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::min(), + ApplyStatus_INT_MAX_SENTINEL_DO_NOT_USE_ = + ::std::numeric_limits<::int32_t>::max(), +}; + +extern const uint32_t ApplyStatus_internal_data_[]; +inline constexpr ApplyStatus ApplyStatus_MIN = + static_cast(0); +inline constexpr ApplyStatus ApplyStatus_MAX = + static_cast(5); +[[nodiscard]] inline bool ApplyStatus_IsValid(int value) { + return 0 <= value && value <= 5; +} +inline constexpr int ApplyStatus_ARRAYSIZE = 5 + 1; +[[nodiscard]] const ::google::protobuf::EnumDescriptor* PROTOBUF_NONNULL +ApplyStatus_descriptor(); +[[nodiscard]] inline auto ProtobufInternalGetEnumDescriptor(ApplyStatus) { + return ApplyStatus_descriptor(); +} +template +[[nodiscard]] const ::std::string& ApplyStatus_Name(T value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to ApplyStatus_Name()."); + return ApplyStatus_Name(static_cast(value)); +} +template <> +[[nodiscard]] inline const ::std::string& ApplyStatus_Name(ApplyStatus value) { + return ::google::protobuf::internal::NameOfDenseEnum( + static_cast(value)); +} +[[nodiscard]] inline bool ApplyStatus_Parse( + ::absl::string_view name, ApplyStatus* PROTOBUF_NONNULL value) { + return ::google::protobuf::internal::ParseNamedEnum(ApplyStatus_descriptor(), name, + value); +} +using ::google::protobuf::internal::generated_enum::AbslParseFlag; +using ::google::protobuf::internal::generated_enum::AbslUnparseFlag; + +// =================================================================== + + +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED TCPSettings final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment_journal.v1.TCPSettings) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline TCPSettings() : TCPSettings(nullptr) {} + ~TCPSettings() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(TCPSettings* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(TCPSettings)); + } +#endif + + template + explicit constexpr TCPSettings(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline TCPSettings(const TCPSettings& from) : TCPSettings(nullptr, from) {} + inline TCPSettings(TCPSettings&& from) noexcept : TCPSettings(nullptr, ::std::move(from)) {} + inline TCPSettings& operator=(const TCPSettings& from) { + CopyFrom(from); + return *this; + } + inline TCPSettings& operator=(TCPSettings&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const TCPSettings& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&TCPSettings_globals_); + } + static constexpr int kIndexInFileMessages = 0; + friend void swap(TCPSettings& a, TCPSettings& b) { a.Swap(&b); } + inline void Swap(TCPSettings* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TCPSettings* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] TCPSettings* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const TCPSettings& from); + using Super_::MergeFrom; + void MergeFrom(const TCPSettings& from) { TCPSettings::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(TCPSettings* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment_journal.v1.TCPSettings"; } + + explicit TCPSettings(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + TCPSettings(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const TCPSettings& from); + TCPSettings( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, TCPSettings&& from) noexcept + : TCPSettings(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kCongestionControlFieldNumber = 1, + kRtoMinMsFieldNumber = 3, + kInitialCongestionWindowFieldNumber = 4, + kInitialReceiveWindowFieldNumber = 5, + kCongestionLockFieldNumber = 2, + kQuickAckFieldNumber = 6, + kEcnFieldNumber = 7, + }; + // optional string congestion_control = 1 [json_name = "congestionControl"]; + [[nodiscard]] bool has_congestion_control() const; + void clear_congestion_control() ; + [[nodiscard]] const ::std::string& congestion_control() const; + template + void set_congestion_control(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_congestion_control(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_congestion_control(); + void set_allocated_congestion_control(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_congestion_control() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_congestion_control(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_congestion_control(); + + public: + // optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs"]; + [[nodiscard]] bool has_rto_min_ms() const; + void clear_rto_min_ms() ; + [[nodiscard]] ::uint32_t rto_min_ms() const; + void set_rto_min_ms(::uint32_t value); + + private: + ::uint32_t _internal_rto_min_ms() const; + void _internal_set_rto_min_ms(::uint32_t value); + + public: + // optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow"]; + [[nodiscard]] bool has_initial_congestion_window() const; + void clear_initial_congestion_window() ; + [[nodiscard]] ::uint32_t initial_congestion_window() const; + void set_initial_congestion_window(::uint32_t value); + + private: + ::uint32_t _internal_initial_congestion_window() const; + void _internal_set_initial_congestion_window(::uint32_t value); + + public: + // optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow"]; + [[nodiscard]] bool has_initial_receive_window() const; + void clear_initial_receive_window() ; + [[nodiscard]] ::uint32_t initial_receive_window() const; + void set_initial_receive_window(::uint32_t value); + + private: + ::uint32_t _internal_initial_receive_window() const; + void _internal_set_initial_receive_window(::uint32_t value); + + public: + // bool congestion_lock = 2 [json_name = "congestionLock"]; + void clear_congestion_lock() ; + [[nodiscard]] bool congestion_lock() const; + void set_congestion_lock(bool value); + + private: + bool _internal_congestion_lock() const; + void _internal_set_congestion_lock(bool value); + + public: + // optional bool quick_ack = 6 [json_name = "quickAck"]; + [[nodiscard]] bool has_quick_ack() const; + void clear_quick_ack() ; + [[nodiscard]] bool quick_ack() const; + void set_quick_ack(bool value); + + private: + bool _internal_quick_ack() const; + void _internal_set_quick_ack(bool value); + + public: + // optional bool ecn = 7 [json_name = "ecn"]; + [[nodiscard]] bool has_ecn() const; + void clear_ecn() ; + [[nodiscard]] bool ecn() const; + void set_ecn(bool value); + + private: + bool _internal_ecn() const; + void _internal_set_ecn(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment_journal.v1.TCPSettings) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 7, + 0, 64, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const TCPSettings& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr congestion_control_; + ::uint32_t rto_min_ms_; + ::uint32_t initial_congestion_window_; + ::uint32_t initial_receive_window_; + bool congestion_lock_; + bool quick_ack_; + bool ecn_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Treatment final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment_journal.v1.Treatment) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Treatment() : Treatment(nullptr) {} + ~Treatment() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Treatment* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Treatment)); + } +#endif + + template + explicit constexpr Treatment(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Treatment(const Treatment& from) : Treatment(nullptr, from) {} + inline Treatment(Treatment&& from) noexcept : Treatment(nullptr, ::std::move(from)) {} + inline Treatment& operator=(const Treatment& from) { + CopyFrom(from); + return *this; + } + inline Treatment& operator=(Treatment&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Treatment& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Treatment_globals_); + } + static constexpr int kIndexInFileMessages = 1; + friend void swap(Treatment& a, Treatment& b) { a.Swap(&b); } + inline void Swap(Treatment* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Treatment* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Treatment* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Treatment& from); + using Super_::MergeFrom; + void MergeFrom(const Treatment& from) { Treatment::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Treatment* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment_journal.v1.Treatment"; } + + explicit Treatment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Treatment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Treatment& from); + Treatment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Treatment&& from) noexcept + : Treatment(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kIdFieldNumber = 1, + kDestinationFieldNumber = 3, + kSettingsFieldNumber = 4, + kRevisionFieldNumber = 2, + kEcnFabricVerifiedFieldNumber = 5, + }; + // string id = 1 [json_name = "id"]; + void clear_id() ; + [[nodiscard]] const ::std::string& id() const; + template + void set_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_id(); + void set_allocated_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_id(); + + public: + // string destination = 3 [json_name = "destination"]; + void clear_destination() ; + [[nodiscard]] const ::std::string& destination() const; + template + void set_destination(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_destination(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_destination(); + void set_allocated_destination(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_destination() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_destination(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_destination(); + + public: + // .xtcp_treatment_journal.v1.TCPSettings settings = 4 [json_name = "settings"]; + [[nodiscard]] bool has_settings() const; + void clear_settings() ; + [[nodiscard]] const ::xtcp_treatment_journal::v1::TCPSettings& settings() const; + [[nodiscard]] ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE release_settings(); + ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NONNULL mutable_settings(); + void set_allocated_settings(::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_settings(::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE value); + ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE unsafe_arena_release_settings(); + + private: + const ::xtcp_treatment_journal::v1::TCPSettings& _internal_settings() const; + ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NONNULL _internal_mutable_settings(); + + public: + // uint64 revision = 2 [json_name = "revision"]; + void clear_revision() ; + [[nodiscard]] ::uint64_t revision() const; + void set_revision(::uint64_t value); + + private: + ::uint64_t _internal_revision() const; + void _internal_set_revision(::uint64_t value); + + public: + // bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; + void clear_ecn_fabric_verified() ; + [[nodiscard]] bool ecn_fabric_verified() const; + void set_ecn_fabric_verified(bool value); + + private: + bool _internal_ecn_fabric_verified() const; + void _internal_set_ecn_fabric_verified(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment_journal.v1.Treatment) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 5, + 1, 57, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Treatment& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr id_; + ::google::protobuf::internal::ArenaStringPtr destination_; + ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE settings_; + ::uint64_t revision_; + bool ecn_fabric_verified_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Assignment final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment_journal.v1.Assignment) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Assignment() : Assignment(nullptr) {} + ~Assignment() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Assignment* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Assignment)); + } +#endif + + template + explicit constexpr Assignment(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Assignment(const Assignment& from) : Assignment(nullptr, from) {} + inline Assignment(Assignment&& from) noexcept : Assignment(nullptr, ::std::move(from)) {} + inline Assignment& operator=(const Assignment& from) { + CopyFrom(from); + return *this; + } + inline Assignment& operator=(Assignment&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Assignment& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Assignment_globals_); + } + static constexpr int kIndexInFileMessages = 2; + friend void swap(Assignment& a, Assignment& b) { a.Swap(&b); } + inline void Swap(Assignment* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Assignment* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Assignment* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Assignment& from); + using Super_::MergeFrom; + void MergeFrom(const Assignment& from) { Assignment::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Assignment* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment_journal.v1.Assignment"; } + + explicit Assignment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Assignment(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Assignment& from); + Assignment( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Assignment&& from) noexcept + : Assignment(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kExperimentIdFieldNumber = 1, + kTreatmentFieldNumber = 2, + kLeaseExpiresAtFieldNumber = 4, + kPredecessorFieldNumber = 5, + kGenerationFieldNumber = 6, + kModeFieldNumber = 3, + }; + // string experiment_id = 1 [json_name = "experimentId"]; + void clear_experiment_id() ; + [[nodiscard]] const ::std::string& experiment_id() const; + template + void set_experiment_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_experiment_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_experiment_id(); + void set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_experiment_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_experiment_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_experiment_id(); + + public: + // .xtcp_treatment_journal.v1.Treatment treatment = 2 [json_name = "treatment"]; + [[nodiscard]] bool has_treatment() const; + void clear_treatment() ; + [[nodiscard]] const ::xtcp_treatment_journal::v1::Treatment& treatment() const; + [[nodiscard]] ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE release_treatment(); + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL mutable_treatment(); + void set_allocated_treatment(::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_treatment(::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value); + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE unsafe_arena_release_treatment(); + + private: + const ::xtcp_treatment_journal::v1::Treatment& _internal_treatment() const; + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL _internal_mutable_treatment(); + + public: + // .google.protobuf.Timestamp lease_expires_at = 4 [json_name = "leaseExpiresAt"]; + [[nodiscard]] bool has_lease_expires_at() const; + void clear_lease_expires_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& lease_expires_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_lease_expires_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_lease_expires_at(); + void set_allocated_lease_expires_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_lease_expires_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_lease_expires_at(); + + private: + const ::google::protobuf::Timestamp& _internal_lease_expires_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_lease_expires_at(); + + public: + // .xtcp_treatment_journal.v1.Treatment predecessor = 5 [json_name = "predecessor"]; + [[nodiscard]] bool has_predecessor() const; + void clear_predecessor() ; + [[nodiscard]] const ::xtcp_treatment_journal::v1::Treatment& predecessor() const; + [[nodiscard]] ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE release_predecessor(); + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL mutable_predecessor(); + void set_allocated_predecessor(::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_predecessor(::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value); + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE unsafe_arena_release_predecessor(); + + private: + const ::xtcp_treatment_journal::v1::Treatment& _internal_predecessor() const; + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL _internal_mutable_predecessor(); + + public: + // uint64 generation = 6 [json_name = "generation"]; + void clear_generation() ; + [[nodiscard]] ::uint64_t generation() const; + void set_generation(::uint64_t value); + + private: + ::uint64_t _internal_generation() const; + void _internal_set_generation(::uint64_t value); + + public: + // .xtcp_treatment_journal.v1.AssignmentMode mode = 3 [json_name = "mode"]; + void clear_mode() ; + [[nodiscard]] ::xtcp_treatment_journal::v1::AssignmentMode mode() const; + void set_mode(::xtcp_treatment_journal::v1::AssignmentMode value); + + private: + ::xtcp_treatment_journal::v1::AssignmentMode _internal_mode() const; + void _internal_set_mode(::xtcp_treatment_journal::v1::AssignmentMode value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment_journal.v1.Assignment) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<3, 6, + 3, 58, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Assignment& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr experiment_id_; + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE treatment_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE lease_expires_at_; + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE predecessor_; + ::uint64_t generation_; + int mode_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Record final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment_journal.v1.Record) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Record() : Record(nullptr) {} + ~Record() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Record* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Record)); + } +#endif + + template + explicit constexpr Record(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Record(const Record& from) : Record(nullptr, from) {} + inline Record(Record&& from) noexcept : Record(nullptr, ::std::move(from)) {} + inline Record& operator=(const Record& from) { + CopyFrom(from); + return *this; + } + inline Record& operator=(Record&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Record& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Record_globals_); + } + static constexpr int kIndexInFileMessages = 4; + friend void swap(Record& a, Record& b) { a.Swap(&b); } + inline void Swap(Record* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Record* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Record* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Record& from); + using Super_::MergeFrom; + void MergeFrom(const Record& from) { Record::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Record* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment_journal.v1.Record"; } + + explicit Record(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Record(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Record& from); + Record( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Record&& from) noexcept + : Record(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kErrorFieldNumber = 9, + kInstalledRouteFieldNumber = 10, + kInstalledBootIdFieldNumber = 11, + kAssignmentFieldNumber = 1, + kReceivedAtFieldNumber = 4, + kAttemptedAtFieldNumber = 5, + kAppliedAtFieldNumber = 6, + kVerifiedAtFieldNumber = 7, + kRemovedAtFieldNumber = 8, + kDesiredRevisionFieldNumber = 2, + kStatusFieldNumber = 3, + kExpiredLatchedFieldNumber = 12, + }; + // string error = 9 [json_name = "error"]; + void clear_error() ; + [[nodiscard]] const ::std::string& error() const; + template + void set_error(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_error(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_error(); + void set_allocated_error(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_error() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_error(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_error(); + + public: + // bytes installed_route = 10 [json_name = "installedRoute"]; + void clear_installed_route() ; + [[nodiscard]] const ::std::string& installed_route() const; + template + void set_installed_route(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_installed_route(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_installed_route(); + void set_allocated_installed_route(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_installed_route() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_installed_route(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_installed_route(); + + public: + // string installed_boot_id = 11 [json_name = "installedBootId"]; + void clear_installed_boot_id() ; + [[nodiscard]] const ::std::string& installed_boot_id() const; + template + void set_installed_boot_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_installed_boot_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_installed_boot_id(); + void set_allocated_installed_boot_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_installed_boot_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_installed_boot_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_installed_boot_id(); + + public: + // .xtcp_treatment_journal.v1.Assignment assignment = 1 [json_name = "assignment"]; + [[nodiscard]] bool has_assignment() const; + void clear_assignment() ; + [[nodiscard]] const ::xtcp_treatment_journal::v1::Assignment& assignment() const; + [[nodiscard]] ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE release_assignment(); + ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL mutable_assignment(); + void set_allocated_assignment(::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_assignment(::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE value); + ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE unsafe_arena_release_assignment(); + + private: + const ::xtcp_treatment_journal::v1::Assignment& _internal_assignment() const; + ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL _internal_mutable_assignment(); + + public: + // .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; + [[nodiscard]] bool has_received_at() const; + void clear_received_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& received_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_received_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_received_at(); + void set_allocated_received_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_received_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_received_at(); + + private: + const ::google::protobuf::Timestamp& _internal_received_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_received_at(); + + public: + // .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; + [[nodiscard]] bool has_attempted_at() const; + void clear_attempted_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& attempted_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_attempted_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_attempted_at(); + void set_allocated_attempted_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_attempted_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_attempted_at(); + + private: + const ::google::protobuf::Timestamp& _internal_attempted_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_attempted_at(); + + public: + // .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; + [[nodiscard]] bool has_applied_at() const; + void clear_applied_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& applied_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_applied_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_applied_at(); + void set_allocated_applied_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_applied_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_applied_at(); + + private: + const ::google::protobuf::Timestamp& _internal_applied_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_applied_at(); + + public: + // .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; + [[nodiscard]] bool has_verified_at() const; + void clear_verified_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& verified_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_verified_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_verified_at(); + void set_allocated_verified_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_verified_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_verified_at(); + + private: + const ::google::protobuf::Timestamp& _internal_verified_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_verified_at(); + + public: + // .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; + [[nodiscard]] bool has_removed_at() const; + void clear_removed_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& removed_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_removed_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_removed_at(); + void set_allocated_removed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_removed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_removed_at(); + + private: + const ::google::protobuf::Timestamp& _internal_removed_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_removed_at(); + + public: + // uint64 desired_revision = 2 [json_name = "desiredRevision"]; + void clear_desired_revision() ; + [[nodiscard]] ::uint64_t desired_revision() const; + void set_desired_revision(::uint64_t value); + + private: + ::uint64_t _internal_desired_revision() const; + void _internal_set_desired_revision(::uint64_t value); + + public: + // .xtcp_treatment_journal.v1.ApplyStatus status = 3 [json_name = "status"]; + void clear_status() ; + [[nodiscard]] ::xtcp_treatment_journal::v1::ApplyStatus status() const; + void set_status(::xtcp_treatment_journal::v1::ApplyStatus value); + + private: + ::xtcp_treatment_journal::v1::ApplyStatus _internal_status() const; + void _internal_set_status(::xtcp_treatment_journal::v1::ApplyStatus value); + + public: + // bool expired_latched = 12 [json_name = "expiredLatched"]; + void clear_expired_latched() ; + [[nodiscard]] bool expired_latched() const; + void set_expired_latched(bool value); + + private: + bool _internal_expired_latched() const; + void _internal_set_expired_latched(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment_journal.v1.Record) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<4, 12, + 6, 71, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Record& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::ArenaStringPtr error_; + ::google::protobuf::internal::ArenaStringPtr installed_route_; + ::google::protobuf::internal::ArenaStringPtr installed_boot_id_; + ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE assignment_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE received_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE attempted_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE applied_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE verified_at_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE removed_at_; + ::uint64_t desired_revision_; + int status_; + bool expired_latched_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Desired final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment_journal.v1.Desired) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Desired() : Desired(nullptr) {} + ~Desired() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Desired* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Desired)); + } +#endif + + template + explicit constexpr Desired(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Desired(const Desired& from) : Desired(nullptr, from) {} + inline Desired(Desired&& from) noexcept : Desired(nullptr, ::std::move(from)) {} + inline Desired& operator=(const Desired& from) { + CopyFrom(from); + return *this; + } + inline Desired& operator=(Desired&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Desired& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Desired_globals_); + } + static constexpr int kIndexInFileMessages = 3; + friend void swap(Desired& a, Desired& b) { a.Swap(&b); } + inline void Swap(Desired* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Desired* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Desired* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Desired& from); + using Super_::MergeFrom; + void MergeFrom(const Desired& from) { Desired::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Desired* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment_journal.v1.Desired"; } + + explicit Desired(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Desired(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Desired& from); + Desired( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Desired&& from) noexcept + : Desired(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kAssignmentsFieldNumber = 4, + kIssuedAtFieldNumber = 3, + kRevisionFieldNumber = 1, + kSuspendedFieldNumber = 2, + }; + // repeated .xtcp_treatment_journal.v1.Assignment assignments = 4 [json_name = "assignments"]; + [[nodiscard]] int assignments_size() const; + private: + int _internal_assignments_size() const; + + public: + void clear_assignments() ; + [[nodiscard]] const ::xtcp_treatment_journal::v1::Assignment& assignments(int index) const; + [[nodiscard]] ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL mutable_assignments(int index); + ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL add_assignments(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>& + assignments() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>* PROTOBUF_NONNULL + mutable_assignments(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>& _internal_assignments() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>* PROTOBUF_NONNULL _internal_mutable_assignments(); + + public: + // .google.protobuf.Timestamp issued_at = 3 [json_name = "issuedAt"]; + [[nodiscard]] bool has_issued_at() const; + void clear_issued_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& issued_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_issued_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_issued_at(); + void set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_issued_at(); + + private: + const ::google::protobuf::Timestamp& _internal_issued_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_issued_at(); + + public: + // uint64 revision = 1 [json_name = "revision"]; + void clear_revision() ; + [[nodiscard]] ::uint64_t revision() const; + void set_revision(::uint64_t value); + + private: + ::uint64_t _internal_revision() const; + void _internal_set_revision(::uint64_t value); + + public: + // bool suspended = 2 [json_name = "suspended"]; + void clear_suspended() ; + [[nodiscard]] bool suspended() const; + void set_suspended(bool value); + + private: + bool _internal_suspended() const; + void _internal_set_suspended(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment_journal.v1.Desired) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<2, 4, + 2, 0, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Desired& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment_journal::v1::Assignment > assignments_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE issued_at_; + ::uint64_t revision_; + bool suspended_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED Journal final : public ::google::protobuf::Message +/* @@protoc_insertion_point(class_definition:xtcp_treatment_journal.v1.Journal) */ { + using Super_ = ::google::protobuf::Message; + + public: + inline Journal() : Journal(nullptr) {} + ~Journal() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Journal* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Journal)); + } +#endif + + template + explicit constexpr Journal(::google::protobuf::internal::ConstantInitialized, + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL + class_data); + + inline Journal(const Journal& from) : Journal(nullptr, from) {} + inline Journal(Journal&& from) noexcept : Journal(nullptr, ::std::move(from)) {} + inline Journal& operator=(const Journal& from) { + CopyFrom(from); + return *this; + } + inline Journal& operator=(Journal&& from) noexcept { + if (this == &from) return *this; + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + [[nodiscard]] inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + [[nodiscard]] inline ::google::protobuf::UnknownFieldSet* PROTOBUF_NONNULL + mutable_unknown_fields() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL descriptor() { + return GetDescriptor(); + } + [[nodiscard]] static const ::google::protobuf::Descriptor* PROTOBUF_NONNULL + GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + [[nodiscard]] static const ::google::protobuf::Reflection* PROTOBUF_NONNULL GetReflection() { + return default_instance().GetMetadata().reflection; + } + [[nodiscard]] static const Journal& default_instance() { + return *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance(&Journal_globals_); + } + static constexpr int kIndexInFileMessages = 5; + friend void swap(Journal& a, Journal& b) { a.Swap(&b); } + inline void Swap(Journal* PROTOBUF_NONNULL other) { + if (other == this) return; + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Journal* PROTOBUF_NONNULL other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + [[nodiscard]] Journal* PROTOBUF_NONNULL + New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const { + return Super_::DefaultConstruct(arena); + } + using Super_::CopyFrom; + void CopyFrom(const Journal& from); + using Super_::MergeFrom; + void MergeFrom(const Journal& from) { Journal::MergeImpl(*this, from); } + + private: + static void MergeImpl(::google::protobuf::MessageLite& to_msg, + const ::google::protobuf::MessageLite& from_msg); + + public: + [[nodiscard]] bool IsInitialized() const { + return true; + } + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + [[nodiscard]] static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + [[nodiscard]] static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream); + + public: + [[nodiscard]] ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] ::size_t ByteSizeLong() const final; + [[nodiscard]] ::uint8_t* PROTOBUF_NONNULL _InternalSerialize( + ::uint8_t* PROTOBUF_NONNULL target, + ::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE + [[nodiscard]] int GetCachedSize() const { + return _impl_._cached_size_.Get(); + } + + private: + void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static void SharedDtor(MessageLite& self); + void InternalSwap(Journal* PROTOBUF_NONNULL other); + private: + static ::absl::string_view FullMessageName() { return "xtcp_treatment_journal.v1.Journal"; } + + explicit Journal(::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + Journal(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Journal& from); + Journal( + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, Journal&& from) noexcept + : Journal(arena) { + *this = ::std::move(from); + } + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL; + static void* PROTOBUF_NONNULL PlacementNew_( + const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + static constexpr auto InternalNewImpl_(); + + public: + static constexpr auto InternalGenerateClassData_( + const MessageLite& prototype, + const ::google::protobuf::internal::TcParseTableBase* PROTOBUF_NULLABLE tc_table = nullptr); + + [[nodiscard]] ::google::protobuf::Metadata GetMetadata() const; + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + enum : int { + kRecordsFieldNumber = 7, + kAgentIdFieldNumber = 1, + kLocationFieldNumber = 2, + kBootIdFieldNumber = 3, + kSuspensionReasonFieldNumber = 6, + kCollectionIdFieldNumber = 9, + kDesiredFieldNumber = 4, + kUpdatedAtFieldNumber = 8, + kLocallySuspendedFieldNumber = 5, + }; + // repeated .xtcp_treatment_journal.v1.Record records = 7 [json_name = "records"]; + [[nodiscard]] int records_size() const; + private: + int _internal_records_size() const; + + public: + void clear_records() ; + [[nodiscard]] const ::xtcp_treatment_journal::v1::Record& records(int index) const; + [[nodiscard]] ::xtcp_treatment_journal::v1::Record* PROTOBUF_NONNULL mutable_records(int index); + ::xtcp_treatment_journal::v1::Record* PROTOBUF_NONNULL add_records(); + [[nodiscard]] const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>& + records() const; + [[nodiscard]] ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>* PROTOBUF_NONNULL + mutable_records(); + + private: + const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>& _internal_records() const; + ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>* PROTOBUF_NONNULL _internal_mutable_records(); + + public: + // string agent_id = 1 [json_name = "agentId"]; + void clear_agent_id() ; + [[nodiscard]] const ::std::string& agent_id() const; + template + void set_agent_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_agent_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_agent_id(); + void set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_agent_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_agent_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_agent_id(); + + public: + // string location = 2 [json_name = "location"]; + void clear_location() ; + [[nodiscard]] const ::std::string& location() const; + template + void set_location(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_location(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_location(); + void set_allocated_location(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_location() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_location(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_location(); + + public: + // string boot_id = 3 [json_name = "bootId"]; + void clear_boot_id() ; + [[nodiscard]] const ::std::string& boot_id() const; + template + void set_boot_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_boot_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_boot_id(); + void set_allocated_boot_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_boot_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_boot_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_boot_id(); + + public: + // string suspension_reason = 6 [json_name = "suspensionReason"]; + void clear_suspension_reason() ; + [[nodiscard]] const ::std::string& suspension_reason() const; + template + void set_suspension_reason(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_suspension_reason(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_suspension_reason(); + void set_allocated_suspension_reason(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_suspension_reason() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_suspension_reason(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_suspension_reason(); + + public: + // string collection_id = 9 [json_name = "collectionId"]; + void clear_collection_id() ; + [[nodiscard]] const ::std::string& collection_id() const; + template + void set_collection_id(Arg_&& arg, Args_... args); + ::std::string* PROTOBUF_NONNULL mutable_collection_id(); + [[nodiscard]] ::std::string* PROTOBUF_NULLABLE release_collection_id(); + void set_allocated_collection_id(::std::string* PROTOBUF_NULLABLE value); + + private: + const ::std::string& _internal_collection_id() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_collection_id(const ::std::string& value); + ::std::string* PROTOBUF_NONNULL _internal_mutable_collection_id(); + + public: + // .xtcp_treatment_journal.v1.Desired desired = 4 [json_name = "desired"]; + [[nodiscard]] bool has_desired() const; + void clear_desired() ; + [[nodiscard]] const ::xtcp_treatment_journal::v1::Desired& desired() const; + [[nodiscard]] ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE release_desired(); + ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NONNULL mutable_desired(); + void set_allocated_desired(::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_desired(::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE value); + ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE unsafe_arena_release_desired(); + + private: + const ::xtcp_treatment_journal::v1::Desired& _internal_desired() const; + ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NONNULL _internal_mutable_desired(); + + public: + // .google.protobuf.Timestamp updated_at = 8 [json_name = "updatedAt"]; + [[nodiscard]] bool has_updated_at() const; + void clear_updated_at() ; + [[nodiscard]] const ::google::protobuf::Timestamp& updated_at() const; + [[nodiscard]] ::google::protobuf::Timestamp* PROTOBUF_NULLABLE release_updated_at(); + ::google::protobuf::Timestamp* PROTOBUF_NONNULL mutable_updated_at(); + void set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + void unsafe_arena_set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value); + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE unsafe_arena_release_updated_at(); + + private: + const ::google::protobuf::Timestamp& _internal_updated_at() const; + ::google::protobuf::Timestamp* PROTOBUF_NONNULL _internal_mutable_updated_at(); + + public: + // bool locally_suspended = 5 [json_name = "locallySuspended"]; + void clear_locally_suspended() ; + [[nodiscard]] bool locally_suspended() const; + void set_locally_suspended(bool value); + + private: + bool _internal_locally_suspended() const; + void _internal_set_locally_suspended(bool value); + + public: + // @@protoc_insertion_point(class_scope:xtcp_treatment_journal.v1.Journal) + private: + class _Internal; + using ParseTableT_ = + ::google::protobuf::internal::TcParseTable<4, 9, + 3, 103, + 2>; + static constexpr ParseTableT_ InternalGenerateParseTable_( + const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL class_data); + friend class ::google::protobuf::internal::TcParser; + #ifndef PROTOBUF_MESSAGE_GLOBALS + static const ParseTableT_ _table_; + #endif + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + friend ::google::protobuf::internal::PrivateAccess; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena); + inline explicit Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from, + const Journal& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::RepeatedPtrField< ::xtcp_treatment_journal::v1::Record > records_; + ::google::protobuf::internal::ArenaStringPtr agent_id_; + ::google::protobuf::internal::ArenaStringPtr location_; + ::google::protobuf::internal::ArenaStringPtr boot_id_; + ::google::protobuf::internal::ArenaStringPtr suspension_reason_; + ::google::protobuf::internal::ArenaStringPtr collection_id_; + ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE desired_; + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE updated_at_; + bool locally_suspended_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// TCPSettings + +// optional string congestion_control = 1 [json_name = "congestionControl"]; +inline bool TCPSettings::has_congestion_control() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000001U); + return value; +} +inline void TCPSettings::clear_congestion_control() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_control_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& TCPSettings::congestion_control() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.TCPSettings.congestion_control) + return _internal_congestion_control(); +} +template +PROTOBUF_ALWAYS_INLINE void TCPSettings::set_congestion_control(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.congestion_control_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.TCPSettings.congestion_control) +} +inline ::std::string* PROTOBUF_NONNULL TCPSettings::mutable_congestion_control() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_congestion_control(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.TCPSettings.congestion_control) + return _s; +} +inline const ::std::string& TCPSettings::_internal_congestion_control() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.congestion_control_.Get(); +} +inline void TCPSettings::_internal_set_congestion_control(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_control_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL TCPSettings::_internal_mutable_congestion_control() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.congestion_control_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE TCPSettings::release_congestion_control() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.TCPSettings.congestion_control) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.congestion_control_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.congestion_control_.Set("", GetArena()); + } + return released; +} +inline void TCPSettings::set_allocated_congestion_control(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.congestion_control_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.congestion_control_.IsDefault()) { + _impl_.congestion_control_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.TCPSettings.congestion_control) +} + +// bool congestion_lock = 2 [json_name = "congestionLock"]; +inline void TCPSettings::clear_congestion_lock() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_lock_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline bool TCPSettings::congestion_lock() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.TCPSettings.congestion_lock) + return _internal_congestion_lock(); +} +inline void TCPSettings::set_congestion_lock(bool value) { + _internal_set_congestion_lock(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.TCPSettings.congestion_lock) +} +inline bool TCPSettings::_internal_congestion_lock() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.congestion_lock_; +} +inline void TCPSettings::_internal_set_congestion_lock(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.congestion_lock_ = value; +} + +// optional uint32 rto_min_ms = 3 [json_name = "rtoMinMs"]; +inline bool TCPSettings::has_rto_min_ms() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + return value; +} +inline void TCPSettings::clear_rto_min_ms() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rto_min_ms_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline ::uint32_t TCPSettings::rto_min_ms() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.TCPSettings.rto_min_ms) + return _internal_rto_min_ms(); +} +inline void TCPSettings::set_rto_min_ms(::uint32_t value) { + _internal_set_rto_min_ms(value); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.TCPSettings.rto_min_ms) +} +inline ::uint32_t TCPSettings::_internal_rto_min_ms() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.rto_min_ms_; +} +inline void TCPSettings::_internal_set_rto_min_ms(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.rto_min_ms_ = value; +} + +// optional uint32 initial_congestion_window = 4 [json_name = "initialCongestionWindow"]; +inline bool TCPSettings::has_initial_congestion_window() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + return value; +} +inline void TCPSettings::clear_initial_congestion_window() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_congestion_window_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline ::uint32_t TCPSettings::initial_congestion_window() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.TCPSettings.initial_congestion_window) + return _internal_initial_congestion_window(); +} +inline void TCPSettings::set_initial_congestion_window(::uint32_t value) { + _internal_set_initial_congestion_window(value); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.TCPSettings.initial_congestion_window) +} +inline ::uint32_t TCPSettings::_internal_initial_congestion_window() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.initial_congestion_window_; +} +inline void TCPSettings::_internal_set_initial_congestion_window(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_congestion_window_ = value; +} + +// optional uint32 initial_receive_window = 5 [json_name = "initialReceiveWindow"]; +inline bool TCPSettings::has_initial_receive_window() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + return value; +} +inline void TCPSettings::clear_initial_receive_window() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_receive_window_ = 0u; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline ::uint32_t TCPSettings::initial_receive_window() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.TCPSettings.initial_receive_window) + return _internal_initial_receive_window(); +} +inline void TCPSettings::set_initial_receive_window(::uint32_t value) { + _internal_set_initial_receive_window(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.TCPSettings.initial_receive_window) +} +inline ::uint32_t TCPSettings::_internal_initial_receive_window() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.initial_receive_window_; +} +inline void TCPSettings::_internal_set_initial_receive_window(::uint32_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.initial_receive_window_ = value; +} + +// optional bool quick_ack = 6 [json_name = "quickAck"]; +inline bool TCPSettings::has_quick_ack() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U); + return value; +} +inline void TCPSettings::clear_quick_ack() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.quick_ack_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline bool TCPSettings::quick_ack() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.TCPSettings.quick_ack) + return _internal_quick_ack(); +} +inline void TCPSettings::set_quick_ack(bool value) { + _internal_set_quick_ack(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.TCPSettings.quick_ack) +} +inline bool TCPSettings::_internal_quick_ack() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.quick_ack_; +} +inline void TCPSettings::_internal_set_quick_ack(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.quick_ack_ = value; +} + +// optional bool ecn = 7 [json_name = "ecn"]; +inline bool TCPSettings::has_ecn() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U); + return value; +} +inline void TCPSettings::clear_ecn() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline bool TCPSettings::ecn() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.TCPSettings.ecn) + return _internal_ecn(); +} +inline void TCPSettings::set_ecn(bool value) { + _internal_set_ecn(value); + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.TCPSettings.ecn) +} +inline bool TCPSettings::_internal_ecn() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.ecn_; +} +inline void TCPSettings::_internal_set_ecn(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_ = value; +} + +// ------------------------------------------------------------------- + +// Treatment + +// string id = 1 [json_name = "id"]; +inline void Treatment::clear_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& Treatment::id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Treatment.id) + return _internal_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Treatment::set_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Treatment.id) +} +inline ::std::string* PROTOBUF_NONNULL Treatment::mutable_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Treatment.id) + return _s; +} +inline const ::std::string& Treatment::_internal_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.id_.Get(); +} +inline void Treatment::_internal_set_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Treatment::_internal_mutable_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Treatment::release_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Treatment.id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.id_.Set("", GetArena()); + } + return released; +} +inline void Treatment::set_allocated_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.id_.IsDefault()) { + _impl_.id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Treatment.id) +} + +// uint64 revision = 2 [json_name = "revision"]; +inline void Treatment::clear_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline ::uint64_t Treatment::revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Treatment.revision) + return _internal_revision(); +} +inline void Treatment::set_revision(::uint64_t value) { + _internal_set_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Treatment.revision) +} +inline ::uint64_t Treatment::_internal_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.revision_; +} +inline void Treatment::_internal_set_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = value; +} + +// string destination = 3 [json_name = "destination"]; +inline void Treatment::clear_destination() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.destination_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& Treatment::destination() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Treatment.destination) + return _internal_destination(); +} +template +PROTOBUF_ALWAYS_INLINE void Treatment::set_destination(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.destination_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Treatment.destination) +} +inline ::std::string* PROTOBUF_NONNULL Treatment::mutable_destination() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_destination(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Treatment.destination) + return _s; +} +inline const ::std::string& Treatment::_internal_destination() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.destination_.Get(); +} +inline void Treatment::_internal_set_destination(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.destination_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Treatment::_internal_mutable_destination() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.destination_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Treatment::release_destination() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Treatment.destination) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.destination_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.destination_.Set("", GetArena()); + } + return released; +} +inline void Treatment::set_allocated_destination(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.destination_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.destination_.IsDefault()) { + _impl_.destination_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Treatment.destination) +} + +// .xtcp_treatment_journal.v1.TCPSettings settings = 4 [json_name = "settings"]; +inline bool Treatment::has_settings() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.settings_ != nullptr); + return value; +} +inline void Treatment::clear_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.settings_ != nullptr) _impl_.settings_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::xtcp_treatment_journal::v1::TCPSettings& Treatment::_internal_settings() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment_journal::v1::TCPSettings* p = _impl_.settings_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment_journal::v1::TCPSettings>(&::xtcp_treatment_journal::v1::TCPSettings_globals_); +} +inline const ::xtcp_treatment_journal::v1::TCPSettings& Treatment::settings() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Treatment.settings) + return _internal_settings(); +} +inline void Treatment::unsafe_arena_set_allocated_settings( + ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.settings_); + } + _impl_.settings_ = reinterpret_cast<::xtcp_treatment_journal::v1::TCPSettings*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Treatment.settings) +} +inline ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE Treatment::release_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment_journal::v1::TCPSettings* released = _impl_.settings_; + _impl_.settings_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE Treatment::unsafe_arena_release_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Treatment.settings) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment_journal::v1::TCPSettings* temp = _impl_.settings_; + _impl_.settings_ = nullptr; + return temp; +} +inline ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NONNULL Treatment::_internal_mutable_settings() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.settings_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment_journal::v1::TCPSettings>(GetArena()); + _impl_.settings_ = reinterpret_cast<::xtcp_treatment_journal::v1::TCPSettings*>(p); + } + return _impl_.settings_; +} +inline ::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NONNULL Treatment::mutable_settings() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::xtcp_treatment_journal::v1::TCPSettings* _msg = _internal_mutable_settings(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Treatment.settings) + return _msg; +} +inline void Treatment::set_allocated_settings(::xtcp_treatment_journal::v1::TCPSettings* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.settings_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.settings_ = reinterpret_cast<::xtcp_treatment_journal::v1::TCPSettings*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Treatment.settings) +} + +// bool ecn_fabric_verified = 5 [json_name = "ecnFabricVerified"]; +inline void Treatment::clear_ecn_fabric_verified() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_fabric_verified_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline bool Treatment::ecn_fabric_verified() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Treatment.ecn_fabric_verified) + return _internal_ecn_fabric_verified(); +} +inline void Treatment::set_ecn_fabric_verified(bool value) { + _internal_set_ecn_fabric_verified(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Treatment.ecn_fabric_verified) +} +inline bool Treatment::_internal_ecn_fabric_verified() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.ecn_fabric_verified_; +} +inline void Treatment::_internal_set_ecn_fabric_verified(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.ecn_fabric_verified_ = value; +} + +// ------------------------------------------------------------------- + +// Assignment + +// string experiment_id = 1 [json_name = "experimentId"]; +inline void Assignment::clear_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& Assignment::experiment_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Assignment.experiment_id) + return _internal_experiment_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Assignment::set_experiment_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.experiment_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Assignment.experiment_id) +} +inline ::std::string* PROTOBUF_NONNULL Assignment::mutable_experiment_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_experiment_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Assignment.experiment_id) + return _s; +} +inline const ::std::string& Assignment::_internal_experiment_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.experiment_id_.Get(); +} +inline void Assignment::_internal_set_experiment_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.experiment_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Assignment::_internal_mutable_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.experiment_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Assignment::release_experiment_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Assignment.experiment_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.experiment_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.experiment_id_.Set("", GetArena()); + } + return released; +} +inline void Assignment::set_allocated_experiment_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.experiment_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.experiment_id_.IsDefault()) { + _impl_.experiment_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Assignment.experiment_id) +} + +// .xtcp_treatment_journal.v1.Treatment treatment = 2 [json_name = "treatment"]; +inline bool Assignment::has_treatment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + PROTOBUF_ASSUME(!value || _impl_.treatment_ != nullptr); + return value; +} +inline void Assignment::clear_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.treatment_ != nullptr) _impl_.treatment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::xtcp_treatment_journal::v1::Treatment& Assignment::_internal_treatment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment_journal::v1::Treatment* p = _impl_.treatment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment_journal::v1::Treatment>(&::xtcp_treatment_journal::v1::Treatment_globals_); +} +inline const ::xtcp_treatment_journal::v1::Treatment& Assignment::treatment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Assignment.treatment) + return _internal_treatment(); +} +inline void Assignment::unsafe_arena_set_allocated_treatment( + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.treatment_); + } + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment_journal::v1::Treatment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Assignment.treatment) +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE Assignment::release_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment_journal::v1::Treatment* released = _impl_.treatment_; + _impl_.treatment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE Assignment::unsafe_arena_release_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Assignment.treatment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment_journal::v1::Treatment* temp = _impl_.treatment_; + _impl_.treatment_ = nullptr; + return temp; +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL Assignment::_internal_mutable_treatment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.treatment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment_journal::v1::Treatment>(GetArena()); + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment_journal::v1::Treatment*>(p); + } + return _impl_.treatment_; +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL Assignment::mutable_treatment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::xtcp_treatment_journal::v1::Treatment* _msg = _internal_mutable_treatment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Assignment.treatment) + return _msg; +} +inline void Assignment::set_allocated_treatment(::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.treatment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + + _impl_.treatment_ = reinterpret_cast<::xtcp_treatment_journal::v1::Treatment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Assignment.treatment) +} + +// .xtcp_treatment_journal.v1.AssignmentMode mode = 3 [json_name = "mode"]; +inline void Assignment::clear_mode() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.mode_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline ::xtcp_treatment_journal::v1::AssignmentMode Assignment::mode() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Assignment.mode) + return _internal_mode(); +} +inline void Assignment::set_mode(::xtcp_treatment_journal::v1::AssignmentMode value) { + _internal_set_mode(value); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Assignment.mode) +} +inline ::xtcp_treatment_journal::v1::AssignmentMode Assignment::_internal_mode() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment_journal::v1::AssignmentMode>(_impl_.mode_); +} +inline void Assignment::_internal_set_mode(::xtcp_treatment_journal::v1::AssignmentMode value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.mode_ = value; +} + +// .google.protobuf.Timestamp lease_expires_at = 4 [json_name = "leaseExpiresAt"]; +inline bool Assignment::has_lease_expires_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000004U); + PROTOBUF_ASSUME(!value || _impl_.lease_expires_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Assignment::_internal_lease_expires_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.lease_expires_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Assignment::lease_expires_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Assignment.lease_expires_at) + return _internal_lease_expires_at(); +} +inline void Assignment::unsafe_arena_set_allocated_lease_expires_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.lease_expires_at_); + } + _impl_.lease_expires_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Assignment.lease_expires_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Assignment::release_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* released = _impl_.lease_expires_at_; + _impl_.lease_expires_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Assignment::unsafe_arena_release_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Assignment.lease_expires_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* temp = _impl_.lease_expires_at_; + _impl_.lease_expires_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Assignment::_internal_mutable_lease_expires_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.lease_expires_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.lease_expires_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.lease_expires_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Assignment::mutable_lease_expires_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_lease_expires_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Assignment.lease_expires_at) + return _msg; +} +inline void Assignment::set_allocated_lease_expires_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.lease_expires_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + + _impl_.lease_expires_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Assignment.lease_expires_at) +} + +// .xtcp_treatment_journal.v1.Treatment predecessor = 5 [json_name = "predecessor"]; +inline bool Assignment::has_predecessor() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.predecessor_ != nullptr); + return value; +} +inline void Assignment::clear_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.predecessor_ != nullptr) _impl_.predecessor_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::xtcp_treatment_journal::v1::Treatment& Assignment::_internal_predecessor() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment_journal::v1::Treatment* p = _impl_.predecessor_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment_journal::v1::Treatment>(&::xtcp_treatment_journal::v1::Treatment_globals_); +} +inline const ::xtcp_treatment_journal::v1::Treatment& Assignment::predecessor() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Assignment.predecessor) + return _internal_predecessor(); +} +inline void Assignment::unsafe_arena_set_allocated_predecessor( + ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.predecessor_); + } + _impl_.predecessor_ = reinterpret_cast<::xtcp_treatment_journal::v1::Treatment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Assignment.predecessor) +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE Assignment::release_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment_journal::v1::Treatment* released = _impl_.predecessor_; + _impl_.predecessor_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE Assignment::unsafe_arena_release_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Assignment.predecessor) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment_journal::v1::Treatment* temp = _impl_.predecessor_; + _impl_.predecessor_ = nullptr; + return temp; +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL Assignment::_internal_mutable_predecessor() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.predecessor_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment_journal::v1::Treatment>(GetArena()); + _impl_.predecessor_ = reinterpret_cast<::xtcp_treatment_journal::v1::Treatment*>(p); + } + return _impl_.predecessor_; +} +inline ::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NONNULL Assignment::mutable_predecessor() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment_journal::v1::Treatment* _msg = _internal_mutable_predecessor(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Assignment.predecessor) + return _msg; +} +inline void Assignment::set_allocated_predecessor(::xtcp_treatment_journal::v1::Treatment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.predecessor_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.predecessor_ = reinterpret_cast<::xtcp_treatment_journal::v1::Treatment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Assignment.predecessor) +} + +// uint64 generation = 6 [json_name = "generation"]; +inline void Assignment::clear_generation() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.generation_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline ::uint64_t Assignment::generation() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Assignment.generation) + return _internal_generation(); +} +inline void Assignment::set_generation(::uint64_t value) { + _internal_set_generation(value); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Assignment.generation) +} +inline ::uint64_t Assignment::_internal_generation() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.generation_; +} +inline void Assignment::_internal_set_generation(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.generation_ = value; +} + +// ------------------------------------------------------------------- + +// Desired + +// uint64 revision = 1 [json_name = "revision"]; +inline void Desired::clear_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline ::uint64_t Desired::revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Desired.revision) + return _internal_revision(); +} +inline void Desired::set_revision(::uint64_t value) { + _internal_set_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Desired.revision) +} +inline ::uint64_t Desired::_internal_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.revision_; +} +inline void Desired::_internal_set_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.revision_ = value; +} + +// bool suspended = 2 [json_name = "suspended"]; +inline void Desired::clear_suspended() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspended_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline bool Desired::suspended() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Desired.suspended) + return _internal_suspended(); +} +inline void Desired::set_suspended(bool value) { + _internal_set_suspended(value); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Desired.suspended) +} +inline bool Desired::_internal_suspended() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.suspended_; +} +inline void Desired::_internal_set_suspended(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspended_ = value; +} + +// .google.protobuf.Timestamp issued_at = 3 [json_name = "issuedAt"]; +inline bool Desired::has_issued_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000002U); + PROTOBUF_ASSUME(!value || _impl_.issued_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Desired::_internal_issued_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.issued_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Desired::issued_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Desired.issued_at) + return _internal_issued_at(); +} +inline void Desired::unsafe_arena_set_allocated_issued_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.issued_at_); + } + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Desired.issued_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Desired::release_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::google::protobuf::Timestamp* released = _impl_.issued_at_; + _impl_.issued_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Desired::unsafe_arena_release_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Desired.issued_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + ::google::protobuf::Timestamp* temp = _impl_.issued_at_; + _impl_.issued_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Desired::_internal_mutable_issued_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.issued_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.issued_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Desired::mutable_issued_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_issued_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Desired.issued_at) + return _msg; +} +inline void Desired::set_allocated_issued_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.issued_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + + _impl_.issued_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Desired.issued_at) +} + +// repeated .xtcp_treatment_journal.v1.Assignment assignments = 4 [json_name = "assignments"]; +inline int Desired::_internal_assignments_size() const { + return _internal_assignments().size(); +} +inline int Desired::assignments_size() const { + return _internal_assignments_size(); +} +inline void Desired::clear_assignments() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.assignments_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::xtcp_treatment_journal::v1::Assignment& Desired::assignments(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Desired.assignments) + return _internal_assignments().Get(index); +} +inline ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL Desired::mutable_assignments(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Desired.assignments) + return _internal_mutable_assignments()->Mutable(index); +} +inline ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL Desired::add_assignments() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment_journal::v1::Assignment* _add = + _internal_mutable_assignments()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment_journal.v1.Desired.assignments) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>& Desired::assignments() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment_journal.v1.Desired.assignments) + return _internal_assignments(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>* PROTOBUF_NONNULL +Desired::mutable_assignments() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment_journal.v1.Desired.assignments) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_assignments(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>& +Desired::_internal_assignments() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.assignments_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Assignment>* PROTOBUF_NONNULL +Desired::_internal_mutable_assignments() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.assignments_; +} + +// ------------------------------------------------------------------- + +// Record + +// .xtcp_treatment_journal.v1.Assignment assignment = 1 [json_name = "assignment"]; +inline bool Record::has_assignment() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000008U); + PROTOBUF_ASSUME(!value || _impl_.assignment_ != nullptr); + return value; +} +inline void Record::clear_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.assignment_ != nullptr) _impl_.assignment_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::xtcp_treatment_journal::v1::Assignment& Record::_internal_assignment() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment_journal::v1::Assignment* p = _impl_.assignment_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment_journal::v1::Assignment>(&::xtcp_treatment_journal::v1::Assignment_globals_); +} +inline const ::xtcp_treatment_journal::v1::Assignment& Record::assignment() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.assignment) + return _internal_assignment(); +} +inline void Record::unsafe_arena_set_allocated_assignment( + ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.assignment_); + } + _impl_.assignment_ = reinterpret_cast<::xtcp_treatment_journal::v1::Assignment*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Record.assignment) +} +inline ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE Record::release_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment_journal::v1::Assignment* released = _impl_.assignment_; + _impl_.assignment_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE Record::unsafe_arena_release_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.assignment) + + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment_journal::v1::Assignment* temp = _impl_.assignment_; + _impl_.assignment_ = nullptr; + return temp; +} +inline ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL Record::_internal_mutable_assignment() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.assignment_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment_journal::v1::Assignment>(GetArena()); + _impl_.assignment_ = reinterpret_cast<::xtcp_treatment_journal::v1::Assignment*>(p); + } + return _impl_.assignment_; +} +inline ::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NONNULL Record::mutable_assignment() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::xtcp_treatment_journal::v1::Assignment* _msg = _internal_mutable_assignment(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.assignment) + return _msg; +} +inline void Record::set_allocated_assignment(::xtcp_treatment_journal::v1::Assignment* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.assignment_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + + _impl_.assignment_ = reinterpret_cast<::xtcp_treatment_journal::v1::Assignment*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.assignment) +} + +// uint64 desired_revision = 2 [json_name = "desiredRevision"]; +inline void Record::clear_desired_revision() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.desired_revision_ = ::uint64_t{0u}; + ClearHasBit(_impl_._has_bits_[0], 0x00000200U); +} +inline ::uint64_t Record::desired_revision() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.desired_revision) + return _internal_desired_revision(); +} +inline void Record::set_desired_revision(::uint64_t value) { + _internal_set_desired_revision(value); + SetHasBit(_impl_._has_bits_[0], 0x00000200U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Record.desired_revision) +} +inline ::uint64_t Record::_internal_desired_revision() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.desired_revision_; +} +inline void Record::_internal_set_desired_revision(::uint64_t value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.desired_revision_ = value; +} + +// .xtcp_treatment_journal.v1.ApplyStatus status = 3 [json_name = "status"]; +inline void Record::clear_status() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.status_ = 0; + ClearHasBit(_impl_._has_bits_[0], 0x00000400U); +} +inline ::xtcp_treatment_journal::v1::ApplyStatus Record::status() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.status) + return _internal_status(); +} +inline void Record::set_status(::xtcp_treatment_journal::v1::ApplyStatus value) { + _internal_set_status(value); + SetHasBit(_impl_._has_bits_[0], 0x00000400U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Record.status) +} +inline ::xtcp_treatment_journal::v1::ApplyStatus Record::_internal_status() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::xtcp_treatment_journal::v1::ApplyStatus>(_impl_.status_); +} +inline void Record::_internal_set_status(::xtcp_treatment_journal::v1::ApplyStatus value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.status_ = value; +} + +// .google.protobuf.Timestamp received_at = 4 [json_name = "receivedAt"]; +inline bool Record::has_received_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000010U); + PROTOBUF_ASSUME(!value || _impl_.received_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Record::_internal_received_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.received_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Record::received_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.received_at) + return _internal_received_at(); +} +inline void Record::unsafe_arena_set_allocated_received_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.received_at_); + } + _impl_.received_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Record.received_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::release_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* released = _impl_.received_at_; + _impl_.received_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::unsafe_arena_release_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.received_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* temp = _impl_.received_at_; + _impl_.received_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::_internal_mutable_received_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.received_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.received_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.received_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::mutable_received_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_received_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.received_at) + return _msg; +} +inline void Record::set_allocated_received_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.received_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + + _impl_.received_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.received_at) +} + +// .google.protobuf.Timestamp attempted_at = 5 [json_name = "attemptedAt"]; +inline bool Record::has_attempted_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000020U); + PROTOBUF_ASSUME(!value || _impl_.attempted_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Record::_internal_attempted_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.attempted_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Record::attempted_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.attempted_at) + return _internal_attempted_at(); +} +inline void Record::unsafe_arena_set_allocated_attempted_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attempted_at_); + } + _impl_.attempted_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Record.attempted_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::release_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* released = _impl_.attempted_at_; + _impl_.attempted_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::unsafe_arena_release_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.attempted_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* temp = _impl_.attempted_at_; + _impl_.attempted_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::_internal_mutable_attempted_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.attempted_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.attempted_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.attempted_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::mutable_attempted_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_attempted_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.attempted_at) + return _msg; +} +inline void Record::set_allocated_attempted_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attempted_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + + _impl_.attempted_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.attempted_at) +} + +// .google.protobuf.Timestamp applied_at = 6 [json_name = "appliedAt"]; +inline bool Record::has_applied_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U); + PROTOBUF_ASSUME(!value || _impl_.applied_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Record::_internal_applied_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.applied_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Record::applied_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.applied_at) + return _internal_applied_at(); +} +inline void Record::unsafe_arena_set_allocated_applied_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.applied_at_); + } + _impl_.applied_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Record.applied_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::release_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* released = _impl_.applied_at_; + _impl_.applied_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::unsafe_arena_release_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.applied_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* temp = _impl_.applied_at_; + _impl_.applied_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::_internal_mutable_applied_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.applied_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.applied_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.applied_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::mutable_applied_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_applied_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.applied_at) + return _msg; +} +inline void Record::set_allocated_applied_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.applied_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + + _impl_.applied_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.applied_at) +} + +// .google.protobuf.Timestamp verified_at = 7 [json_name = "verifiedAt"]; +inline bool Record::has_verified_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000080U); + PROTOBUF_ASSUME(!value || _impl_.verified_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Record::_internal_verified_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.verified_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Record::verified_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.verified_at) + return _internal_verified_at(); +} +inline void Record::unsafe_arena_set_allocated_verified_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.verified_at_); + } + _impl_.verified_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Record.verified_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::release_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* released = _impl_.verified_at_; + _impl_.verified_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::unsafe_arena_release_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.verified_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* temp = _impl_.verified_at_; + _impl_.verified_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::_internal_mutable_verified_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.verified_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.verified_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.verified_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::mutable_verified_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_verified_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.verified_at) + return _msg; +} +inline void Record::set_allocated_verified_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.verified_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + + _impl_.verified_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.verified_at) +} + +// .google.protobuf.Timestamp removed_at = 8 [json_name = "removedAt"]; +inline bool Record::has_removed_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000100U); + PROTOBUF_ASSUME(!value || _impl_.removed_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Record::_internal_removed_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.removed_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Record::removed_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.removed_at) + return _internal_removed_at(); +} +inline void Record::unsafe_arena_set_allocated_removed_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.removed_at_); + } + _impl_.removed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Record.removed_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::release_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* released = _impl_.removed_at_; + _impl_.removed_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Record::unsafe_arena_release_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.removed_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* temp = _impl_.removed_at_; + _impl_.removed_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::_internal_mutable_removed_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.removed_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.removed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.removed_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Record::mutable_removed_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_removed_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.removed_at) + return _msg; +} +inline void Record::set_allocated_removed_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.removed_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); + } + + _impl_.removed_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.removed_at) +} + +// string error = 9 [json_name = "error"]; +inline void Record::clear_error() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.error_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::std::string& Record::error() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.error) + return _internal_error(); +} +template +PROTOBUF_ALWAYS_INLINE void Record::set_error(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + _impl_.error_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Record.error) +} +inline ::std::string* PROTOBUF_NONNULL Record::mutable_error() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + ::std::string* _s = _internal_mutable_error(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.error) + return _s; +} +inline const ::std::string& Record::_internal_error() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.error_.Get(); +} +inline void Record::_internal_set_error(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.error_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Record::_internal_mutable_error() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.error_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Record::release_error() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.error) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000001U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + auto* released = _impl_.error_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.error_.Set("", GetArena()); + } + return released; +} +inline void Record::set_allocated_error(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); + } + _impl_.error_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.error_.IsDefault()) { + _impl_.error_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.error) +} + +// bytes installed_route = 10 [json_name = "installedRoute"]; +inline void Record::clear_installed_route() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_route_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& Record::installed_route() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.installed_route) + return _internal_installed_route(); +} +template +PROTOBUF_ALWAYS_INLINE void Record::set_installed_route(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.installed_route_.SetBytes(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Record.installed_route) +} +inline ::std::string* PROTOBUF_NONNULL Record::mutable_installed_route() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_installed_route(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.installed_route) + return _s; +} +inline const ::std::string& Record::_internal_installed_route() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.installed_route_.Get(); +} +inline void Record::_internal_set_installed_route(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_route_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Record::_internal_mutable_installed_route() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.installed_route_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Record::release_installed_route() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.installed_route) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.installed_route_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.installed_route_.Set("", GetArena()); + } + return released; +} +inline void Record::set_allocated_installed_route(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.installed_route_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.installed_route_.IsDefault()) { + _impl_.installed_route_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.installed_route) +} + +// string installed_boot_id = 11 [json_name = "installedBootId"]; +inline void Record::clear_installed_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_boot_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& Record::installed_boot_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.installed_boot_id) + return _internal_installed_boot_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Record::set_installed_boot_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.installed_boot_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Record.installed_boot_id) +} +inline ::std::string* PROTOBUF_NONNULL Record::mutable_installed_boot_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_installed_boot_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Record.installed_boot_id) + return _s; +} +inline const ::std::string& Record::_internal_installed_boot_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.installed_boot_id_.Get(); +} +inline void Record::_internal_set_installed_boot_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.installed_boot_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Record::_internal_mutable_installed_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.installed_boot_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Record::release_installed_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Record.installed_boot_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.installed_boot_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.installed_boot_id_.Set("", GetArena()); + } + return released; +} +inline void Record::set_allocated_installed_boot_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.installed_boot_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.installed_boot_id_.IsDefault()) { + _impl_.installed_boot_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Record.installed_boot_id) +} + +// bool expired_latched = 12 [json_name = "expiredLatched"]; +inline void Record::clear_expired_latched() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expired_latched_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000800U); +} +inline bool Record::expired_latched() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Record.expired_latched) + return _internal_expired_latched(); +} +inline void Record::set_expired_latched(bool value) { + _internal_set_expired_latched(value); + SetHasBit(_impl_._has_bits_[0], 0x00000800U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Record.expired_latched) +} +inline bool Record::_internal_expired_latched() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.expired_latched_; +} +inline void Record::_internal_set_expired_latched(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.expired_latched_ = value; +} + +// ------------------------------------------------------------------- + +// Journal + +// string agent_id = 1 [json_name = "agentId"]; +inline void Journal::clear_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); +} +inline const ::std::string& Journal::agent_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.agent_id) + return _internal_agent_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Journal::set_agent_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + _impl_.agent_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Journal.agent_id) +} +inline ::std::string* PROTOBUF_NONNULL Journal::mutable_agent_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + ::std::string* _s = _internal_mutable_agent_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.agent_id) + return _s; +} +inline const ::std::string& Journal::_internal_agent_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.agent_id_.Get(); +} +inline void Journal::_internal_set_agent_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.agent_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Journal::_internal_mutable_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.agent_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Journal::release_agent_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Journal.agent_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000002U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + auto* released = _impl_.agent_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.agent_id_.Set("", GetArena()); + } + return released; +} +inline void Journal::set_allocated_agent_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000002U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000002U); + } + _impl_.agent_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.agent_id_.IsDefault()) { + _impl_.agent_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Journal.agent_id) +} + +// string location = 2 [json_name = "location"]; +inline void Journal::clear_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); +} +inline const ::std::string& Journal::location() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.location) + return _internal_location(); +} +template +PROTOBUF_ALWAYS_INLINE void Journal::set_location(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + _impl_.location_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Journal.location) +} +inline ::std::string* PROTOBUF_NONNULL Journal::mutable_location() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + ::std::string* _s = _internal_mutable_location(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.location) + return _s; +} +inline const ::std::string& Journal::_internal_location() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.location_.Get(); +} +inline void Journal::_internal_set_location(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.location_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Journal::_internal_mutable_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.location_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Journal::release_location() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Journal.location) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000004U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + auto* released = _impl_.location_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.location_.Set("", GetArena()); + } + return released; +} +inline void Journal::set_allocated_location(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000004U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000004U); + } + _impl_.location_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.location_.IsDefault()) { + _impl_.location_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Journal.location) +} + +// string boot_id = 3 [json_name = "bootId"]; +inline void Journal::clear_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.boot_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); +} +inline const ::std::string& Journal::boot_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.boot_id) + return _internal_boot_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Journal::set_boot_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + _impl_.boot_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Journal.boot_id) +} +inline ::std::string* PROTOBUF_NONNULL Journal::mutable_boot_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + ::std::string* _s = _internal_mutable_boot_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.boot_id) + return _s; +} +inline const ::std::string& Journal::_internal_boot_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.boot_id_.Get(); +} +inline void Journal::_internal_set_boot_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.boot_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Journal::_internal_mutable_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.boot_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Journal::release_boot_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Journal.boot_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000008U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + auto* released = _impl_.boot_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.boot_id_.Set("", GetArena()); + } + return released; +} +inline void Journal::set_allocated_boot_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000008U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000008U); + } + _impl_.boot_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.boot_id_.IsDefault()) { + _impl_.boot_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Journal.boot_id) +} + +// .xtcp_treatment_journal.v1.Desired desired = 4 [json_name = "desired"]; +inline bool Journal::has_desired() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000040U); + PROTOBUF_ASSUME(!value || _impl_.desired_ != nullptr); + return value; +} +inline void Journal::clear_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ != nullptr) _impl_.desired_->Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); +} +inline const ::xtcp_treatment_journal::v1::Desired& Journal::_internal_desired() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::xtcp_treatment_journal::v1::Desired* p = _impl_.desired_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::xtcp_treatment_journal::v1::Desired>(&::xtcp_treatment_journal::v1::Desired_globals_); +} +inline const ::xtcp_treatment_journal::v1::Desired& Journal::desired() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.desired) + return _internal_desired(); +} +inline void Journal::unsafe_arena_set_allocated_desired( + ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + _impl_.desired_ = reinterpret_cast<::xtcp_treatment_journal::v1::Desired*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Journal.desired) +} +inline ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE Journal::release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::xtcp_treatment_journal::v1::Desired* released = _impl_.desired_; + _impl_.desired_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE Journal::unsafe_arena_release_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Journal.desired) + + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + ::xtcp_treatment_journal::v1::Desired* temp = _impl_.desired_; + _impl_.desired_ = nullptr; + return temp; +} +inline ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NONNULL Journal::_internal_mutable_desired() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.desired_ == nullptr) { + auto* p = Super_::DefaultConstruct<::xtcp_treatment_journal::v1::Desired>(GetArena()); + _impl_.desired_ = reinterpret_cast<::xtcp_treatment_journal::v1::Desired*>(p); + } + return _impl_.desired_; +} +inline ::xtcp_treatment_journal::v1::Desired* PROTOBUF_NONNULL Journal::mutable_desired() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + ::xtcp_treatment_journal::v1::Desired* _msg = _internal_mutable_desired(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.desired) + return _msg; +} +inline void Journal::set_allocated_desired(::xtcp_treatment_journal::v1::Desired* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.desired_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = value->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000040U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000040U); + } + + _impl_.desired_ = reinterpret_cast<::xtcp_treatment_journal::v1::Desired*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Journal.desired) +} + +// bool locally_suspended = 5 [json_name = "locallySuspended"]; +inline void Journal::clear_locally_suspended() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.locally_suspended_ = false; + ClearHasBit(_impl_._has_bits_[0], 0x00000100U); +} +inline bool Journal::locally_suspended() const { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.locally_suspended) + return _internal_locally_suspended(); +} +inline void Journal::set_locally_suspended(bool value) { + _internal_set_locally_suspended(value); + SetHasBit(_impl_._has_bits_[0], 0x00000100U); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Journal.locally_suspended) +} +inline bool Journal::_internal_locally_suspended() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.locally_suspended_; +} +inline void Journal::_internal_set_locally_suspended(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.locally_suspended_ = value; +} + +// string suspension_reason = 6 [json_name = "suspensionReason"]; +inline void Journal::clear_suspension_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspension_reason_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); +} +inline const ::std::string& Journal::suspension_reason() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.suspension_reason) + return _internal_suspension_reason(); +} +template +PROTOBUF_ALWAYS_INLINE void Journal::set_suspension_reason(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + _impl_.suspension_reason_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Journal.suspension_reason) +} +inline ::std::string* PROTOBUF_NONNULL Journal::mutable_suspension_reason() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + ::std::string* _s = _internal_mutable_suspension_reason(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.suspension_reason) + return _s; +} +inline const ::std::string& Journal::_internal_suspension_reason() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.suspension_reason_.Get(); +} +inline void Journal::_internal_set_suspension_reason(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.suspension_reason_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Journal::_internal_mutable_suspension_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.suspension_reason_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Journal::release_suspension_reason() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Journal.suspension_reason) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000010U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + auto* released = _impl_.suspension_reason_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.suspension_reason_.Set("", GetArena()); + } + return released; +} +inline void Journal::set_allocated_suspension_reason(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000010U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000010U); + } + _impl_.suspension_reason_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.suspension_reason_.IsDefault()) { + _impl_.suspension_reason_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Journal.suspension_reason) +} + +// repeated .xtcp_treatment_journal.v1.Record records = 7 [json_name = "records"]; +inline int Journal::_internal_records_size() const { + return _internal_records().size(); +} +inline int Journal::records_size() const { + return _internal_records_size(); +} +inline void Journal::clear_records() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.records_.Clear(); + ClearHasBit(_impl_._has_bits_[0], 0x00000001U); +} +inline const ::xtcp_treatment_journal::v1::Record& Journal::records(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.records) + return _internal_records().Get(index); +} +inline ::xtcp_treatment_journal::v1::Record* PROTOBUF_NONNULL Journal::mutable_records(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.records) + return _internal_mutable_records()->Mutable(index); +} +inline ::xtcp_treatment_journal::v1::Record* PROTOBUF_NONNULL Journal::add_records() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::google::protobuf::internal::TSanWrite(&_impl_); + ::xtcp_treatment_journal::v1::Record* _add = + _internal_mutable_records()->InternalAddWithArena( + ::google::protobuf::MessageLite::internal_visibility(), GetArena()); + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_add:xtcp_treatment_journal.v1.Journal.records) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>& Journal::records() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:xtcp_treatment_journal.v1.Journal.records) + return _internal_records(); +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>* PROTOBUF_NONNULL +Journal::mutable_records() ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000001U); + // @@protoc_insertion_point(field_mutable_list:xtcp_treatment_journal.v1.Journal.records) + ::google::protobuf::internal::TSanWrite(&_impl_); + return _internal_mutable_records(); +} +inline const ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>& +Journal::_internal_records() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.records_; +} +inline ::google::protobuf::RepeatedPtrField<::xtcp_treatment_journal::v1::Record>* PROTOBUF_NONNULL +Journal::_internal_mutable_records() { + ::google::protobuf::internal::TSanRead(&_impl_); + return &_impl_.records_; +} + +// .google.protobuf.Timestamp updated_at = 8 [json_name = "updatedAt"]; +inline bool Journal::has_updated_at() const { + bool value = CheckHasBit(_impl_._has_bits_[0], 0x00000080U); + PROTOBUF_ASSUME(!value || _impl_.updated_at_ != nullptr); + return value; +} +inline const ::google::protobuf::Timestamp& Journal::_internal_updated_at() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::Timestamp* p = _impl_.updated_at_; + return p != nullptr ? *p : *::google::protobuf::internal::MessageGlobalsBase::ToDefaultInstance<::google::protobuf::Timestamp>(&::google::protobuf::Timestamp_globals_); +} +inline const ::google::protobuf::Timestamp& Journal::updated_at() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.updated_at) + return _internal_updated_at(); +} +inline void Journal::unsafe_arena_set_allocated_updated_at( + ::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.updated_at_); + } + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:xtcp_treatment_journal.v1.Journal.updated_at) +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Journal::release_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* released = _impl_.updated_at_; + _impl_.updated_at_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NULLABLE Journal::unsafe_arena_release_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Journal.updated_at) + + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* temp = _impl_.updated_at_; + _impl_.updated_at_ = nullptr; + return temp; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Journal::_internal_mutable_updated_at() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.updated_at_ == nullptr) { + auto* p = Super_::DefaultConstruct<::google::protobuf::Timestamp>(GetArena()); + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(p); + } + return _impl_.updated_at_; +} +inline ::google::protobuf::Timestamp* PROTOBUF_NONNULL Journal::mutable_updated_at() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + ::google::protobuf::Timestamp* _msg = _internal_mutable_updated_at(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.updated_at) + return _msg; +} +inline void Journal::set_allocated_updated_at(::google::protobuf::Timestamp* PROTOBUF_NULLABLE value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.updated_at_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::Message*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + SetHasBit(_impl_._has_bits_[0], 0x00000080U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000080U); + } + + _impl_.updated_at_ = reinterpret_cast<::google::protobuf::Timestamp*>(value); + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Journal.updated_at) +} + +// string collection_id = 9 [json_name = "collectionId"]; +inline void Journal::clear_collection_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.collection_id_.ClearToEmpty(); + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); +} +inline const ::std::string& Journal::collection_id() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:xtcp_treatment_journal.v1.Journal.collection_id) + return _internal_collection_id(); +} +template +PROTOBUF_ALWAYS_INLINE void Journal::set_collection_id(Arg_&& arg, Args_... args) { + ::google::protobuf::internal::TSanWrite(&_impl_); + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + _impl_.collection_id_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:xtcp_treatment_journal.v1.Journal.collection_id) +} +inline ::std::string* PROTOBUF_NONNULL Journal::mutable_collection_id() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + ::std::string* _s = _internal_mutable_collection_id(); + // @@protoc_insertion_point(field_mutable:xtcp_treatment_journal.v1.Journal.collection_id) + return _s; +} +inline const ::std::string& Journal::_internal_collection_id() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.collection_id_.Get(); +} +inline void Journal::_internal_set_collection_id(const ::std::string& value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.collection_id_.Set(value, GetArena()); +} +inline ::std::string* PROTOBUF_NONNULL Journal::_internal_mutable_collection_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + return _impl_.collection_id_.Mutable( GetArena()); +} +inline ::std::string* PROTOBUF_NULLABLE Journal::release_collection_id() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:xtcp_treatment_journal.v1.Journal.collection_id) + if (!CheckHasBit(_impl_._has_bits_[0], 0x00000020U)) { + return nullptr; + } + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + auto* released = _impl_.collection_id_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.collection_id_.Set("", GetArena()); + } + return released; +} +inline void Journal::set_allocated_collection_id(::std::string* PROTOBUF_NULLABLE value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + SetHasBit(_impl_._has_bits_[0], 0x00000020U); + } else { + ClearHasBit(_impl_._has_bits_[0], 0x00000020U); + } + _impl_.collection_id_.SetAllocated(value, GetArena()); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.collection_id_.IsDefault()) { + _impl_.collection_id_.Set("", GetArena()); + } + // @@protoc_insertion_point(field_set_allocated:xtcp_treatment_journal.v1.Journal.collection_id) +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) +} // namespace v1 +} // namespace xtcp_treatment_journal + + +namespace google { +namespace protobuf { + +template <> +struct is_proto_enum<::xtcp_treatment_journal::v1::AssignmentMode> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment_journal::v1::AssignmentMode>() { + return ::xtcp_treatment_journal::v1::AssignmentMode_descriptor(); +} +template <> +struct is_proto_enum<::xtcp_treatment_journal::v1::ApplyStatus> : std::true_type {}; +template <> +inline const EnumDescriptor* PROTOBUF_NONNULL GetEnumDescriptor<::xtcp_treatment_journal::v1::ApplyStatus>() { + return ::xtcp_treatment_journal::v1::ApplyStatus_descriptor(); +} + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" +// clang-format on + +#endif // xtcp_5ftreatment_5fjournal_2fv1_2fjournal_2eproto_2epb_2eh diff --git a/gen/dart/xtcp_treatment/v1/agent.pb.dart b/gen/dart/xtcp_treatment/v1/agent.pb.dart new file mode 100644 index 000000000..74de84ecd --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/agent.pb.dart @@ -0,0 +1,466 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/agent.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'treatment.pb.dart' as $1; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +class CheckInRequest extends $pb.GeneratedMessage { + factory CheckInRequest({ + $core.String? agentId, + $core.String? location, + $1.Capabilities? capabilities, + $fixnum.Int64? desiredRevision, + $core.Iterable<$1.ApplicationRecord>? records, + $core.bool? locallySuspended, + }) { + final result = CheckInRequest._(); + if (agentId != null) result.agentId = agentId; + if (location != null) result.location = location; + if (capabilities != null) result.capabilities = capabilities; + if (desiredRevision != null) result.desiredRevision = desiredRevision; + if (records != null) result.records.addAll(records); + if (locallySuspended != null) result.locallySuspended = locallySuspended; + return result; + } + + CheckInRequest._(); + + factory CheckInRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + CheckInRequest()..mergeFromBuffer(data, registry); + factory CheckInRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + CheckInRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'CheckInRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: CheckInRequest.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'agentId') + ..aOS(2, _omitFieldNames ? '' : 'location') + ..aOM<$1.Capabilities>(3, _omitFieldNames ? '' : 'capabilities', + subBuilder: $1.Capabilities.$_createMessage) + ..a<$fixnum.Int64>( + 4, _omitFieldNames ? '' : 'desiredRevision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..pPM<$1.ApplicationRecord>(5, _omitFieldNames ? '' : 'records', + subBuilder: $1.ApplicationRecord.$_createMessage) + ..aOB(6, _omitFieldNames ? '' : 'locallySuspended') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + CheckInRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + CheckInRequest copyWith(void Function(CheckInRequest) updates) => + super.copyWith((message) => updates(message as CheckInRequest)) + as CheckInRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use CheckInRequest() / CheckInRequest.new instead') + static CheckInRequest create() => CheckInRequest._(); + static $pb.GeneratedMessage $_createMessage() => CheckInRequest._(); + @$core.override + CheckInRequest createEmptyInstance() => CheckInRequest._(); + @$core.pragma('dart2js:noInline') + static CheckInRequest getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + CheckInRequest.$_createMessage); + static CheckInRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get agentId => $_getSZ(0); + @$pb.TagNumber(1) + set agentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasAgentId() => $_has(0); + @$pb.TagNumber(1) + void clearAgentId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get location => $_getSZ(1); + @$pb.TagNumber(2) + set location($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasLocation() => $_has(1); + @$pb.TagNumber(2) + void clearLocation() => $_clearField(2); + + @$pb.TagNumber(3) + $1.Capabilities get capabilities => $_getN(2); + @$pb.TagNumber(3) + set capabilities($1.Capabilities value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasCapabilities() => $_has(2); + @$pb.TagNumber(3) + void clearCapabilities() => $_clearField(3); + @$pb.TagNumber(3) + $1.Capabilities ensureCapabilities() => $_ensure(2); + + @$pb.TagNumber(4) + $fixnum.Int64 get desiredRevision => $_getI64(3); + @$pb.TagNumber(4) + set desiredRevision($fixnum.Int64 value) => $_setInt64(3, value); + @$pb.TagNumber(4) + $core.bool hasDesiredRevision() => $_has(3); + @$pb.TagNumber(4) + void clearDesiredRevision() => $_clearField(4); + + @$pb.TagNumber(5) + $pb.PbList<$1.ApplicationRecord> get records => $_getList(4); + + @$pb.TagNumber(6) + $core.bool get locallySuspended => $_getBF(5); + @$pb.TagNumber(6) + set locallySuspended($core.bool value) => $_setBool(5, value); + @$pb.TagNumber(6) + $core.bool hasLocallySuspended() => $_has(5); + @$pb.TagNumber(6) + void clearLocallySuspended() => $_clearField(6); +} + +class CheckInResponse extends $pb.GeneratedMessage { + factory CheckInResponse({ + $1.DesiredState? desired, + }) { + final result = CheckInResponse._(); + if (desired != null) result.desired = desired; + return result; + } + + CheckInResponse._(); + + factory CheckInResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + CheckInResponse()..mergeFromBuffer(data, registry); + factory CheckInResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + CheckInResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'CheckInResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: CheckInResponse.$_createMessage) + ..aOM<$1.DesiredState>(1, _omitFieldNames ? '' : 'desired', + subBuilder: $1.DesiredState.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + CheckInResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + CheckInResponse copyWith(void Function(CheckInResponse) updates) => + super.copyWith((message) => updates(message as CheckInResponse)) + as CheckInResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use CheckInResponse() / CheckInResponse.new instead') + static CheckInResponse create() => CheckInResponse._(); + static $pb.GeneratedMessage $_createMessage() => CheckInResponse._(); + @$core.override + CheckInResponse createEmptyInstance() => CheckInResponse._(); + @$core.pragma('dart2js:noInline') + static CheckInResponse getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + CheckInResponse.$_createMessage); + static CheckInResponse? _defaultInstance; + + @$pb.TagNumber(1) + $1.DesiredState get desired => $_getN(0); + @$pb.TagNumber(1) + set desired($1.DesiredState value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasDesired() => $_has(0); + @$pb.TagNumber(1) + void clearDesired() => $_clearField(1); + @$pb.TagNumber(1) + $1.DesiredState ensureDesired() => $_ensure(0); +} + +class GetDesiredStateRequest extends $pb.GeneratedMessage { + factory GetDesiredStateRequest({ + $core.String? agentId, + }) { + final result = GetDesiredStateRequest._(); + if (agentId != null) result.agentId = agentId; + return result; + } + + GetDesiredStateRequest._(); + + factory GetDesiredStateRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + GetDesiredStateRequest()..mergeFromBuffer(data, registry); + factory GetDesiredStateRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + GetDesiredStateRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'GetDesiredStateRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: GetDesiredStateRequest.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'agentId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GetDesiredStateRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GetDesiredStateRequest copyWith( + void Function(GetDesiredStateRequest) updates) => + super.copyWith((message) => updates(message as GetDesiredStateRequest)) + as GetDesiredStateRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated( + 'Use GetDesiredStateRequest() / GetDesiredStateRequest.new instead') + static GetDesiredStateRequest create() => GetDesiredStateRequest._(); + static $pb.GeneratedMessage $_createMessage() => GetDesiredStateRequest._(); + @$core.override + GetDesiredStateRequest createEmptyInstance() => GetDesiredStateRequest._(); + @$core.pragma('dart2js:noInline') + static GetDesiredStateRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor( + GetDesiredStateRequest.$_createMessage); + static GetDesiredStateRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get agentId => $_getSZ(0); + @$pb.TagNumber(1) + set agentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasAgentId() => $_has(0); + @$pb.TagNumber(1) + void clearAgentId() => $_clearField(1); +} + +class GetDesiredStateResponse extends $pb.GeneratedMessage { + factory GetDesiredStateResponse({ + $1.DesiredState? desired, + }) { + final result = GetDesiredStateResponse._(); + if (desired != null) result.desired = desired; + return result; + } + + GetDesiredStateResponse._(); + + factory GetDesiredStateResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + GetDesiredStateResponse()..mergeFromBuffer(data, registry); + factory GetDesiredStateResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + GetDesiredStateResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'GetDesiredStateResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: GetDesiredStateResponse.$_createMessage) + ..aOM<$1.DesiredState>(1, _omitFieldNames ? '' : 'desired', + subBuilder: $1.DesiredState.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GetDesiredStateResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GetDesiredStateResponse copyWith( + void Function(GetDesiredStateResponse) updates) => + super.copyWith((message) => updates(message as GetDesiredStateResponse)) + as GetDesiredStateResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated( + 'Use GetDesiredStateResponse() / GetDesiredStateResponse.new instead') + static GetDesiredStateResponse create() => GetDesiredStateResponse._(); + static $pb.GeneratedMessage $_createMessage() => GetDesiredStateResponse._(); + @$core.override + GetDesiredStateResponse createEmptyInstance() => GetDesiredStateResponse._(); + @$core.pragma('dart2js:noInline') + static GetDesiredStateResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor( + GetDesiredStateResponse.$_createMessage); + static GetDesiredStateResponse? _defaultInstance; + + @$pb.TagNumber(1) + $1.DesiredState get desired => $_getN(0); + @$pb.TagNumber(1) + set desired($1.DesiredState value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasDesired() => $_has(0); + @$pb.TagNumber(1) + void clearDesired() => $_clearField(1); + @$pb.TagNumber(1) + $1.DesiredState ensureDesired() => $_ensure(0); +} + +class WatchDesiredStateRequest extends $pb.GeneratedMessage { + factory WatchDesiredStateRequest({ + $core.String? agentId, + $fixnum.Int64? afterRevision, + }) { + final result = WatchDesiredStateRequest._(); + if (agentId != null) result.agentId = agentId; + if (afterRevision != null) result.afterRevision = afterRevision; + return result; + } + + WatchDesiredStateRequest._(); + + factory WatchDesiredStateRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + WatchDesiredStateRequest()..mergeFromBuffer(data, registry); + factory WatchDesiredStateRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + WatchDesiredStateRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WatchDesiredStateRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: WatchDesiredStateRequest.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'agentId') + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'afterRevision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WatchDesiredStateRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WatchDesiredStateRequest copyWith( + void Function(WatchDesiredStateRequest) updates) => + super.copyWith((message) => updates(message as WatchDesiredStateRequest)) + as WatchDesiredStateRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated( + 'Use WatchDesiredStateRequest() / WatchDesiredStateRequest.new instead') + static WatchDesiredStateRequest create() => WatchDesiredStateRequest._(); + static $pb.GeneratedMessage $_createMessage() => WatchDesiredStateRequest._(); + @$core.override + WatchDesiredStateRequest createEmptyInstance() => + WatchDesiredStateRequest._(); + @$core.pragma('dart2js:noInline') + static WatchDesiredStateRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor( + WatchDesiredStateRequest.$_createMessage); + static WatchDesiredStateRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get agentId => $_getSZ(0); + @$pb.TagNumber(1) + set agentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasAgentId() => $_has(0); + @$pb.TagNumber(1) + void clearAgentId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get afterRevision => $_getI64(1); + @$pb.TagNumber(2) + set afterRevision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasAfterRevision() => $_has(1); + @$pb.TagNumber(2) + void clearAfterRevision() => $_clearField(2); +} + +class WatchDesiredStateResponse extends $pb.GeneratedMessage { + factory WatchDesiredStateResponse({ + $fixnum.Int64? revision, + }) { + final result = WatchDesiredStateResponse._(); + if (revision != null) result.revision = revision; + return result; + } + + WatchDesiredStateResponse._(); + + factory WatchDesiredStateResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + WatchDesiredStateResponse()..mergeFromBuffer(data, registry); + factory WatchDesiredStateResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + WatchDesiredStateResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WatchDesiredStateResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: WatchDesiredStateResponse.$_createMessage) + ..a<$fixnum.Int64>( + 1, _omitFieldNames ? '' : 'revision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WatchDesiredStateResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WatchDesiredStateResponse copyWith( + void Function(WatchDesiredStateResponse) updates) => + super.copyWith((message) => updates(message as WatchDesiredStateResponse)) + as WatchDesiredStateResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated( + 'Use WatchDesiredStateResponse() / WatchDesiredStateResponse.new instead') + static WatchDesiredStateResponse create() => WatchDesiredStateResponse._(); + static $pb.GeneratedMessage $_createMessage() => + WatchDesiredStateResponse._(); + @$core.override + WatchDesiredStateResponse createEmptyInstance() => + WatchDesiredStateResponse._(); + @$core.pragma('dart2js:noInline') + static WatchDesiredStateResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor( + WatchDesiredStateResponse.$_createMessage); + static WatchDesiredStateResponse? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get revision => $_getI64(0); + @$pb.TagNumber(1) + set revision($fixnum.Int64 value) => $_setInt64(0, value); + @$pb.TagNumber(1) + $core.bool hasRevision() => $_has(0); + @$pb.TagNumber(1) + void clearRevision() => $_clearField(1); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/gen/dart/xtcp_treatment/v1/agent.pbenum.dart b/gen/dart/xtcp_treatment/v1/agent.pbenum.dart new file mode 100644 index 000000000..239d62c37 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/agent.pbenum.dart @@ -0,0 +1,11 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/agent.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/gen/dart/xtcp_treatment/v1/agent.pbgrpc.dart b/gen/dart/xtcp_treatment/v1/agent.pbgrpc.dart new file mode 100644 index 000000000..9e1217668 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/agent.pbgrpc.dart @@ -0,0 +1,134 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/agent.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:async' as $async; +import 'dart:core' as $core; + +import 'package:grpc/service_api.dart' as $grpc; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'agent.pb.dart' as $0; + +export 'agent.pb.dart'; + +@$pb.GrpcServiceName('xtcp_treatment.v1.AgentControlService') +class AgentControlServiceClient extends $grpc.Client { + /// The hostname for this service. + static const $core.String defaultHost = ''; + + /// OAuth scopes needed for the client. + static const $core.List<$core.String> oauthScopes = [ + '', + ]; + + AgentControlServiceClient(super.channel, {super.options, super.interceptors}); + + $grpc.ResponseFuture<$0.CheckInResponse> checkIn( + $0.CheckInRequest request, { + $grpc.CallOptions? options, + }) { + return $createUnaryCall(_$checkIn, request, options: options); + } + + $grpc.ResponseFuture<$0.GetDesiredStateResponse> getDesiredState( + $0.GetDesiredStateRequest request, { + $grpc.CallOptions? options, + }) { + return $createUnaryCall(_$getDesiredState, request, options: options); + } + + $grpc.ResponseStream<$0.WatchDesiredStateResponse> watchDesiredState( + $0.WatchDesiredStateRequest request, { + $grpc.CallOptions? options, + }) { + return $createStreamingCall( + _$watchDesiredState, $async.Stream.fromIterable([request]), + options: options); + } + + // method descriptors + + static final _$checkIn = + $grpc.ClientMethod<$0.CheckInRequest, $0.CheckInResponse>( + '/xtcp_treatment.v1.AgentControlService/CheckIn', + ($0.CheckInRequest value) => value.writeToBuffer(), + $0.CheckInResponse.fromBuffer); + static final _$getDesiredState = + $grpc.ClientMethod<$0.GetDesiredStateRequest, $0.GetDesiredStateResponse>( + '/xtcp_treatment.v1.AgentControlService/GetDesiredState', + ($0.GetDesiredStateRequest value) => value.writeToBuffer(), + $0.GetDesiredStateResponse.fromBuffer); + static final _$watchDesiredState = $grpc.ClientMethod< + $0.WatchDesiredStateRequest, $0.WatchDesiredStateResponse>( + '/xtcp_treatment.v1.AgentControlService/WatchDesiredState', + ($0.WatchDesiredStateRequest value) => value.writeToBuffer(), + $0.WatchDesiredStateResponse.fromBuffer); +} + +@$pb.GrpcServiceName('xtcp_treatment.v1.AgentControlService') +abstract class AgentControlServiceBase extends $grpc.Service { + $core.String get $name => 'xtcp_treatment.v1.AgentControlService'; + + AgentControlServiceBase() { + $addMethod($grpc.ServiceMethod<$0.CheckInRequest, $0.CheckInResponse>( + 'CheckIn', + checkIn_Pre, + false, + false, + ($core.List<$core.int> value) => $0.CheckInRequest.fromBuffer(value), + ($0.CheckInResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.GetDesiredStateRequest, + $0.GetDesiredStateResponse>( + 'GetDesiredState', + getDesiredState_Pre, + false, + false, + ($core.List<$core.int> value) => + $0.GetDesiredStateRequest.fromBuffer(value), + ($0.GetDesiredStateResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.WatchDesiredStateRequest, + $0.WatchDesiredStateResponse>( + 'WatchDesiredState', + watchDesiredState_Pre, + false, + true, + ($core.List<$core.int> value) => + $0.WatchDesiredStateRequest.fromBuffer(value), + ($0.WatchDesiredStateResponse value) => value.writeToBuffer())); + } + + $async.Future<$0.CheckInResponse> checkIn_Pre($grpc.ServiceCall $call, + $async.Future<$0.CheckInRequest> $request) async { + return checkIn($call, await $request); + } + + $async.Future<$0.CheckInResponse> checkIn( + $grpc.ServiceCall call, $0.CheckInRequest request); + + $async.Future<$0.GetDesiredStateResponse> getDesiredState_Pre( + $grpc.ServiceCall $call, + $async.Future<$0.GetDesiredStateRequest> $request) async { + return getDesiredState($call, await $request); + } + + $async.Future<$0.GetDesiredStateResponse> getDesiredState( + $grpc.ServiceCall call, $0.GetDesiredStateRequest request); + + $async.Stream<$0.WatchDesiredStateResponse> watchDesiredState_Pre( + $grpc.ServiceCall $call, + $async.Future<$0.WatchDesiredStateRequest> $request) async* { + yield* watchDesiredState($call, await $request); + } + + $async.Stream<$0.WatchDesiredStateResponse> watchDesiredState( + $grpc.ServiceCall call, $0.WatchDesiredStateRequest request); +} diff --git a/gen/dart/xtcp_treatment/v1/agent.pbjson.dart b/gen/dart/xtcp_treatment/v1/agent.pbjson.dart new file mode 100644 index 000000000..f890d0f44 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/agent.pbjson.dart @@ -0,0 +1,146 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/agent.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use checkInRequestDescriptor instead') +const CheckInRequest$json = { + '1': 'CheckInRequest', + '2': [ + {'1': 'agent_id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'agentId'}, + {'1': 'location', '3': 2, '4': 1, '5': 9, '8': {}, '10': 'location'}, + { + '1': 'capabilities', + '3': 3, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Capabilities', + '8': {}, + '10': 'capabilities' + }, + {'1': 'desired_revision', '3': 4, '4': 1, '5': 4, '10': 'desiredRevision'}, + { + '1': 'records', + '3': 5, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.ApplicationRecord', + '8': {}, + '10': 'records' + }, + { + '1': 'locally_suspended', + '3': 6, + '4': 1, + '5': 8, + '10': 'locallySuspended' + }, + ], +}; + +/// Descriptor for `CheckInRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List checkInRequestDescriptor = $convert.base64Decode( + 'Cg5DaGVja0luUmVxdWVzdBJECghhZ2VudF9pZBgBIAEoCUIpukgmciQyIl5bYS16QS1aMC05XV' + 'thLXpBLVowLTlfLi1dezAsMTI3fSRSB2FnZW50SWQSRQoIbG9jYXRpb24YAiABKAlCKbpIJnIk' + 'MiJeW2EtekEtWjAtOV1bYS16QS1aMC05Xy4tXXswLDEyN30kUghsb2NhdGlvbhJLCgxjYXBhYm' + 'lsaXRpZXMYAyABKAsyHy54dGNwX3RyZWF0bWVudC52MS5DYXBhYmlsaXRpZXNCBrpIA8gBAVIM' + 'Y2FwYWJpbGl0aWVzEikKEGRlc2lyZWRfcmV2aXNpb24YBCABKARSD2Rlc2lyZWRSZXZpc2lvbh' + 'JJCgdyZWNvcmRzGAUgAygLMiQueHRjcF90cmVhdG1lbnQudjEuQXBwbGljYXRpb25SZWNvcmRC' + 'CbpIBpIBAxCAQFIHcmVjb3JkcxIrChFsb2NhbGx5X3N1c3BlbmRlZBgGIAEoCFIQbG9jYWxseV' + 'N1c3BlbmRlZA=='); + +@$core.Deprecated('Use checkInResponseDescriptor instead') +const CheckInResponse$json = { + '1': 'CheckInResponse', + '2': [ + { + '1': 'desired', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.DesiredState', + '10': 'desired' + }, + ], +}; + +/// Descriptor for `CheckInResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List checkInResponseDescriptor = $convert.base64Decode( + 'Cg9DaGVja0luUmVzcG9uc2USOQoHZGVzaXJlZBgBIAEoCzIfLnh0Y3BfdHJlYXRtZW50LnYxLk' + 'Rlc2lyZWRTdGF0ZVIHZGVzaXJlZA=='); + +@$core.Deprecated('Use getDesiredStateRequestDescriptor instead') +const GetDesiredStateRequest$json = { + '1': 'GetDesiredStateRequest', + '2': [ + {'1': 'agent_id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'agentId'}, + ], +}; + +/// Descriptor for `GetDesiredStateRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List getDesiredStateRequestDescriptor = + $convert.base64Decode( + 'ChZHZXREZXNpcmVkU3RhdGVSZXF1ZXN0EkQKCGFnZW50X2lkGAEgASgJQim6SCZyJDIiXlthLX' + 'pBLVowLTldW2EtekEtWjAtOV8uLV17MCwxMjd9JFIHYWdlbnRJZA=='); + +@$core.Deprecated('Use getDesiredStateResponseDescriptor instead') +const GetDesiredStateResponse$json = { + '1': 'GetDesiredStateResponse', + '2': [ + { + '1': 'desired', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.DesiredState', + '10': 'desired' + }, + ], +}; + +/// Descriptor for `GetDesiredStateResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List getDesiredStateResponseDescriptor = + $convert.base64Decode( + 'ChdHZXREZXNpcmVkU3RhdGVSZXNwb25zZRI5CgdkZXNpcmVkGAEgASgLMh8ueHRjcF90cmVhdG' + '1lbnQudjEuRGVzaXJlZFN0YXRlUgdkZXNpcmVk'); + +@$core.Deprecated('Use watchDesiredStateRequestDescriptor instead') +const WatchDesiredStateRequest$json = { + '1': 'WatchDesiredStateRequest', + '2': [ + {'1': 'agent_id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'agentId'}, + {'1': 'after_revision', '3': 2, '4': 1, '5': 4, '10': 'afterRevision'}, + ], +}; + +/// Descriptor for `WatchDesiredStateRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List watchDesiredStateRequestDescriptor = $convert.base64Decode( + 'ChhXYXRjaERlc2lyZWRTdGF0ZVJlcXVlc3QSRAoIYWdlbnRfaWQYASABKAlCKbpIJnIkMiJeW2' + 'EtekEtWjAtOV1bYS16QS1aMC05Xy4tXXswLDEyN30kUgdhZ2VudElkEiUKDmFmdGVyX3Jldmlz' + 'aW9uGAIgASgEUg1hZnRlclJldmlzaW9u'); + +@$core.Deprecated('Use watchDesiredStateResponseDescriptor instead') +const WatchDesiredStateResponse$json = { + '1': 'WatchDesiredStateResponse', + '2': [ + {'1': 'revision', '3': 1, '4': 1, '5': 4, '10': 'revision'}, + ], +}; + +/// Descriptor for `WatchDesiredStateResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List watchDesiredStateResponseDescriptor = + $convert.base64Decode( + 'ChlXYXRjaERlc2lyZWRTdGF0ZVJlc3BvbnNlEhoKCHJldmlzaW9uGAEgASgEUghyZXZpc2lvbg' + '=='); diff --git a/gen/dart/xtcp_treatment/v1/operator.pb.dart b/gen/dart/xtcp_treatment/v1/operator.pb.dart new file mode 100644 index 000000000..07ef060e8 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/operator.pb.dart @@ -0,0 +1,821 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/operator.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'agent.pb.dart' as $2; +import 'operator.pbenum.dart'; +import 'treatment.pb.dart' as $1; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'operator.pbenum.dart'; + +class ProposeRequest extends $pb.GeneratedMessage { + factory ProposeRequest({ + $1.Experiment? experiment, + $core.String? requestId, + }) { + final result = ProposeRequest._(); + if (experiment != null) result.experiment = experiment; + if (requestId != null) result.requestId = requestId; + return result; + } + + ProposeRequest._(); + + factory ProposeRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ProposeRequest()..mergeFromBuffer(data, registry); + factory ProposeRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ProposeRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ProposeRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ProposeRequest.$_createMessage) + ..aOM<$1.Experiment>(1, _omitFieldNames ? '' : 'experiment', + subBuilder: $1.Experiment.$_createMessage) + ..aOS(2, _omitFieldNames ? '' : 'requestId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ProposeRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ProposeRequest copyWith(void Function(ProposeRequest) updates) => + super.copyWith((message) => updates(message as ProposeRequest)) + as ProposeRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ProposeRequest() / ProposeRequest.new instead') + static ProposeRequest create() => ProposeRequest._(); + static $pb.GeneratedMessage $_createMessage() => ProposeRequest._(); + @$core.override + ProposeRequest createEmptyInstance() => ProposeRequest._(); + @$core.pragma('dart2js:noInline') + static ProposeRequest getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ProposeRequest.$_createMessage); + static ProposeRequest? _defaultInstance; + + @$pb.TagNumber(1) + $1.Experiment get experiment => $_getN(0); + @$pb.TagNumber(1) + set experiment($1.Experiment value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasExperiment() => $_has(0); + @$pb.TagNumber(1) + void clearExperiment() => $_clearField(1); + @$pb.TagNumber(1) + $1.Experiment ensureExperiment() => $_ensure(0); + + @$pb.TagNumber(2) + $core.String get requestId => $_getSZ(1); + @$pb.TagNumber(2) + set requestId($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasRequestId() => $_has(1); + @$pb.TagNumber(2) + void clearRequestId() => $_clearField(2); +} + +class ProposeResponse extends $pb.GeneratedMessage { + factory ProposeResponse({ + $1.Experiment? experiment, + }) { + final result = ProposeResponse._(); + if (experiment != null) result.experiment = experiment; + return result; + } + + ProposeResponse._(); + + factory ProposeResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ProposeResponse()..mergeFromBuffer(data, registry); + factory ProposeResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ProposeResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ProposeResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ProposeResponse.$_createMessage) + ..aOM<$1.Experiment>(1, _omitFieldNames ? '' : 'experiment', + subBuilder: $1.Experiment.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ProposeResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ProposeResponse copyWith(void Function(ProposeResponse) updates) => + super.copyWith((message) => updates(message as ProposeResponse)) + as ProposeResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ProposeResponse() / ProposeResponse.new instead') + static ProposeResponse create() => ProposeResponse._(); + static $pb.GeneratedMessage $_createMessage() => ProposeResponse._(); + @$core.override + ProposeResponse createEmptyInstance() => ProposeResponse._(); + @$core.pragma('dart2js:noInline') + static ProposeResponse getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ProposeResponse.$_createMessage); + static ProposeResponse? _defaultInstance; + + @$pb.TagNumber(1) + $1.Experiment get experiment => $_getN(0); + @$pb.TagNumber(1) + set experiment($1.Experiment value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasExperiment() => $_has(0); + @$pb.TagNumber(1) + void clearExperiment() => $_clearField(1); + @$pb.TagNumber(1) + $1.Experiment ensureExperiment() => $_ensure(0); +} + +class AnalyzeRequest extends $pb.GeneratedMessage { + factory AnalyzeRequest({ + $core.String? experimentId, + $fixnum.Int64? expectedRevision, + }) { + final result = AnalyzeRequest._(); + if (experimentId != null) result.experimentId = experimentId; + if (expectedRevision != null) result.expectedRevision = expectedRevision; + return result; + } + + AnalyzeRequest._(); + + factory AnalyzeRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + AnalyzeRequest()..mergeFromBuffer(data, registry); + factory AnalyzeRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + AnalyzeRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AnalyzeRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: AnalyzeRequest.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'experimentId') + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'expectedRevision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AnalyzeRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AnalyzeRequest copyWith(void Function(AnalyzeRequest) updates) => + super.copyWith((message) => updates(message as AnalyzeRequest)) + as AnalyzeRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use AnalyzeRequest() / AnalyzeRequest.new instead') + static AnalyzeRequest create() => AnalyzeRequest._(); + static $pb.GeneratedMessage $_createMessage() => AnalyzeRequest._(); + @$core.override + AnalyzeRequest createEmptyInstance() => AnalyzeRequest._(); + @$core.pragma('dart2js:noInline') + static AnalyzeRequest getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + AnalyzeRequest.$_createMessage); + static AnalyzeRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get experimentId => $_getSZ(0); + @$pb.TagNumber(1) + set experimentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasExperimentId() => $_has(0); + @$pb.TagNumber(1) + void clearExperimentId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get expectedRevision => $_getI64(1); + @$pb.TagNumber(2) + set expectedRevision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasExpectedRevision() => $_has(1); + @$pb.TagNumber(2) + void clearExpectedRevision() => $_clearField(2); +} + +class AnalyzeResponse extends $pb.GeneratedMessage { + factory AnalyzeResponse({ + $1.Evidence? evidence, + $1.Outcome? outcome, + }) { + final result = AnalyzeResponse._(); + if (evidence != null) result.evidence = evidence; + if (outcome != null) result.outcome = outcome; + return result; + } + + AnalyzeResponse._(); + + factory AnalyzeResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + AnalyzeResponse()..mergeFromBuffer(data, registry); + factory AnalyzeResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + AnalyzeResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AnalyzeResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: AnalyzeResponse.$_createMessage) + ..aOM<$1.Evidence>(1, _omitFieldNames ? '' : 'evidence', + subBuilder: $1.Evidence.$_createMessage) + ..aE<$1.Outcome>(2, _omitFieldNames ? '' : 'outcome', + enumValues: $1.Outcome.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AnalyzeResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AnalyzeResponse copyWith(void Function(AnalyzeResponse) updates) => + super.copyWith((message) => updates(message as AnalyzeResponse)) + as AnalyzeResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use AnalyzeResponse() / AnalyzeResponse.new instead') + static AnalyzeResponse create() => AnalyzeResponse._(); + static $pb.GeneratedMessage $_createMessage() => AnalyzeResponse._(); + @$core.override + AnalyzeResponse createEmptyInstance() => AnalyzeResponse._(); + @$core.pragma('dart2js:noInline') + static AnalyzeResponse getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + AnalyzeResponse.$_createMessage); + static AnalyzeResponse? _defaultInstance; + + @$pb.TagNumber(1) + $1.Evidence get evidence => $_getN(0); + @$pb.TagNumber(1) + set evidence($1.Evidence value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasEvidence() => $_has(0); + @$pb.TagNumber(1) + void clearEvidence() => $_clearField(1); + @$pb.TagNumber(1) + $1.Evidence ensureEvidence() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Outcome get outcome => $_getN(1); + @$pb.TagNumber(2) + set outcome($1.Outcome value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasOutcome() => $_has(1); + @$pb.TagNumber(2) + void clearOutcome() => $_clearField(2); +} + +class ReviewRequest extends $pb.GeneratedMessage { + factory ReviewRequest({ + $core.String? experimentId, + $fixnum.Int64? expectedRevision, + $core.bool? approve, + $core.String? reason, + $core.String? requestId, + $1.Evidence? evidence, + }) { + final result = ReviewRequest._(); + if (experimentId != null) result.experimentId = experimentId; + if (expectedRevision != null) result.expectedRevision = expectedRevision; + if (approve != null) result.approve = approve; + if (reason != null) result.reason = reason; + if (requestId != null) result.requestId = requestId; + if (evidence != null) result.evidence = evidence; + return result; + } + + ReviewRequest._(); + + factory ReviewRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ReviewRequest()..mergeFromBuffer(data, registry); + factory ReviewRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ReviewRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ReviewRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ReviewRequest.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'experimentId') + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'expectedRevision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOB(3, _omitFieldNames ? '' : 'approve') + ..aOS(4, _omitFieldNames ? '' : 'reason') + ..aOS(5, _omitFieldNames ? '' : 'requestId') + ..aOM<$1.Evidence>(6, _omitFieldNames ? '' : 'evidence', + subBuilder: $1.Evidence.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ReviewRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ReviewRequest copyWith(void Function(ReviewRequest) updates) => + super.copyWith((message) => updates(message as ReviewRequest)) + as ReviewRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ReviewRequest() / ReviewRequest.new instead') + static ReviewRequest create() => ReviewRequest._(); + static $pb.GeneratedMessage $_createMessage() => ReviewRequest._(); + @$core.override + ReviewRequest createEmptyInstance() => ReviewRequest._(); + @$core.pragma('dart2js:noInline') + static ReviewRequest getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ReviewRequest.$_createMessage); + static ReviewRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get experimentId => $_getSZ(0); + @$pb.TagNumber(1) + set experimentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasExperimentId() => $_has(0); + @$pb.TagNumber(1) + void clearExperimentId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get expectedRevision => $_getI64(1); + @$pb.TagNumber(2) + set expectedRevision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasExpectedRevision() => $_has(1); + @$pb.TagNumber(2) + void clearExpectedRevision() => $_clearField(2); + + @$pb.TagNumber(3) + $core.bool get approve => $_getBF(2); + @$pb.TagNumber(3) + set approve($core.bool value) => $_setBool(2, value); + @$pb.TagNumber(3) + $core.bool hasApprove() => $_has(2); + @$pb.TagNumber(3) + void clearApprove() => $_clearField(3); + + @$pb.TagNumber(4) + $core.String get reason => $_getSZ(3); + @$pb.TagNumber(4) + set reason($core.String value) => $_setString(3, value); + @$pb.TagNumber(4) + $core.bool hasReason() => $_has(3); + @$pb.TagNumber(4) + void clearReason() => $_clearField(4); + + @$pb.TagNumber(5) + $core.String get requestId => $_getSZ(4); + @$pb.TagNumber(5) + set requestId($core.String value) => $_setString(4, value); + @$pb.TagNumber(5) + $core.bool hasRequestId() => $_has(4); + @$pb.TagNumber(5) + void clearRequestId() => $_clearField(5); + + /// Initial review uses baseline; subsequent reviews require fresh evidence. + @$pb.TagNumber(6) + $1.Evidence get evidence => $_getN(5); + @$pb.TagNumber(6) + set evidence($1.Evidence value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasEvidence() => $_has(5); + @$pb.TagNumber(6) + void clearEvidence() => $_clearField(6); + @$pb.TagNumber(6) + $1.Evidence ensureEvidence() => $_ensure(5); +} + +class ReviewResponse extends $pb.GeneratedMessage { + factory ReviewResponse({ + $1.Experiment? experiment, + }) { + final result = ReviewResponse._(); + if (experiment != null) result.experiment = experiment; + return result; + } + + ReviewResponse._(); + + factory ReviewResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ReviewResponse()..mergeFromBuffer(data, registry); + factory ReviewResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ReviewResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ReviewResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ReviewResponse.$_createMessage) + ..aOM<$1.Experiment>(1, _omitFieldNames ? '' : 'experiment', + subBuilder: $1.Experiment.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ReviewResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ReviewResponse copyWith(void Function(ReviewResponse) updates) => + super.copyWith((message) => updates(message as ReviewResponse)) + as ReviewResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ReviewResponse() / ReviewResponse.new instead') + static ReviewResponse create() => ReviewResponse._(); + static $pb.GeneratedMessage $_createMessage() => ReviewResponse._(); + @$core.override + ReviewResponse createEmptyInstance() => ReviewResponse._(); + @$core.pragma('dart2js:noInline') + static ReviewResponse getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ReviewResponse.$_createMessage); + static ReviewResponse? _defaultInstance; + + @$pb.TagNumber(1) + $1.Experiment get experiment => $_getN(0); + @$pb.TagNumber(1) + set experiment($1.Experiment value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasExperiment() => $_has(0); + @$pb.TagNumber(1) + void clearExperiment() => $_clearField(1); + @$pb.TagNumber(1) + $1.Experiment ensureExperiment() => $_ensure(0); +} + +class ControlRequest extends $pb.GeneratedMessage { + factory ControlRequest({ + $core.String? experimentId, + $core.String? agentId, + $core.String? location, + $core.bool? fleet, + ControlAction? action, + $core.String? reason, + $core.String? requestId, + }) { + final result = ControlRequest._(); + if (experimentId != null) result.experimentId = experimentId; + if (agentId != null) result.agentId = agentId; + if (location != null) result.location = location; + if (fleet != null) result.fleet = fleet; + if (action != null) result.action = action; + if (reason != null) result.reason = reason; + if (requestId != null) result.requestId = requestId; + return result; + } + + ControlRequest._(); + + factory ControlRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ControlRequest()..mergeFromBuffer(data, registry); + factory ControlRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ControlRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ControlRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ControlRequest.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'experimentId') + ..aOS(2, _omitFieldNames ? '' : 'agentId') + ..aOS(3, _omitFieldNames ? '' : 'location') + ..aOB(4, _omitFieldNames ? '' : 'fleet') + ..aE(5, _omitFieldNames ? '' : 'action', + enumValues: ControlAction.values) + ..aOS(6, _omitFieldNames ? '' : 'reason') + ..aOS(7, _omitFieldNames ? '' : 'requestId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ControlRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ControlRequest copyWith(void Function(ControlRequest) updates) => + super.copyWith((message) => updates(message as ControlRequest)) + as ControlRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ControlRequest() / ControlRequest.new instead') + static ControlRequest create() => ControlRequest._(); + static $pb.GeneratedMessage $_createMessage() => ControlRequest._(); + @$core.override + ControlRequest createEmptyInstance() => ControlRequest._(); + @$core.pragma('dart2js:noInline') + static ControlRequest getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ControlRequest.$_createMessage); + static ControlRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get experimentId => $_getSZ(0); + @$pb.TagNumber(1) + set experimentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasExperimentId() => $_has(0); + @$pb.TagNumber(1) + void clearExperimentId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get agentId => $_getSZ(1); + @$pb.TagNumber(2) + set agentId($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasAgentId() => $_has(1); + @$pb.TagNumber(2) + void clearAgentId() => $_clearField(2); + + @$pb.TagNumber(3) + $core.String get location => $_getSZ(2); + @$pb.TagNumber(3) + set location($core.String value) => $_setString(2, value); + @$pb.TagNumber(3) + $core.bool hasLocation() => $_has(2); + @$pb.TagNumber(3) + void clearLocation() => $_clearField(3); + + @$pb.TagNumber(4) + $core.bool get fleet => $_getBF(3); + @$pb.TagNumber(4) + set fleet($core.bool value) => $_setBool(3, value); + @$pb.TagNumber(4) + $core.bool hasFleet() => $_has(3); + @$pb.TagNumber(4) + void clearFleet() => $_clearField(4); + + @$pb.TagNumber(5) + ControlAction get action => $_getN(4); + @$pb.TagNumber(5) + set action(ControlAction value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasAction() => $_has(4); + @$pb.TagNumber(5) + void clearAction() => $_clearField(5); + + @$pb.TagNumber(6) + $core.String get reason => $_getSZ(5); + @$pb.TagNumber(6) + set reason($core.String value) => $_setString(5, value); + @$pb.TagNumber(6) + $core.bool hasReason() => $_has(5); + @$pb.TagNumber(6) + void clearReason() => $_clearField(6); + + @$pb.TagNumber(7) + $core.String get requestId => $_getSZ(6); + @$pb.TagNumber(7) + set requestId($core.String value) => $_setString(6, value); + @$pb.TagNumber(7) + $core.bool hasRequestId() => $_has(6); + @$pb.TagNumber(7) + void clearRequestId() => $_clearField(7); +} + +class ControlResponse extends $pb.GeneratedMessage { + factory ControlResponse({ + $core.int? affectedAgents, + }) { + final result = ControlResponse._(); + if (affectedAgents != null) result.affectedAgents = affectedAgents; + return result; + } + + ControlResponse._(); + + factory ControlResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ControlResponse()..mergeFromBuffer(data, registry); + factory ControlResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ControlResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ControlResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ControlResponse.$_createMessage) + ..aI(1, _omitFieldNames ? '' : 'affectedAgents', + fieldType: $pb.PbFieldType.OU3) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ControlResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ControlResponse copyWith(void Function(ControlResponse) updates) => + super.copyWith((message) => updates(message as ControlResponse)) + as ControlResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ControlResponse() / ControlResponse.new instead') + static ControlResponse create() => ControlResponse._(); + static $pb.GeneratedMessage $_createMessage() => ControlResponse._(); + @$core.override + ControlResponse createEmptyInstance() => ControlResponse._(); + @$core.pragma('dart2js:noInline') + static ControlResponse getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ControlResponse.$_createMessage); + static ControlResponse? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get affectedAgents => $_getIZ(0); + @$pb.TagNumber(1) + set affectedAgents($core.int value) => $_setUnsignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasAffectedAgents() => $_has(0); + @$pb.TagNumber(1) + void clearAffectedAgents() => $_clearField(1); +} + +class InspectRequest extends $pb.GeneratedMessage { + factory InspectRequest({ + $core.String? experimentId, + $core.String? agentId, + }) { + final result = InspectRequest._(); + if (experimentId != null) result.experimentId = experimentId; + if (agentId != null) result.agentId = agentId; + return result; + } + + InspectRequest._(); + + factory InspectRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + InspectRequest()..mergeFromBuffer(data, registry); + factory InspectRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + InspectRequest()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'InspectRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: InspectRequest.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'experimentId') + ..aOS(2, _omitFieldNames ? '' : 'agentId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + InspectRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + InspectRequest copyWith(void Function(InspectRequest) updates) => + super.copyWith((message) => updates(message as InspectRequest)) + as InspectRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use InspectRequest() / InspectRequest.new instead') + static InspectRequest create() => InspectRequest._(); + static $pb.GeneratedMessage $_createMessage() => InspectRequest._(); + @$core.override + InspectRequest createEmptyInstance() => InspectRequest._(); + @$core.pragma('dart2js:noInline') + static InspectRequest getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + InspectRequest.$_createMessage); + static InspectRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get experimentId => $_getSZ(0); + @$pb.TagNumber(1) + set experimentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasExperimentId() => $_has(0); + @$pb.TagNumber(1) + void clearExperimentId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get agentId => $_getSZ(1); + @$pb.TagNumber(2) + set agentId($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasAgentId() => $_has(1); + @$pb.TagNumber(2) + void clearAgentId() => $_clearField(2); +} + +class InspectResponse extends $pb.GeneratedMessage { + factory InspectResponse({ + $core.Iterable<$1.Experiment>? experiments, + $core.Iterable<$1.DesiredState>? desired, + $core.Iterable<$2.CheckInRequest>? observed, + }) { + final result = InspectResponse._(); + if (experiments != null) result.experiments.addAll(experiments); + if (desired != null) result.desired.addAll(desired); + if (observed != null) result.observed.addAll(observed); + return result; + } + + InspectResponse._(); + + factory InspectResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + InspectResponse()..mergeFromBuffer(data, registry); + factory InspectResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + InspectResponse()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'InspectResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: InspectResponse.$_createMessage) + ..pPM<$1.Experiment>(1, _omitFieldNames ? '' : 'experiments', + subBuilder: $1.Experiment.$_createMessage) + ..pPM<$1.DesiredState>(2, _omitFieldNames ? '' : 'desired', + subBuilder: $1.DesiredState.$_createMessage) + ..pPM<$2.CheckInRequest>(3, _omitFieldNames ? '' : 'observed', + subBuilder: $2.CheckInRequest.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + InspectResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + InspectResponse copyWith(void Function(InspectResponse) updates) => + super.copyWith((message) => updates(message as InspectResponse)) + as InspectResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use InspectResponse() / InspectResponse.new instead') + static InspectResponse create() => InspectResponse._(); + static $pb.GeneratedMessage $_createMessage() => InspectResponse._(); + @$core.override + InspectResponse createEmptyInstance() => InspectResponse._(); + @$core.pragma('dart2js:noInline') + static InspectResponse getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + InspectResponse.$_createMessage); + static InspectResponse? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList<$1.Experiment> get experiments => $_getList(0); + + @$pb.TagNumber(2) + $pb.PbList<$1.DesiredState> get desired => $_getList(1); + + @$pb.TagNumber(3) + $pb.PbList<$2.CheckInRequest> get observed => $_getList(2); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/gen/dart/xtcp_treatment/v1/operator.pbenum.dart b/gen/dart/xtcp_treatment/v1/operator.pbenum.dart new file mode 100644 index 000000000..4580f6956 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/operator.pbenum.dart @@ -0,0 +1,49 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/operator.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class ControlAction extends $pb.ProtobufEnum { + static const ControlAction CONTROL_ACTION_UNSPECIFIED = + ControlAction._(0, _omitEnumNames ? '' : 'CONTROL_ACTION_UNSPECIFIED'); + static const ControlAction CONTROL_ACTION_PAUSE = + ControlAction._(1, _omitEnumNames ? '' : 'CONTROL_ACTION_PAUSE'); + static const ControlAction CONTROL_ACTION_SUSPEND = + ControlAction._(2, _omitEnumNames ? '' : 'CONTROL_ACTION_SUSPEND'); + static const ControlAction CONTROL_ACTION_RESUME = + ControlAction._(3, _omitEnumNames ? '' : 'CONTROL_ACTION_RESUME'); + static const ControlAction CONTROL_ACTION_ROLLBACK = + ControlAction._(4, _omitEnumNames ? '' : 'CONTROL_ACTION_ROLLBACK'); + static const ControlAction CONTROL_ACTION_RETIRE = + ControlAction._(5, _omitEnumNames ? '' : 'CONTROL_ACTION_RETIRE'); + + static const $core.List values = [ + CONTROL_ACTION_UNSPECIFIED, + CONTROL_ACTION_PAUSE, + CONTROL_ACTION_SUSPEND, + CONTROL_ACTION_RESUME, + CONTROL_ACTION_ROLLBACK, + CONTROL_ACTION_RETIRE, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 5); + static ControlAction? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const ControlAction._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/gen/dart/xtcp_treatment/v1/operator.pbgrpc.dart b/gen/dart/xtcp_treatment/v1/operator.pbgrpc.dart new file mode 100644 index 000000000..0fcc2843d --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/operator.pbgrpc.dart @@ -0,0 +1,180 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/operator.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:async' as $async; +import 'dart:core' as $core; + +import 'package:grpc/service_api.dart' as $grpc; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'operator.pb.dart' as $0; + +export 'operator.pb.dart'; + +@$pb.GrpcServiceName('xtcp_treatment.v1.OperatorService') +class OperatorServiceClient extends $grpc.Client { + /// The hostname for this service. + static const $core.String defaultHost = ''; + + /// OAuth scopes needed for the client. + static const $core.List<$core.String> oauthScopes = [ + '', + ]; + + OperatorServiceClient(super.channel, {super.options, super.interceptors}); + + $grpc.ResponseFuture<$0.ProposeResponse> propose( + $0.ProposeRequest request, { + $grpc.CallOptions? options, + }) { + return $createUnaryCall(_$propose, request, options: options); + } + + $grpc.ResponseFuture<$0.AnalyzeResponse> analyze( + $0.AnalyzeRequest request, { + $grpc.CallOptions? options, + }) { + return $createUnaryCall(_$analyze, request, options: options); + } + + $grpc.ResponseFuture<$0.ReviewResponse> review( + $0.ReviewRequest request, { + $grpc.CallOptions? options, + }) { + return $createUnaryCall(_$review, request, options: options); + } + + $grpc.ResponseFuture<$0.ControlResponse> control( + $0.ControlRequest request, { + $grpc.CallOptions? options, + }) { + return $createUnaryCall(_$control, request, options: options); + } + + $grpc.ResponseFuture<$0.InspectResponse> inspect( + $0.InspectRequest request, { + $grpc.CallOptions? options, + }) { + return $createUnaryCall(_$inspect, request, options: options); + } + + // method descriptors + + static final _$propose = + $grpc.ClientMethod<$0.ProposeRequest, $0.ProposeResponse>( + '/xtcp_treatment.v1.OperatorService/Propose', + ($0.ProposeRequest value) => value.writeToBuffer(), + $0.ProposeResponse.fromBuffer); + static final _$analyze = + $grpc.ClientMethod<$0.AnalyzeRequest, $0.AnalyzeResponse>( + '/xtcp_treatment.v1.OperatorService/Analyze', + ($0.AnalyzeRequest value) => value.writeToBuffer(), + $0.AnalyzeResponse.fromBuffer); + static final _$review = + $grpc.ClientMethod<$0.ReviewRequest, $0.ReviewResponse>( + '/xtcp_treatment.v1.OperatorService/Review', + ($0.ReviewRequest value) => value.writeToBuffer(), + $0.ReviewResponse.fromBuffer); + static final _$control = + $grpc.ClientMethod<$0.ControlRequest, $0.ControlResponse>( + '/xtcp_treatment.v1.OperatorService/Control', + ($0.ControlRequest value) => value.writeToBuffer(), + $0.ControlResponse.fromBuffer); + static final _$inspect = + $grpc.ClientMethod<$0.InspectRequest, $0.InspectResponse>( + '/xtcp_treatment.v1.OperatorService/Inspect', + ($0.InspectRequest value) => value.writeToBuffer(), + $0.InspectResponse.fromBuffer); +} + +@$pb.GrpcServiceName('xtcp_treatment.v1.OperatorService') +abstract class OperatorServiceBase extends $grpc.Service { + $core.String get $name => 'xtcp_treatment.v1.OperatorService'; + + OperatorServiceBase() { + $addMethod($grpc.ServiceMethod<$0.ProposeRequest, $0.ProposeResponse>( + 'Propose', + propose_Pre, + false, + false, + ($core.List<$core.int> value) => $0.ProposeRequest.fromBuffer(value), + ($0.ProposeResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.AnalyzeRequest, $0.AnalyzeResponse>( + 'Analyze', + analyze_Pre, + false, + false, + ($core.List<$core.int> value) => $0.AnalyzeRequest.fromBuffer(value), + ($0.AnalyzeResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.ReviewRequest, $0.ReviewResponse>( + 'Review', + review_Pre, + false, + false, + ($core.List<$core.int> value) => $0.ReviewRequest.fromBuffer(value), + ($0.ReviewResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.ControlRequest, $0.ControlResponse>( + 'Control', + control_Pre, + false, + false, + ($core.List<$core.int> value) => $0.ControlRequest.fromBuffer(value), + ($0.ControlResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$0.InspectRequest, $0.InspectResponse>( + 'Inspect', + inspect_Pre, + false, + false, + ($core.List<$core.int> value) => $0.InspectRequest.fromBuffer(value), + ($0.InspectResponse value) => value.writeToBuffer())); + } + + $async.Future<$0.ProposeResponse> propose_Pre($grpc.ServiceCall $call, + $async.Future<$0.ProposeRequest> $request) async { + return propose($call, await $request); + } + + $async.Future<$0.ProposeResponse> propose( + $grpc.ServiceCall call, $0.ProposeRequest request); + + $async.Future<$0.AnalyzeResponse> analyze_Pre($grpc.ServiceCall $call, + $async.Future<$0.AnalyzeRequest> $request) async { + return analyze($call, await $request); + } + + $async.Future<$0.AnalyzeResponse> analyze( + $grpc.ServiceCall call, $0.AnalyzeRequest request); + + $async.Future<$0.ReviewResponse> review_Pre( + $grpc.ServiceCall $call, $async.Future<$0.ReviewRequest> $request) async { + return review($call, await $request); + } + + $async.Future<$0.ReviewResponse> review( + $grpc.ServiceCall call, $0.ReviewRequest request); + + $async.Future<$0.ControlResponse> control_Pre($grpc.ServiceCall $call, + $async.Future<$0.ControlRequest> $request) async { + return control($call, await $request); + } + + $async.Future<$0.ControlResponse> control( + $grpc.ServiceCall call, $0.ControlRequest request); + + $async.Future<$0.InspectResponse> inspect_Pre($grpc.ServiceCall $call, + $async.Future<$0.InspectRequest> $request) async { + return inspect($call, await $request); + } + + $async.Future<$0.InspectResponse> inspect( + $grpc.ServiceCall call, $0.InspectRequest request); +} diff --git a/gen/dart/xtcp_treatment/v1/operator.pbjson.dart b/gen/dart/xtcp_treatment/v1/operator.pbjson.dart new file mode 100644 index 000000000..9f8dda8b2 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/operator.pbjson.dart @@ -0,0 +1,328 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/operator.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use controlActionDescriptor instead') +const ControlAction$json = { + '1': 'ControlAction', + '2': [ + {'1': 'CONTROL_ACTION_UNSPECIFIED', '2': 0}, + {'1': 'CONTROL_ACTION_PAUSE', '2': 1}, + {'1': 'CONTROL_ACTION_SUSPEND', '2': 2}, + {'1': 'CONTROL_ACTION_RESUME', '2': 3}, + {'1': 'CONTROL_ACTION_ROLLBACK', '2': 4}, + {'1': 'CONTROL_ACTION_RETIRE', '2': 5}, + ], +}; + +/// Descriptor for `ControlAction`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List controlActionDescriptor = $convert.base64Decode( + 'Cg1Db250cm9sQWN0aW9uEh4KGkNPTlRST0xfQUNUSU9OX1VOU1BFQ0lGSUVEEAASGAoUQ09OVF' + 'JPTF9BQ1RJT05fUEFVU0UQARIaChZDT05UUk9MX0FDVElPTl9TVVNQRU5EEAISGQoVQ09OVFJP' + 'TF9BQ1RJT05fUkVTVU1FEAMSGwoXQ09OVFJPTF9BQ1RJT05fUk9MTEJBQ0sQBBIZChVDT05UUk' + '9MX0FDVElPTl9SRVRJUkUQBQ=='); + +@$core.Deprecated('Use proposeRequestDescriptor instead') +const ProposeRequest$json = { + '1': 'ProposeRequest', + '2': [ + { + '1': 'experiment', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Experiment', + '8': {}, + '10': 'experiment' + }, + {'1': 'request_id', '3': 2, '4': 1, '5': 9, '8': {}, '10': 'requestId'}, + ], + '7': {}, +}; + +/// Descriptor for `ProposeRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List proposeRequestDescriptor = $convert.base64Decode( + 'Cg5Qcm9wb3NlUmVxdWVzdBJFCgpleHBlcmltZW50GAEgASgLMh0ueHRjcF90cmVhdG1lbnQudj' + 'EuRXhwZXJpbWVudEIGukgDyAEBUgpleHBlcmltZW50EkgKCnJlcXVlc3RfaWQYAiABKAlCKbpI' + 'JnIkMiJeW2EtekEtWjAtOV1bYS16QS1aMC05Xy4tXXswLDEyN30kUglyZXF1ZXN0SWQ6lwG6SJ' + 'MBGpABChlwcm9wb3NlLnJlcXVlc3RfaWRfc3VmZml4Ek1yZXF1ZXN0X2lkIG11c3Qgbm90IGVu' + 'ZCB3aXRoIC5yZXN1bHQgKHJlc2VydmVkIGZvciB0aGUgcGFpcmVkIHJlc3BvbnNlIGV2ZW50KR' + 'okIXRoaXMucmVxdWVzdF9pZC5lbmRzV2l0aCgnLnJlc3VsdCcp'); + +@$core.Deprecated('Use proposeResponseDescriptor instead') +const ProposeResponse$json = { + '1': 'ProposeResponse', + '2': [ + { + '1': 'experiment', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Experiment', + '10': 'experiment' + }, + ], +}; + +/// Descriptor for `ProposeResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List proposeResponseDescriptor = $convert.base64Decode( + 'Cg9Qcm9wb3NlUmVzcG9uc2USPQoKZXhwZXJpbWVudBgBIAEoCzIdLnh0Y3BfdHJlYXRtZW50Ln' + 'YxLkV4cGVyaW1lbnRSCmV4cGVyaW1lbnQ='); + +@$core.Deprecated('Use analyzeRequestDescriptor instead') +const AnalyzeRequest$json = { + '1': 'AnalyzeRequest', + '2': [ + { + '1': 'experiment_id', + '3': 1, + '4': 1, + '5': 9, + '8': {}, + '10': 'experimentId' + }, + { + '1': 'expected_revision', + '3': 2, + '4': 1, + '5': 4, + '10': 'expectedRevision' + }, + ], +}; + +/// Descriptor for `AnalyzeRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List analyzeRequestDescriptor = $convert.base64Decode( + 'Cg5BbmFseXplUmVxdWVzdBJOCg1leHBlcmltZW50X2lkGAEgASgJQim6SCZyJDIiXlthLXpBLV' + 'owLTldW2EtekEtWjAtOV8uLV17MCwxMjd9JFIMZXhwZXJpbWVudElkEisKEWV4cGVjdGVkX3Jl' + 'dmlzaW9uGAIgASgEUhBleHBlY3RlZFJldmlzaW9u'); + +@$core.Deprecated('Use analyzeResponseDescriptor instead') +const AnalyzeResponse$json = { + '1': 'AnalyzeResponse', + '2': [ + { + '1': 'evidence', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Evidence', + '10': 'evidence' + }, + { + '1': 'outcome', + '3': 2, + '4': 1, + '5': 14, + '6': '.xtcp_treatment.v1.Outcome', + '10': 'outcome' + }, + ], +}; + +/// Descriptor for `AnalyzeResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List analyzeResponseDescriptor = $convert.base64Decode( + 'Cg9BbmFseXplUmVzcG9uc2USNwoIZXZpZGVuY2UYASABKAsyGy54dGNwX3RyZWF0bWVudC52MS' + '5FdmlkZW5jZVIIZXZpZGVuY2USNAoHb3V0Y29tZRgCIAEoDjIaLnh0Y3BfdHJlYXRtZW50LnYx' + 'Lk91dGNvbWVSB291dGNvbWU='); + +@$core.Deprecated('Use reviewRequestDescriptor instead') +const ReviewRequest$json = { + '1': 'ReviewRequest', + '2': [ + { + '1': 'experiment_id', + '3': 1, + '4': 1, + '5': 9, + '8': {}, + '10': 'experimentId' + }, + { + '1': 'expected_revision', + '3': 2, + '4': 1, + '5': 4, + '10': 'expectedRevision' + }, + {'1': 'approve', '3': 3, '4': 1, '5': 8, '10': 'approve'}, + {'1': 'reason', '3': 4, '4': 1, '5': 9, '8': {}, '10': 'reason'}, + {'1': 'request_id', '3': 5, '4': 1, '5': 9, '8': {}, '10': 'requestId'}, + { + '1': 'evidence', + '3': 6, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Evidence', + '10': 'evidence' + }, + ], + '7': {}, +}; + +/// Descriptor for `ReviewRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List reviewRequestDescriptor = $convert.base64Decode( + 'Cg1SZXZpZXdSZXF1ZXN0Ek4KDWV4cGVyaW1lbnRfaWQYASABKAlCKbpIJnIkMiJeW2EtekEtWj' + 'AtOV1bYS16QS1aMC05Xy4tXXswLDEyN30kUgxleHBlcmltZW50SWQSKwoRZXhwZWN0ZWRfcmV2' + 'aXNpb24YAiABKARSEGV4cGVjdGVkUmV2aXNpb24SGAoHYXBwcm92ZRgDIAEoCFIHYXBwcm92ZR' + 'IiCgZyZWFzb24YBCABKAlCCrpIB3IFEAEYgCBSBnJlYXNvbhJICgpyZXF1ZXN0X2lkGAUgASgJ' + 'Qim6SCZyJDIiXlthLXpBLVowLTldW2EtekEtWjAtOV8uLV17MCwxMjd9JFIJcmVxdWVzdElkEj' + 'cKCGV2aWRlbmNlGAYgASgLMhsueHRjcF90cmVhdG1lbnQudjEuRXZpZGVuY2VSCGV2aWRlbmNl' + 'OpYBukiSARqPAQoYcmV2aWV3LnJlcXVlc3RfaWRfc3VmZml4Ek1yZXF1ZXN0X2lkIG11c3Qgbm' + '90IGVuZCB3aXRoIC5yZXN1bHQgKHJlc2VydmVkIGZvciB0aGUgcGFpcmVkIHJlc3BvbnNlIGV2' + 'ZW50KRokIXRoaXMucmVxdWVzdF9pZC5lbmRzV2l0aCgnLnJlc3VsdCcp'); + +@$core.Deprecated('Use reviewResponseDescriptor instead') +const ReviewResponse$json = { + '1': 'ReviewResponse', + '2': [ + { + '1': 'experiment', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Experiment', + '10': 'experiment' + }, + ], +}; + +/// Descriptor for `ReviewResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List reviewResponseDescriptor = $convert.base64Decode( + 'Cg5SZXZpZXdSZXNwb25zZRI9CgpleHBlcmltZW50GAEgASgLMh0ueHRjcF90cmVhdG1lbnQudj' + 'EuRXhwZXJpbWVudFIKZXhwZXJpbWVudA=='); + +@$core.Deprecated('Use controlRequestDescriptor instead') +const ControlRequest$json = { + '1': 'ControlRequest', + '2': [ + { + '1': 'experiment_id', + '3': 1, + '4': 1, + '5': 9, + '8': {}, + '10': 'experimentId' + }, + {'1': 'agent_id', '3': 2, '4': 1, '5': 9, '8': {}, '10': 'agentId'}, + {'1': 'location', '3': 3, '4': 1, '5': 9, '8': {}, '10': 'location'}, + {'1': 'fleet', '3': 4, '4': 1, '5': 8, '10': 'fleet'}, + { + '1': 'action', + '3': 5, + '4': 1, + '5': 14, + '6': '.xtcp_treatment.v1.ControlAction', + '8': {}, + '10': 'action' + }, + {'1': 'reason', '3': 6, '4': 1, '5': 9, '8': {}, '10': 'reason'}, + {'1': 'request_id', '3': 7, '4': 1, '5': 9, '8': {}, '10': 'requestId'}, + ], + '7': {}, +}; + +/// Descriptor for `ControlRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List controlRequestDescriptor = $convert.base64Decode( + 'Cg5Db250cm9sUmVxdWVzdBJRCg1leHBlcmltZW50X2lkGAEgASgJQiy6SCnYAQFyJDIiXlthLX' + 'pBLVowLTldW2EtekEtWjAtOV8uLV17MCwxMjd9JFIMZXhwZXJpbWVudElkEkcKCGFnZW50X2lk' + 'GAIgASgJQiy6SCnYAQFyJDIiXlthLXpBLVowLTldW2EtekEtWjAtOV8uLV17MCwxMjd9JFIHYW' + 'dlbnRJZBJICghsb2NhdGlvbhgDIAEoCUIsukgp2AEBciQyIl5bYS16QS1aMC05XVthLXpBLVow' + 'LTlfLi1dezAsMTI3fSRSCGxvY2F0aW9uEhQKBWZsZWV0GAQgASgIUgVmbGVldBJECgZhY3Rpb2' + '4YBSABKA4yIC54dGNwX3RyZWF0bWVudC52MS5Db250cm9sQWN0aW9uQgq6SAeCAQQQASAAUgZh' + 'Y3Rpb24SIgoGcmVhc29uGAYgASgJQgq6SAdyBRABGIAgUgZyZWFzb24SSAoKcmVxdWVzdF9pZB' + 'gHIAEoCUIpukgmciQyIl5bYS16QS1aMC05XVthLXpBLVowLTlfLi1dezAsMTI3fSRSCXJlcXVl' + 'c3RJZDr3ArpI8wIakAEKGWNvbnRyb2wucmVxdWVzdF9pZF9zdWZmaXgSTXJlcXVlc3RfaWQgbX' + 'VzdCBub3QgZW5kIHdpdGggLnJlc3VsdCAocmVzZXJ2ZWQgZm9yIHRoZSBwYWlyZWQgcmVzcG9u' + 'c2UgZXZlbnQpGiQhdGhpcy5yZXF1ZXN0X2lkLmVuZHNXaXRoKCcucmVzdWx0Jyka3QEKFGNvbn' + 'Ryb2wub25lX3NlbGVjdG9yEkVleGFjdGx5IG9uZSBvZiBleHBlcmltZW50X2lkLCBhZ2VudF9p' + 'ZCwgbG9jYXRpb24gb3IgZmxlZXQgaXMgcmVxdWlyZWQafih0aGlzLmZsZWV0ID8gMSA6IDApIC' + 'sgKHRoaXMuZXhwZXJpbWVudF9pZCAhPSAnJyA/IDEgOiAwKSArICh0aGlzLmFnZW50X2lkICE9' + 'ICcnID8gMSA6IDApICsgKHRoaXMubG9jYXRpb24gIT0gJycgPyAxIDogMCkgPT0gMQ=='); + +@$core.Deprecated('Use controlResponseDescriptor instead') +const ControlResponse$json = { + '1': 'ControlResponse', + '2': [ + {'1': 'affected_agents', '3': 1, '4': 1, '5': 13, '10': 'affectedAgents'}, + ], +}; + +/// Descriptor for `ControlResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List controlResponseDescriptor = $convert.base64Decode( + 'Cg9Db250cm9sUmVzcG9uc2USJwoPYWZmZWN0ZWRfYWdlbnRzGAEgASgNUg5hZmZlY3RlZEFnZW' + '50cw=='); + +@$core.Deprecated('Use inspectRequestDescriptor instead') +const InspectRequest$json = { + '1': 'InspectRequest', + '2': [ + { + '1': 'experiment_id', + '3': 1, + '4': 1, + '5': 9, + '8': {}, + '10': 'experimentId' + }, + {'1': 'agent_id', '3': 2, '4': 1, '5': 9, '8': {}, '10': 'agentId'}, + ], +}; + +/// Descriptor for `InspectRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List inspectRequestDescriptor = $convert.base64Decode( + 'Cg5JbnNwZWN0UmVxdWVzdBJRCg1leHBlcmltZW50X2lkGAEgASgJQiy6SCnYAQFyJDIiXlthLX' + 'pBLVowLTldW2EtekEtWjAtOV8uLV17MCwxMjd9JFIMZXhwZXJpbWVudElkEkcKCGFnZW50X2lk' + 'GAIgASgJQiy6SCnYAQFyJDIiXlthLXpBLVowLTldW2EtekEtWjAtOV8uLV17MCwxMjd9JFIHYW' + 'dlbnRJZA=='); + +@$core.Deprecated('Use inspectResponseDescriptor instead') +const InspectResponse$json = { + '1': 'InspectResponse', + '2': [ + { + '1': 'experiments', + '3': 1, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.Experiment', + '10': 'experiments' + }, + { + '1': 'desired', + '3': 2, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.DesiredState', + '10': 'desired' + }, + { + '1': 'observed', + '3': 3, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.CheckInRequest', + '10': 'observed' + }, + ], +}; + +/// Descriptor for `InspectResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List inspectResponseDescriptor = $convert.base64Decode( + 'Cg9JbnNwZWN0UmVzcG9uc2USPwoLZXhwZXJpbWVudHMYASADKAsyHS54dGNwX3RyZWF0bWVudC' + '52MS5FeHBlcmltZW50UgtleHBlcmltZW50cxI5CgdkZXNpcmVkGAIgAygLMh8ueHRjcF90cmVh' + 'dG1lbnQudjEuRGVzaXJlZFN0YXRlUgdkZXNpcmVkEj0KCG9ic2VydmVkGAMgAygLMiEueHRjcF' + '90cmVhdG1lbnQudjEuQ2hlY2tJblJlcXVlc3RSCG9ic2VydmVk'); diff --git a/gen/dart/xtcp_treatment/v1/treatment.pb.dart b/gen/dart/xtcp_treatment/v1/treatment.pb.dart new file mode 100644 index 000000000..39aa7199c --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/treatment.pb.dart @@ -0,0 +1,1843 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/treatment.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/duration.pb.dart' + as $1; +import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart' + as $0; + +import 'treatment.pbenum.dart'; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'treatment.pbenum.dart'; + +/// TCPSettings are the per-route TCP parameters a treatment installs. Every +/// field is optional; at least one must be present. +class TCPSettings extends $pb.GeneratedMessage { + factory TCPSettings({ + $core.String? congestionControl, + $core.bool? congestionLock, + $core.int? rtoMinMs, + $core.int? initialCongestionWindow, + $core.int? initialReceiveWindow, + $core.bool? quickAck, + $core.bool? ecn, + }) { + final result = TCPSettings._(); + if (congestionControl != null) result.congestionControl = congestionControl; + if (congestionLock != null) result.congestionLock = congestionLock; + if (rtoMinMs != null) result.rtoMinMs = rtoMinMs; + if (initialCongestionWindow != null) + result.initialCongestionWindow = initialCongestionWindow; + if (initialReceiveWindow != null) + result.initialReceiveWindow = initialReceiveWindow; + if (quickAck != null) result.quickAck = quickAck; + if (ecn != null) result.ecn = ecn; + return result; + } + + TCPSettings._(); + + factory TCPSettings.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + TCPSettings()..mergeFromBuffer(data, registry); + factory TCPSettings.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + TCPSettings()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'TCPSettings', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: TCPSettings.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'congestionControl') + ..aOB(2, _omitFieldNames ? '' : 'congestionLock') + ..aI(3, _omitFieldNames ? '' : 'rtoMinMs', fieldType: $pb.PbFieldType.OU3) + ..aI(4, _omitFieldNames ? '' : 'initialCongestionWindow', + fieldType: $pb.PbFieldType.OU3) + ..aI(5, _omitFieldNames ? '' : 'initialReceiveWindow', + fieldType: $pb.PbFieldType.OU3) + ..aOB(6, _omitFieldNames ? '' : 'quickAck') + ..aOB(7, _omitFieldNames ? '' : 'ecn') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TCPSettings clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TCPSettings copyWith(void Function(TCPSettings) updates) => + super.copyWith((message) => updates(message as TCPSettings)) + as TCPSettings; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use TCPSettings() / TCPSettings.new instead') + static TCPSettings create() => TCPSettings._(); + static $pb.GeneratedMessage $_createMessage() => TCPSettings._(); + @$core.override + TCPSettings createEmptyInstance() => TCPSettings._(); + @$core.pragma('dart2js:noInline') + static TCPSettings getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + TCPSettings.$_createMessage); + static TCPSettings? _defaultInstance; + + /// Kernel algorithm name (TCP_CA_NAME_MAX is 16 including NUL). + @$pb.TagNumber(1) + $core.String get congestionControl => $_getSZ(0); + @$pb.TagNumber(1) + set congestionControl($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasCongestionControl() => $_has(0); + @$pb.TagNumber(1) + void clearCongestionControl() => $_clearField(1); + + @$pb.TagNumber(2) + $core.bool get congestionLock => $_getBF(1); + @$pb.TagNumber(2) + set congestionLock($core.bool value) => $_setBool(1, value); + @$pb.TagNumber(2) + $core.bool hasCongestionLock() => $_has(1); + @$pb.TagNumber(2) + void clearCongestionLock() => $_clearField(2); + + @$pb.TagNumber(3) + $core.int get rtoMinMs => $_getIZ(2); + @$pb.TagNumber(3) + set rtoMinMs($core.int value) => $_setUnsignedInt32(2, value); + @$pb.TagNumber(3) + $core.bool hasRtoMinMs() => $_has(2); + @$pb.TagNumber(3) + void clearRtoMinMs() => $_clearField(3); + + @$pb.TagNumber(4) + $core.int get initialCongestionWindow => $_getIZ(3); + @$pb.TagNumber(4) + set initialCongestionWindow($core.int value) => $_setUnsignedInt32(3, value); + @$pb.TagNumber(4) + $core.bool hasInitialCongestionWindow() => $_has(3); + @$pb.TagNumber(4) + void clearInitialCongestionWindow() => $_clearField(4); + + @$pb.TagNumber(5) + $core.int get initialReceiveWindow => $_getIZ(4); + @$pb.TagNumber(5) + set initialReceiveWindow($core.int value) => $_setUnsignedInt32(4, value); + @$pb.TagNumber(5) + $core.bool hasInitialReceiveWindow() => $_has(4); + @$pb.TagNumber(5) + void clearInitialReceiveWindow() => $_clearField(5); + + @$pb.TagNumber(6) + $core.bool get quickAck => $_getBF(5); + @$pb.TagNumber(6) + set quickAck($core.bool value) => $_setBool(5, value); + @$pb.TagNumber(6) + $core.bool hasQuickAck() => $_has(5); + @$pb.TagNumber(6) + void clearQuickAck() => $_clearField(6); + + @$pb.TagNumber(7) + $core.bool get ecn => $_getBF(6); + @$pb.TagNumber(7) + set ecn($core.bool value) => $_setBool(6, value); + @$pb.TagNumber(7) + $core.bool hasEcn() => $_has(6); + @$pb.TagNumber(7) + void clearEcn() => $_clearField(7); +} + +class Treatment extends $pb.GeneratedMessage { + factory Treatment({ + $core.String? id, + $fixnum.Int64? revision, + $core.String? destination, + TCPSettings? settings, + $core.bool? ecnFabricVerified, + }) { + final result = Treatment._(); + if (id != null) result.id = id; + if (revision != null) result.revision = revision; + if (destination != null) result.destination = destination; + if (settings != null) result.settings = settings; + if (ecnFabricVerified != null) result.ecnFabricVerified = ecnFabricVerified; + return result; + } + + Treatment._(); + + factory Treatment.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Treatment()..mergeFromBuffer(data, registry); + factory Treatment.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Treatment()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Treatment', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: Treatment.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'id') + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'revision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOS(3, _omitFieldNames ? '' : 'destination') + ..aOM(4, _omitFieldNames ? '' : 'settings', + subBuilder: TCPSettings.$_createMessage) + ..aOB(5, _omitFieldNames ? '' : 'ecnFabricVerified') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Treatment clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Treatment copyWith(void Function(Treatment) updates) => + super.copyWith((message) => updates(message as Treatment)) as Treatment; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Treatment() / Treatment.new instead') + static Treatment create() => Treatment._(); + static $pb.GeneratedMessage $_createMessage() => Treatment._(); + @$core.override + Treatment createEmptyInstance() => Treatment._(); + @$core.pragma('dart2js:noInline') + static Treatment getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Treatment.$_createMessage); + static Treatment? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get id => $_getSZ(0); + @$pb.TagNumber(1) + set id($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get revision => $_getI64(1); + @$pb.TagNumber(2) + set revision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasRevision() => $_has(1); + @$pb.TagNumber(2) + void clearRevision() => $_clearField(2); + + /// Canonical unicast host prefix (/32 or /128). Canonical form, unicast and + /// not-loopback are checked by treatment.ValidateTreatment. + @$pb.TagNumber(3) + $core.String get destination => $_getSZ(2); + @$pb.TagNumber(3) + set destination($core.String value) => $_setString(2, value); + @$pb.TagNumber(3) + $core.bool hasDestination() => $_has(2); + @$pb.TagNumber(3) + void clearDestination() => $_clearField(3); + + @$pb.TagNumber(4) + TCPSettings get settings => $_getN(3); + @$pb.TagNumber(4) + set settings(TCPSettings value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasSettings() => $_has(3); + @$pb.TagNumber(4) + void clearSettings() => $_clearField(4); + @$pb.TagNumber(4) + TCPSettings ensureSettings() => $_ensure(3); + + @$pb.TagNumber(5) + $core.bool get ecnFabricVerified => $_getBF(4); + @$pb.TagNumber(5) + set ecnFabricVerified($core.bool value) => $_setBool(4, value); + @$pb.TagNumber(5) + $core.bool hasEcnFabricVerified() => $_has(4); + @$pb.TagNumber(5) + void clearEcnFabricVerified() => $_clearField(5); +} + +class Assignment extends $pb.GeneratedMessage { + factory Assignment({ + $core.String? experimentId, + Treatment? treatment, + AssignmentMode? mode, + $0.Timestamp? leaseExpiresAt, + Treatment? predecessor, + $fixnum.Int64? generation, + }) { + final result = Assignment._(); + if (experimentId != null) result.experimentId = experimentId; + if (treatment != null) result.treatment = treatment; + if (mode != null) result.mode = mode; + if (leaseExpiresAt != null) result.leaseExpiresAt = leaseExpiresAt; + if (predecessor != null) result.predecessor = predecessor; + if (generation != null) result.generation = generation; + return result; + } + + Assignment._(); + + factory Assignment.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Assignment()..mergeFromBuffer(data, registry); + factory Assignment.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Assignment()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Assignment', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: Assignment.$_createMessage) + ..aOS(2, _omitFieldNames ? '' : 'experimentId') + ..aOM(3, _omitFieldNames ? '' : 'treatment', + subBuilder: Treatment.$_createMessage) + ..aE(4, _omitFieldNames ? '' : 'mode', + enumValues: AssignmentMode.values) + ..aOM<$0.Timestamp>(5, _omitFieldNames ? '' : 'leaseExpiresAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM(6, _omitFieldNames ? '' : 'predecessor', + subBuilder: Treatment.$_createMessage) + ..a<$fixnum.Int64>( + 7, _omitFieldNames ? '' : 'generation', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Assignment clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Assignment copyWith(void Function(Assignment) updates) => + super.copyWith((message) => updates(message as Assignment)) as Assignment; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Assignment() / Assignment.new instead') + static Assignment create() => Assignment._(); + static $pb.GeneratedMessage $_createMessage() => Assignment._(); + @$core.override + Assignment createEmptyInstance() => Assignment._(); + @$core.pragma('dart2js:noInline') + static Assignment getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Assignment.$_createMessage); + static Assignment? _defaultInstance; + + @$pb.TagNumber(2) + $core.String get experimentId => $_getSZ(0); + @$pb.TagNumber(2) + set experimentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(2) + $core.bool hasExperimentId() => $_has(0); + @$pb.TagNumber(2) + void clearExperimentId() => $_clearField(2); + + @$pb.TagNumber(3) + Treatment get treatment => $_getN(1); + @$pb.TagNumber(3) + set treatment(Treatment value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasTreatment() => $_has(1); + @$pb.TagNumber(3) + void clearTreatment() => $_clearField(3); + @$pb.TagNumber(3) + Treatment ensureTreatment() => $_ensure(1); + + @$pb.TagNumber(4) + AssignmentMode get mode => $_getN(2); + @$pb.TagNumber(4) + set mode(AssignmentMode value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasMode() => $_has(2); + @$pb.TagNumber(4) + void clearMode() => $_clearField(4); + + @$pb.TagNumber(5) + $0.Timestamp get leaseExpiresAt => $_getN(3); + @$pb.TagNumber(5) + set leaseExpiresAt($0.Timestamp value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasLeaseExpiresAt() => $_has(3); + @$pb.TagNumber(5) + void clearLeaseExpiresAt() => $_clearField(5); + @$pb.TagNumber(5) + $0.Timestamp ensureLeaseExpiresAt() => $_ensure(3); + + /// Previous approved stable treatment, restored on trial expiry/rollback. + @$pb.TagNumber(6) + Treatment get predecessor => $_getN(4); + @$pb.TagNumber(6) + set predecessor(Treatment value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasPredecessor() => $_has(4); + @$pb.TagNumber(6) + void clearPredecessor() => $_clearField(6); + @$pb.TagNumber(6) + Treatment ensurePredecessor() => $_ensure(4); + + /// Increment only on an explicitly approved reactivation, not lease renewal. + @$pb.TagNumber(7) + $fixnum.Int64 get generation => $_getI64(5); + @$pb.TagNumber(7) + set generation($fixnum.Int64 value) => $_setInt64(5, value); + @$pb.TagNumber(7) + $core.bool hasGeneration() => $_has(5); + @$pb.TagNumber(7) + void clearGeneration() => $_clearField(7); +} + +/// DesiredState is the complete revisioned snapshot an agent reconciles to. +/// Duplicate assignment IDs and overlapping destinations are rejected by +/// treatment.ValidateDesired. +class DesiredState extends $pb.GeneratedMessage { + factory DesiredState({ + $core.String? agentId, + $fixnum.Int64? revision, + $core.bool? suspended, + $core.Iterable? assignments, + $0.Timestamp? issuedAt, + }) { + final result = DesiredState._(); + if (agentId != null) result.agentId = agentId; + if (revision != null) result.revision = revision; + if (suspended != null) result.suspended = suspended; + if (assignments != null) result.assignments.addAll(assignments); + if (issuedAt != null) result.issuedAt = issuedAt; + return result; + } + + DesiredState._(); + + factory DesiredState.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + DesiredState()..mergeFromBuffer(data, registry); + factory DesiredState.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + DesiredState()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'DesiredState', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: DesiredState.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'agentId') + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'revision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOB(3, _omitFieldNames ? '' : 'suspended') + ..pPM(4, _omitFieldNames ? '' : 'assignments', + subBuilder: Assignment.$_createMessage) + ..aOM<$0.Timestamp>(5, _omitFieldNames ? '' : 'issuedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + DesiredState clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + DesiredState copyWith(void Function(DesiredState) updates) => + super.copyWith((message) => updates(message as DesiredState)) + as DesiredState; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use DesiredState() / DesiredState.new instead') + static DesiredState create() => DesiredState._(); + static $pb.GeneratedMessage $_createMessage() => DesiredState._(); + @$core.override + DesiredState createEmptyInstance() => DesiredState._(); + @$core.pragma('dart2js:noInline') + static DesiredState getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + DesiredState.$_createMessage); + static DesiredState? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get agentId => $_getSZ(0); + @$pb.TagNumber(1) + set agentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasAgentId() => $_has(0); + @$pb.TagNumber(1) + void clearAgentId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get revision => $_getI64(1); + @$pb.TagNumber(2) + set revision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasRevision() => $_has(1); + @$pb.TagNumber(2) + void clearRevision() => $_clearField(2); + + @$pb.TagNumber(3) + $core.bool get suspended => $_getBF(2); + @$pb.TagNumber(3) + set suspended($core.bool value) => $_setBool(2, value); + @$pb.TagNumber(3) + $core.bool hasSuspended() => $_has(2); + @$pb.TagNumber(3) + void clearSuspended() => $_clearField(3); + + @$pb.TagNumber(4) + $pb.PbList get assignments => $_getList(3); + + @$pb.TagNumber(5) + $0.Timestamp get issuedAt => $_getN(4); + @$pb.TagNumber(5) + set issuedAt($0.Timestamp value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasIssuedAt() => $_has(4); + @$pb.TagNumber(5) + void clearIssuedAt() => $_clearField(5); + @$pb.TagNumber(5) + $0.Timestamp ensureIssuedAt() => $_ensure(4); +} + +class Capabilities extends $pb.GeneratedMessage { + factory Capabilities({ + $core.String? bootId, + $core.String? kernelRelease, + $core.Iterable<$core.String>? congestionAlgorithms, + $core.bool? simpleHostRouting, + $core.bool? actuatorEnabled, + $core.String? collectionId, + }) { + final result = Capabilities._(); + if (bootId != null) result.bootId = bootId; + if (kernelRelease != null) result.kernelRelease = kernelRelease; + if (congestionAlgorithms != null) + result.congestionAlgorithms.addAll(congestionAlgorithms); + if (simpleHostRouting != null) result.simpleHostRouting = simpleHostRouting; + if (actuatorEnabled != null) result.actuatorEnabled = actuatorEnabled; + if (collectionId != null) result.collectionId = collectionId; + return result; + } + + Capabilities._(); + + factory Capabilities.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Capabilities()..mergeFromBuffer(data, registry); + factory Capabilities.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Capabilities()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Capabilities', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: Capabilities.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'bootId') + ..aOS(2, _omitFieldNames ? '' : 'kernelRelease') + ..pPS(3, _omitFieldNames ? '' : 'congestionAlgorithms') + ..aOB(4, _omitFieldNames ? '' : 'simpleHostRouting') + ..aOB(5, _omitFieldNames ? '' : 'actuatorEnabled') + ..aOS(6, _omitFieldNames ? '' : 'collectionId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Capabilities clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Capabilities copyWith(void Function(Capabilities) updates) => + super.copyWith((message) => updates(message as Capabilities)) + as Capabilities; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Capabilities() / Capabilities.new instead') + static Capabilities create() => Capabilities._(); + static $pb.GeneratedMessage $_createMessage() => Capabilities._(); + @$core.override + Capabilities createEmptyInstance() => Capabilities._(); + @$core.pragma('dart2js:noInline') + static Capabilities getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + Capabilities.$_createMessage); + static Capabilities? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get bootId => $_getSZ(0); + @$pb.TagNumber(1) + set bootId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasBootId() => $_has(0); + @$pb.TagNumber(1) + void clearBootId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get kernelRelease => $_getSZ(1); + @$pb.TagNumber(2) + set kernelRelease($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasKernelRelease() => $_has(1); + @$pb.TagNumber(2) + void clearKernelRelease() => $_clearField(2); + + @$pb.TagNumber(3) + $pb.PbList<$core.String> get congestionAlgorithms => $_getList(2); + + @$pb.TagNumber(4) + $core.bool get simpleHostRouting => $_getBF(3); + @$pb.TagNumber(4) + set simpleHostRouting($core.bool value) => $_setBool(3, value); + @$pb.TagNumber(4) + $core.bool hasSimpleHostRouting() => $_has(3); + @$pb.TagNumber(4) + void clearSimpleHostRouting() => $_clearField(4); + + @$pb.TagNumber(5) + $core.bool get actuatorEnabled => $_getBF(4); + @$pb.TagNumber(5) + set actuatorEnabled($core.bool value) => $_setBool(4, value); + @$pb.TagNumber(5) + $core.bool hasActuatorEnabled() => $_has(4); + @$pb.TagNumber(5) + void clearActuatorEnabled() => $_clearField(5); + + /// Per-process nonce the agent writes into its journal header and the + /// daemon stamps into every record as collection_id. Evidence counts only + /// records whose (agent_id, host_boot_id, collection_id) an agent reported. + @$pb.TagNumber(6) + $core.String get collectionId => $_getSZ(5); + @$pb.TagNumber(6) + set collectionId($core.String value) => $_setString(5, value); + @$pb.TagNumber(6) + $core.bool hasCollectionId() => $_has(5); + @$pb.TagNumber(6) + void clearCollectionId() => $_clearField(6); +} + +/// ApplicationRecord is the agent's account of one assignment. Agents report +/// these on check-in with installed_route and installed_boot_id cleared. +class ApplicationRecord extends $pb.GeneratedMessage { + factory ApplicationRecord({ + Assignment? assignment, + $fixnum.Int64? desiredRevision, + ApplyStatus? status, + $0.Timestamp? receivedAt, + $0.Timestamp? attemptedAt, + $0.Timestamp? appliedAt, + $0.Timestamp? verifiedAt, + $0.Timestamp? removedAt, + $core.String? error, + $core.List<$core.int>? installedRoute, + $core.String? installedBootId, + $core.bool? expiredLatched, + }) { + final result = ApplicationRecord._(); + if (assignment != null) result.assignment = assignment; + if (desiredRevision != null) result.desiredRevision = desiredRevision; + if (status != null) result.status = status; + if (receivedAt != null) result.receivedAt = receivedAt; + if (attemptedAt != null) result.attemptedAt = attemptedAt; + if (appliedAt != null) result.appliedAt = appliedAt; + if (verifiedAt != null) result.verifiedAt = verifiedAt; + if (removedAt != null) result.removedAt = removedAt; + if (error != null) result.error = error; + if (installedRoute != null) result.installedRoute = installedRoute; + if (installedBootId != null) result.installedBootId = installedBootId; + if (expiredLatched != null) result.expiredLatched = expiredLatched; + return result; + } + + ApplicationRecord._(); + + factory ApplicationRecord.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ApplicationRecord()..mergeFromBuffer(data, registry); + factory ApplicationRecord.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ApplicationRecord()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ApplicationRecord', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ApplicationRecord.$_createMessage) + ..aOM(1, _omitFieldNames ? '' : 'assignment', + subBuilder: Assignment.$_createMessage) + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'desiredRevision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aE(3, _omitFieldNames ? '' : 'status', + enumValues: ApplyStatus.values) + ..aOM<$0.Timestamp>(4, _omitFieldNames ? '' : 'receivedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(5, _omitFieldNames ? '' : 'attemptedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(6, _omitFieldNames ? '' : 'appliedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(7, _omitFieldNames ? '' : 'verifiedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(8, _omitFieldNames ? '' : 'removedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOS(9, _omitFieldNames ? '' : 'error') + ..a<$core.List<$core.int>>( + 10, _omitFieldNames ? '' : 'installedRoute', $pb.PbFieldType.OY) + ..aOS(11, _omitFieldNames ? '' : 'installedBootId') + ..aOB(12, _omitFieldNames ? '' : 'expiredLatched') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ApplicationRecord clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ApplicationRecord copyWith(void Function(ApplicationRecord) updates) => + super.copyWith((message) => updates(message as ApplicationRecord)) + as ApplicationRecord; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ApplicationRecord() / ApplicationRecord.new instead') + static ApplicationRecord create() => ApplicationRecord._(); + static $pb.GeneratedMessage $_createMessage() => ApplicationRecord._(); + @$core.override + ApplicationRecord createEmptyInstance() => ApplicationRecord._(); + @$core.pragma('dart2js:noInline') + static ApplicationRecord getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ApplicationRecord.$_createMessage); + static ApplicationRecord? _defaultInstance; + + @$pb.TagNumber(1) + Assignment get assignment => $_getN(0); + @$pb.TagNumber(1) + set assignment(Assignment value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasAssignment() => $_has(0); + @$pb.TagNumber(1) + void clearAssignment() => $_clearField(1); + @$pb.TagNumber(1) + Assignment ensureAssignment() => $_ensure(0); + + @$pb.TagNumber(2) + $fixnum.Int64 get desiredRevision => $_getI64(1); + @$pb.TagNumber(2) + set desiredRevision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasDesiredRevision() => $_has(1); + @$pb.TagNumber(2) + void clearDesiredRevision() => $_clearField(2); + + @$pb.TagNumber(3) + ApplyStatus get status => $_getN(2); + @$pb.TagNumber(3) + set status(ApplyStatus value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasStatus() => $_has(2); + @$pb.TagNumber(3) + void clearStatus() => $_clearField(3); + + @$pb.TagNumber(4) + $0.Timestamp get receivedAt => $_getN(3); + @$pb.TagNumber(4) + set receivedAt($0.Timestamp value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasReceivedAt() => $_has(3); + @$pb.TagNumber(4) + void clearReceivedAt() => $_clearField(4); + @$pb.TagNumber(4) + $0.Timestamp ensureReceivedAt() => $_ensure(3); + + @$pb.TagNumber(5) + $0.Timestamp get attemptedAt => $_getN(4); + @$pb.TagNumber(5) + set attemptedAt($0.Timestamp value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasAttemptedAt() => $_has(4); + @$pb.TagNumber(5) + void clearAttemptedAt() => $_clearField(5); + @$pb.TagNumber(5) + $0.Timestamp ensureAttemptedAt() => $_ensure(4); + + @$pb.TagNumber(6) + $0.Timestamp get appliedAt => $_getN(5); + @$pb.TagNumber(6) + set appliedAt($0.Timestamp value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasAppliedAt() => $_has(5); + @$pb.TagNumber(6) + void clearAppliedAt() => $_clearField(6); + @$pb.TagNumber(6) + $0.Timestamp ensureAppliedAt() => $_ensure(5); + + @$pb.TagNumber(7) + $0.Timestamp get verifiedAt => $_getN(6); + @$pb.TagNumber(7) + set verifiedAt($0.Timestamp value) => $_setField(7, value); + @$pb.TagNumber(7) + $core.bool hasVerifiedAt() => $_has(6); + @$pb.TagNumber(7) + void clearVerifiedAt() => $_clearField(7); + @$pb.TagNumber(7) + $0.Timestamp ensureVerifiedAt() => $_ensure(6); + + @$pb.TagNumber(8) + $0.Timestamp get removedAt => $_getN(7); + @$pb.TagNumber(8) + set removedAt($0.Timestamp value) => $_setField(8, value); + @$pb.TagNumber(8) + $core.bool hasRemovedAt() => $_has(7); + @$pb.TagNumber(8) + void clearRemovedAt() => $_clearField(8); + @$pb.TagNumber(8) + $0.Timestamp ensureRemovedAt() => $_ensure(7); + + @$pb.TagNumber(9) + $core.String get error => $_getSZ(8); + @$pb.TagNumber(9) + set error($core.String value) => $_setString(8, value); + @$pb.TagNumber(9) + $core.bool hasError() => $_has(8); + @$pb.TagNumber(9) + void clearError() => $_clearField(9); + + /// Locally generated canonical netlink route body, never accepted from RPC. + @$pb.TagNumber(10) + $core.List<$core.int> get installedRoute => $_getN(9); + @$pb.TagNumber(10) + set installedRoute($core.List<$core.int> value) => $_setBytes(9, value); + @$pb.TagNumber(10) + $core.bool hasInstalledRoute() => $_has(9); + @$pb.TagNumber(10) + void clearInstalledRoute() => $_clearField(10); + + @$pb.TagNumber(11) + $core.String get installedBootId => $_getSZ(10); + @$pb.TagNumber(11) + set installedBootId($core.String value) => $_setString(10, value); + @$pb.TagNumber(11) + $core.bool hasInstalledBootId() => $_has(10); + @$pb.TagNumber(11) + void clearInstalledBootId() => $_clearField(11); + + @$pb.TagNumber(12) + $core.bool get expiredLatched => $_getBF(11); + @$pb.TagNumber(12) + set expiredLatched($core.bool value) => $_setBool(11, value); + @$pb.TagNumber(12) + $core.bool hasExpiredLatched() => $_has(11); + @$pb.TagNumber(12) + void clearExpiredLatched() => $_clearField(12); +} + +/// LocalState is the agent's journal snapshot. It is a file format for the +/// host-side journal and the local tooling, not an RPC payload. +class LocalState extends $pb.GeneratedMessage { + factory LocalState({ + DesiredState? desired, + $core.bool? locallySuspended, + $core.String? suspensionReason, + $core.Iterable? records, + $0.Timestamp? updatedAt, + }) { + final result = LocalState._(); + if (desired != null) result.desired = desired; + if (locallySuspended != null) result.locallySuspended = locallySuspended; + if (suspensionReason != null) result.suspensionReason = suspensionReason; + if (records != null) result.records.addAll(records); + if (updatedAt != null) result.updatedAt = updatedAt; + return result; + } + + LocalState._(); + + factory LocalState.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + LocalState()..mergeFromBuffer(data, registry); + factory LocalState.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + LocalState()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'LocalState', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: LocalState.$_createMessage) + ..aOM(1, _omitFieldNames ? '' : 'desired', + subBuilder: DesiredState.$_createMessage) + ..aOB(2, _omitFieldNames ? '' : 'locallySuspended') + ..aOS(3, _omitFieldNames ? '' : 'suspensionReason') + ..pPM(4, _omitFieldNames ? '' : 'records', + subBuilder: ApplicationRecord.$_createMessage) + ..aOM<$0.Timestamp>(5, _omitFieldNames ? '' : 'updatedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + LocalState clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + LocalState copyWith(void Function(LocalState) updates) => + super.copyWith((message) => updates(message as LocalState)) as LocalState; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use LocalState() / LocalState.new instead') + static LocalState create() => LocalState._(); + static $pb.GeneratedMessage $_createMessage() => LocalState._(); + @$core.override + LocalState createEmptyInstance() => LocalState._(); + @$core.pragma('dart2js:noInline') + static LocalState getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(LocalState.$_createMessage); + static LocalState? _defaultInstance; + + @$pb.TagNumber(1) + DesiredState get desired => $_getN(0); + @$pb.TagNumber(1) + set desired(DesiredState value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasDesired() => $_has(0); + @$pb.TagNumber(1) + void clearDesired() => $_clearField(1); + @$pb.TagNumber(1) + DesiredState ensureDesired() => $_ensure(0); + + @$pb.TagNumber(2) + $core.bool get locallySuspended => $_getBF(1); + @$pb.TagNumber(2) + set locallySuspended($core.bool value) => $_setBool(1, value); + @$pb.TagNumber(2) + $core.bool hasLocallySuspended() => $_has(1); + @$pb.TagNumber(2) + void clearLocallySuspended() => $_clearField(2); + + @$pb.TagNumber(3) + $core.String get suspensionReason => $_getSZ(2); + @$pb.TagNumber(3) + set suspensionReason($core.String value) => $_setString(2, value); + @$pb.TagNumber(3) + $core.bool hasSuspensionReason() => $_has(2); + @$pb.TagNumber(3) + void clearSuspensionReason() => $_clearField(3); + + @$pb.TagNumber(4) + $pb.PbList get records => $_getList(3); + + @$pb.TagNumber(5) + $0.Timestamp get updatedAt => $_getN(4); + @$pb.TagNumber(5) + set updatedAt($0.Timestamp value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasUpdatedAt() => $_has(4); + @$pb.TagNumber(5) + void clearUpdatedAt() => $_clearField(5); + @$pb.TagNumber(5) + $0.Timestamp ensureUpdatedAt() => $_ensure(4); +} + +class HostEvidence extends $pb.GeneratedMessage { + factory HostEvidence({ + $core.String? agentId, + $fixnum.Int64? sockets, + $fixnum.Int64? bytesAcked, + $core.double? goodputBps, + $core.double? retransmissionRatio, + $core.double? rttP95Ms, + $fixnum.Int64? exposedSockets, + $core.bool? collectionHealthy, + $fixnum.Int64? unboundSockets, + }) { + final result = HostEvidence._(); + if (agentId != null) result.agentId = agentId; + if (sockets != null) result.sockets = sockets; + if (bytesAcked != null) result.bytesAcked = bytesAcked; + if (goodputBps != null) result.goodputBps = goodputBps; + if (retransmissionRatio != null) + result.retransmissionRatio = retransmissionRatio; + if (rttP95Ms != null) result.rttP95Ms = rttP95Ms; + if (exposedSockets != null) result.exposedSockets = exposedSockets; + if (collectionHealthy != null) result.collectionHealthy = collectionHealthy; + if (unboundSockets != null) result.unboundSockets = unboundSockets; + return result; + } + + HostEvidence._(); + + factory HostEvidence.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + HostEvidence()..mergeFromBuffer(data, registry); + factory HostEvidence.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + HostEvidence()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'HostEvidence', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: HostEvidence.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'agentId') + ..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'sockets', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..a<$fixnum.Int64>( + 3, _omitFieldNames ? '' : 'bytesAcked', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aD(4, _omitFieldNames ? '' : 'goodputBps') + ..aD(5, _omitFieldNames ? '' : 'retransmissionRatio') + ..aD(6, _omitFieldNames ? '' : 'rttP95Ms') + ..a<$fixnum.Int64>( + 7, _omitFieldNames ? '' : 'exposedSockets', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOB(8, _omitFieldNames ? '' : 'collectionHealthy') + ..a<$fixnum.Int64>( + 9, _omitFieldNames ? '' : 'unboundSockets', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + HostEvidence clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + HostEvidence copyWith(void Function(HostEvidence) updates) => + super.copyWith((message) => updates(message as HostEvidence)) + as HostEvidence; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use HostEvidence() / HostEvidence.new instead') + static HostEvidence create() => HostEvidence._(); + static $pb.GeneratedMessage $_createMessage() => HostEvidence._(); + @$core.override + HostEvidence createEmptyInstance() => HostEvidence._(); + @$core.pragma('dart2js:noInline') + static HostEvidence getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + HostEvidence.$_createMessage); + static HostEvidence? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get agentId => $_getSZ(0); + @$pb.TagNumber(1) + set agentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasAgentId() => $_has(0); + @$pb.TagNumber(1) + void clearAgentId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get sockets => $_getI64(1); + @$pb.TagNumber(2) + set sockets($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasSockets() => $_has(1); + @$pb.TagNumber(2) + void clearSockets() => $_clearField(2); + + @$pb.TagNumber(3) + $fixnum.Int64 get bytesAcked => $_getI64(2); + @$pb.TagNumber(3) + set bytesAcked($fixnum.Int64 value) => $_setInt64(2, value); + @$pb.TagNumber(3) + $core.bool hasBytesAcked() => $_has(2); + @$pb.TagNumber(3) + void clearBytesAcked() => $_clearField(3); + + @$pb.TagNumber(4) + $core.double get goodputBps => $_getN(3); + @$pb.TagNumber(4) + set goodputBps($core.double value) => $_setDouble(3, value); + @$pb.TagNumber(4) + $core.bool hasGoodputBps() => $_has(3); + @$pb.TagNumber(4) + void clearGoodputBps() => $_clearField(4); + + @$pb.TagNumber(5) + $core.double get retransmissionRatio => $_getN(4); + @$pb.TagNumber(5) + set retransmissionRatio($core.double value) => $_setDouble(4, value); + @$pb.TagNumber(5) + $core.bool hasRetransmissionRatio() => $_has(4); + @$pb.TagNumber(5) + void clearRetransmissionRatio() => $_clearField(5); + + @$pb.TagNumber(6) + $core.double get rttP95Ms => $_getN(5); + @$pb.TagNumber(6) + set rttP95Ms($core.double value) => $_setDouble(5, value); + @$pb.TagNumber(6) + $core.bool hasRttP95Ms() => $_has(5); + @$pb.TagNumber(6) + void clearRttP95Ms() => $_clearField(6); + + @$pb.TagNumber(7) + $fixnum.Int64 get exposedSockets => $_getI64(6); + @$pb.TagNumber(7) + set exposedSockets($fixnum.Int64 value) => $_setInt64(6, value); + @$pb.TagNumber(7) + $core.bool hasExposedSockets() => $_has(6); + @$pb.TagNumber(7) + void clearExposedSockets() => $_clearField(7); + + @$pb.TagNumber(8) + $core.bool get collectionHealthy => $_getBF(7); + @$pb.TagNumber(8) + set collectionHealthy($core.bool value) => $_setBool(7, value); + @$pb.TagNumber(8) + $core.bool hasCollectionHealthy() => $_has(7); + @$pb.TagNumber(8) + void clearCollectionHealthy() => $_clearField(8); + + /// Sockets stamped with this agent_id whose boot and collection nonce + /// match no session the agent reported. They are excluded from every other + /// field and counted here so a reviewer can see them. + @$pb.TagNumber(9) + $fixnum.Int64 get unboundSockets => $_getI64(8); + @$pb.TagNumber(9) + set unboundSockets($fixnum.Int64 value) => $_setInt64(8, value); + @$pb.TagNumber(9) + $core.bool hasUnboundSockets() => $_has(8); + @$pb.TagNumber(9) + void clearUnboundSockets() => $_clearField(9); +} + +class Evidence extends $pb.GeneratedMessage { + factory Evidence({ + $core.String? id, + $0.Timestamp? analyzedAt, + $0.Timestamp? windowStart, + $0.Timestamp? windowEnd, + $core.String? queryVersion, + $core.String? enrichmentVersion, + $core.Iterable? hosts, + $core.String? artifactSha256, + }) { + final result = Evidence._(); + if (id != null) result.id = id; + if (analyzedAt != null) result.analyzedAt = analyzedAt; + if (windowStart != null) result.windowStart = windowStart; + if (windowEnd != null) result.windowEnd = windowEnd; + if (queryVersion != null) result.queryVersion = queryVersion; + if (enrichmentVersion != null) result.enrichmentVersion = enrichmentVersion; + if (hosts != null) result.hosts.addAll(hosts); + if (artifactSha256 != null) result.artifactSha256 = artifactSha256; + return result; + } + + Evidence._(); + + factory Evidence.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Evidence()..mergeFromBuffer(data, registry); + factory Evidence.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Evidence()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Evidence', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: Evidence.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'id') + ..aOM<$0.Timestamp>(2, _omitFieldNames ? '' : 'analyzedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(3, _omitFieldNames ? '' : 'windowStart', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(4, _omitFieldNames ? '' : 'windowEnd', + subBuilder: $0.Timestamp.$_createMessage) + ..aOS(5, _omitFieldNames ? '' : 'queryVersion') + ..aOS(6, _omitFieldNames ? '' : 'enrichmentVersion') + ..pPM(7, _omitFieldNames ? '' : 'hosts', + subBuilder: HostEvidence.$_createMessage) + ..aOS(8, _omitFieldNames ? '' : 'artifactSha256') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Evidence clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Evidence copyWith(void Function(Evidence) updates) => + super.copyWith((message) => updates(message as Evidence)) as Evidence; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Evidence() / Evidence.new instead') + static Evidence create() => Evidence._(); + static $pb.GeneratedMessage $_createMessage() => Evidence._(); + @$core.override + Evidence createEmptyInstance() => Evidence._(); + @$core.pragma('dart2js:noInline') + static Evidence getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Evidence.$_createMessage); + static Evidence? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get id => $_getSZ(0); + @$pb.TagNumber(1) + set id($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + $0.Timestamp get analyzedAt => $_getN(1); + @$pb.TagNumber(2) + set analyzedAt($0.Timestamp value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasAnalyzedAt() => $_has(1); + @$pb.TagNumber(2) + void clearAnalyzedAt() => $_clearField(2); + @$pb.TagNumber(2) + $0.Timestamp ensureAnalyzedAt() => $_ensure(1); + + @$pb.TagNumber(3) + $0.Timestamp get windowStart => $_getN(2); + @$pb.TagNumber(3) + set windowStart($0.Timestamp value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasWindowStart() => $_has(2); + @$pb.TagNumber(3) + void clearWindowStart() => $_clearField(3); + @$pb.TagNumber(3) + $0.Timestamp ensureWindowStart() => $_ensure(2); + + @$pb.TagNumber(4) + $0.Timestamp get windowEnd => $_getN(3); + @$pb.TagNumber(4) + set windowEnd($0.Timestamp value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasWindowEnd() => $_has(3); + @$pb.TagNumber(4) + void clearWindowEnd() => $_clearField(4); + @$pb.TagNumber(4) + $0.Timestamp ensureWindowEnd() => $_ensure(3); + + @$pb.TagNumber(5) + $core.String get queryVersion => $_getSZ(4); + @$pb.TagNumber(5) + set queryVersion($core.String value) => $_setString(4, value); + @$pb.TagNumber(5) + $core.bool hasQueryVersion() => $_has(4); + @$pb.TagNumber(5) + void clearQueryVersion() => $_clearField(5); + + @$pb.TagNumber(6) + $core.String get enrichmentVersion => $_getSZ(5); + @$pb.TagNumber(6) + set enrichmentVersion($core.String value) => $_setString(5, value); + @$pb.TagNumber(6) + $core.bool hasEnrichmentVersion() => $_has(5); + @$pb.TagNumber(6) + void clearEnrichmentVersion() => $_clearField(6); + + @$pb.TagNumber(7) + $pb.PbList get hosts => $_getList(6); + + /// SHA-256 of the raw warehouse response bytes, as received, that this + /// summary was decoded from. The response itself is not archived: the + /// digest lets two controllers (or a later audit) confirm they decoded the + /// same bytes, and reproducing it means re-running query_version over + /// [window_start, window_end) against the same table. Archiving responses + /// to object storage is a possible follow-up, not a current guarantee. + @$pb.TagNumber(8) + $core.String get artifactSha256 => $_getSZ(7); + @$pb.TagNumber(8) + set artifactSha256($core.String value) => $_setString(7, value); + @$pb.TagNumber(8) + $core.bool hasArtifactSha256() => $_has(7); + @$pb.TagNumber(8) + void clearArtifactSha256() => $_clearField(8); +} + +class ExperimentPolicy extends $pb.GeneratedMessage { + factory ExperimentPolicy({ + $1.Duration? minimumObservation, + $1.Duration? maximumPhase, + $fixnum.Int64? minimumSocketsPerHost, + $fixnum.Int64? minimumBytesPerHost, + $core.int? minimumTreatedHosts, + $core.double? minimumImprovement, + $core.double? maximumRetransmissionIncrease, + $core.double? maximumRttIncrease, + $1.Duration? maximumEvidenceAge, + }) { + final result = ExperimentPolicy._(); + if (minimumObservation != null) + result.minimumObservation = minimumObservation; + if (maximumPhase != null) result.maximumPhase = maximumPhase; + if (minimumSocketsPerHost != null) + result.minimumSocketsPerHost = minimumSocketsPerHost; + if (minimumBytesPerHost != null) + result.minimumBytesPerHost = minimumBytesPerHost; + if (minimumTreatedHosts != null) + result.minimumTreatedHosts = minimumTreatedHosts; + if (minimumImprovement != null) + result.minimumImprovement = minimumImprovement; + if (maximumRetransmissionIncrease != null) + result.maximumRetransmissionIncrease = maximumRetransmissionIncrease; + if (maximumRttIncrease != null) + result.maximumRttIncrease = maximumRttIncrease; + if (maximumEvidenceAge != null) + result.maximumEvidenceAge = maximumEvidenceAge; + return result; + } + + ExperimentPolicy._(); + + factory ExperimentPolicy.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ExperimentPolicy()..mergeFromBuffer(data, registry); + factory ExperimentPolicy.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + ExperimentPolicy()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ExperimentPolicy', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: ExperimentPolicy.$_createMessage) + ..aOM<$1.Duration>(1, _omitFieldNames ? '' : 'minimumObservation', + subBuilder: $1.Duration.$_createMessage) + ..aOM<$1.Duration>(2, _omitFieldNames ? '' : 'maximumPhase', + subBuilder: $1.Duration.$_createMessage) + ..a<$fixnum.Int64>( + 3, _omitFieldNames ? '' : 'minimumSocketsPerHost', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..a<$fixnum.Int64>( + 4, _omitFieldNames ? '' : 'minimumBytesPerHost', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aI(5, _omitFieldNames ? '' : 'minimumTreatedHosts', + fieldType: $pb.PbFieldType.OU3) + ..aD(6, _omitFieldNames ? '' : 'minimumImprovement') + ..aD(7, _omitFieldNames ? '' : 'maximumRetransmissionIncrease') + ..aD(8, _omitFieldNames ? '' : 'maximumRttIncrease') + ..aOM<$1.Duration>(9, _omitFieldNames ? '' : 'maximumEvidenceAge', + subBuilder: $1.Duration.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ExperimentPolicy clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ExperimentPolicy copyWith(void Function(ExperimentPolicy) updates) => + super.copyWith((message) => updates(message as ExperimentPolicy)) + as ExperimentPolicy; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use ExperimentPolicy() / ExperimentPolicy.new instead') + static ExperimentPolicy create() => ExperimentPolicy._(); + static $pb.GeneratedMessage $_createMessage() => ExperimentPolicy._(); + @$core.override + ExperimentPolicy createEmptyInstance() => ExperimentPolicy._(); + @$core.pragma('dart2js:noInline') + static ExperimentPolicy getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + ExperimentPolicy.$_createMessage); + static ExperimentPolicy? _defaultInstance; + + @$pb.TagNumber(1) + $1.Duration get minimumObservation => $_getN(0); + @$pb.TagNumber(1) + set minimumObservation($1.Duration value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasMinimumObservation() => $_has(0); + @$pb.TagNumber(1) + void clearMinimumObservation() => $_clearField(1); + @$pb.TagNumber(1) + $1.Duration ensureMinimumObservation() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Duration get maximumPhase => $_getN(1); + @$pb.TagNumber(2) + set maximumPhase($1.Duration value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasMaximumPhase() => $_has(1); + @$pb.TagNumber(2) + void clearMaximumPhase() => $_clearField(2); + @$pb.TagNumber(2) + $1.Duration ensureMaximumPhase() => $_ensure(1); + + @$pb.TagNumber(3) + $fixnum.Int64 get minimumSocketsPerHost => $_getI64(2); + @$pb.TagNumber(3) + set minimumSocketsPerHost($fixnum.Int64 value) => $_setInt64(2, value); + @$pb.TagNumber(3) + $core.bool hasMinimumSocketsPerHost() => $_has(2); + @$pb.TagNumber(3) + void clearMinimumSocketsPerHost() => $_clearField(3); + + @$pb.TagNumber(4) + $fixnum.Int64 get minimumBytesPerHost => $_getI64(3); + @$pb.TagNumber(4) + set minimumBytesPerHost($fixnum.Int64 value) => $_setInt64(3, value); + @$pb.TagNumber(4) + $core.bool hasMinimumBytesPerHost() => $_has(3); + @$pb.TagNumber(4) + void clearMinimumBytesPerHost() => $_clearField(4); + + @$pb.TagNumber(5) + $core.int get minimumTreatedHosts => $_getIZ(4); + @$pb.TagNumber(5) + set minimumTreatedHosts($core.int value) => $_setUnsignedInt32(4, value); + @$pb.TagNumber(5) + $core.bool hasMinimumTreatedHosts() => $_has(4); + @$pb.TagNumber(5) + void clearMinimumTreatedHosts() => $_clearField(5); + + @$pb.TagNumber(6) + $core.double get minimumImprovement => $_getN(5); + @$pb.TagNumber(6) + set minimumImprovement($core.double value) => $_setDouble(5, value); + @$pb.TagNumber(6) + $core.bool hasMinimumImprovement() => $_has(5); + @$pb.TagNumber(6) + void clearMinimumImprovement() => $_clearField(6); + + @$pb.TagNumber(7) + $core.double get maximumRetransmissionIncrease => $_getN(6); + @$pb.TagNumber(7) + set maximumRetransmissionIncrease($core.double value) => + $_setDouble(6, value); + @$pb.TagNumber(7) + $core.bool hasMaximumRetransmissionIncrease() => $_has(6); + @$pb.TagNumber(7) + void clearMaximumRetransmissionIncrease() => $_clearField(7); + + @$pb.TagNumber(8) + $core.double get maximumRttIncrease => $_getN(7); + @$pb.TagNumber(8) + set maximumRttIncrease($core.double value) => $_setDouble(7, value); + @$pb.TagNumber(8) + $core.bool hasMaximumRttIncrease() => $_has(7); + @$pb.TagNumber(8) + void clearMaximumRttIncrease() => $_clearField(8); + + @$pb.TagNumber(9) + $1.Duration get maximumEvidenceAge => $_getN(8); + @$pb.TagNumber(9) + set maximumEvidenceAge($1.Duration value) => $_setField(9, value); + @$pb.TagNumber(9) + $core.bool hasMaximumEvidenceAge() => $_has(8); + @$pb.TagNumber(9) + void clearMaximumEvidenceAge() => $_clearField(9); + @$pb.TagNumber(9) + $1.Duration ensureMaximumEvidenceAge() => $_ensure(8); +} + +class Phase extends $pb.GeneratedMessage { + factory Phase({ + $core.int? targetHosts, + $0.Timestamp? issuedAt, + $0.Timestamp? observationStartedAt, + $0.Timestamp? evaluatedAt, + Evidence? evidence, + Outcome? outcome, + $core.String? reviewer, + $core.String? reason, + }) { + final result = Phase._(); + if (targetHosts != null) result.targetHosts = targetHosts; + if (issuedAt != null) result.issuedAt = issuedAt; + if (observationStartedAt != null) + result.observationStartedAt = observationStartedAt; + if (evaluatedAt != null) result.evaluatedAt = evaluatedAt; + if (evidence != null) result.evidence = evidence; + if (outcome != null) result.outcome = outcome; + if (reviewer != null) result.reviewer = reviewer; + if (reason != null) result.reason = reason; + return result; + } + + Phase._(); + + factory Phase.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Phase()..mergeFromBuffer(data, registry); + factory Phase.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Phase()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Phase', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: Phase.$_createMessage) + ..aI(1, _omitFieldNames ? '' : 'targetHosts', + fieldType: $pb.PbFieldType.OU3) + ..aOM<$0.Timestamp>(2, _omitFieldNames ? '' : 'issuedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(3, _omitFieldNames ? '' : 'observationStartedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(4, _omitFieldNames ? '' : 'evaluatedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM(5, _omitFieldNames ? '' : 'evidence', + subBuilder: Evidence.$_createMessage) + ..aE(6, _omitFieldNames ? '' : 'outcome', + enumValues: Outcome.values) + ..aOS(7, _omitFieldNames ? '' : 'reviewer') + ..aOS(8, _omitFieldNames ? '' : 'reason') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Phase clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Phase copyWith(void Function(Phase) updates) => + super.copyWith((message) => updates(message as Phase)) as Phase; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Phase() / Phase.new instead') + static Phase create() => Phase._(); + static $pb.GeneratedMessage $_createMessage() => Phase._(); + @$core.override + Phase createEmptyInstance() => Phase._(); + @$core.pragma('dart2js:noInline') + static Phase getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Phase.$_createMessage); + static Phase? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get targetHosts => $_getIZ(0); + @$pb.TagNumber(1) + set targetHosts($core.int value) => $_setUnsignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasTargetHosts() => $_has(0); + @$pb.TagNumber(1) + void clearTargetHosts() => $_clearField(1); + + @$pb.TagNumber(2) + $0.Timestamp get issuedAt => $_getN(1); + @$pb.TagNumber(2) + set issuedAt($0.Timestamp value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasIssuedAt() => $_has(1); + @$pb.TagNumber(2) + void clearIssuedAt() => $_clearField(2); + @$pb.TagNumber(2) + $0.Timestamp ensureIssuedAt() => $_ensure(1); + + @$pb.TagNumber(3) + $0.Timestamp get observationStartedAt => $_getN(2); + @$pb.TagNumber(3) + set observationStartedAt($0.Timestamp value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasObservationStartedAt() => $_has(2); + @$pb.TagNumber(3) + void clearObservationStartedAt() => $_clearField(3); + @$pb.TagNumber(3) + $0.Timestamp ensureObservationStartedAt() => $_ensure(2); + + @$pb.TagNumber(4) + $0.Timestamp get evaluatedAt => $_getN(3); + @$pb.TagNumber(4) + set evaluatedAt($0.Timestamp value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasEvaluatedAt() => $_has(3); + @$pb.TagNumber(4) + void clearEvaluatedAt() => $_clearField(4); + @$pb.TagNumber(4) + $0.Timestamp ensureEvaluatedAt() => $_ensure(3); + + @$pb.TagNumber(5) + Evidence get evidence => $_getN(4); + @$pb.TagNumber(5) + set evidence(Evidence value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasEvidence() => $_has(4); + @$pb.TagNumber(5) + void clearEvidence() => $_clearField(5); + @$pb.TagNumber(5) + Evidence ensureEvidence() => $_ensure(4); + + @$pb.TagNumber(6) + Outcome get outcome => $_getN(5); + @$pb.TagNumber(6) + set outcome(Outcome value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasOutcome() => $_has(5); + @$pb.TagNumber(6) + void clearOutcome() => $_clearField(6); + + @$pb.TagNumber(7) + $core.String get reviewer => $_getSZ(6); + @$pb.TagNumber(7) + set reviewer($core.String value) => $_setString(6, value); + @$pb.TagNumber(7) + $core.bool hasReviewer() => $_has(6); + @$pb.TagNumber(7) + void clearReviewer() => $_clearField(7); + + @$pb.TagNumber(8) + $core.String get reason => $_getSZ(7); + @$pb.TagNumber(8) + set reason($core.String value) => $_setString(7, value); + @$pb.TagNumber(8) + $core.bool hasReason() => $_has(7); + @$pb.TagNumber(8) + void clearReason() => $_clearField(8); +} + +class Experiment extends $pb.GeneratedMessage { + factory Experiment({ + $core.String? id, + $core.String? location, + $core.String? hypothesis, + Treatment? treatment, + ExperimentPolicy? policy, + Evidence? baseline, + $core.Iterable<$core.String>? cohortOrder, + $core.Iterable? phases, + ExperimentStatus? status, + $fixnum.Int64? revision, + $0.Timestamp? proposedAt, + Evidence? latestEvidence, + Outcome? latestOutcome, + $0.Timestamp? updatedAt, + }) { + final result = Experiment._(); + if (id != null) result.id = id; + if (location != null) result.location = location; + if (hypothesis != null) result.hypothesis = hypothesis; + if (treatment != null) result.treatment = treatment; + if (policy != null) result.policy = policy; + if (baseline != null) result.baseline = baseline; + if (cohortOrder != null) result.cohortOrder.addAll(cohortOrder); + if (phases != null) result.phases.addAll(phases); + if (status != null) result.status = status; + if (revision != null) result.revision = revision; + if (proposedAt != null) result.proposedAt = proposedAt; + if (latestEvidence != null) result.latestEvidence = latestEvidence; + if (latestOutcome != null) result.latestOutcome = latestOutcome; + if (updatedAt != null) result.updatedAt = updatedAt; + return result; + } + + Experiment._(); + + factory Experiment.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Experiment()..mergeFromBuffer(data, registry); + factory Experiment.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Experiment()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Experiment', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'xtcp_treatment.v1'), + createEmptyInstance: Experiment.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'id') + ..aOS(2, _omitFieldNames ? '' : 'location') + ..aOS(3, _omitFieldNames ? '' : 'hypothesis') + ..aOM(4, _omitFieldNames ? '' : 'treatment', + subBuilder: Treatment.$_createMessage) + ..aOM(5, _omitFieldNames ? '' : 'policy', + subBuilder: ExperimentPolicy.$_createMessage) + ..aOM(6, _omitFieldNames ? '' : 'baseline', + subBuilder: Evidence.$_createMessage) + ..pPS(7, _omitFieldNames ? '' : 'cohortOrder') + ..pPM(8, _omitFieldNames ? '' : 'phases', + subBuilder: Phase.$_createMessage) + ..aE(9, _omitFieldNames ? '' : 'status', + enumValues: ExperimentStatus.values) + ..a<$fixnum.Int64>( + 10, _omitFieldNames ? '' : 'revision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOM<$0.Timestamp>(11, _omitFieldNames ? '' : 'proposedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM(12, _omitFieldNames ? '' : 'latestEvidence', + subBuilder: Evidence.$_createMessage) + ..aE(13, _omitFieldNames ? '' : 'latestOutcome', + enumValues: Outcome.values) + ..aOM<$0.Timestamp>(14, _omitFieldNames ? '' : 'updatedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Experiment clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Experiment copyWith(void Function(Experiment) updates) => + super.copyWith((message) => updates(message as Experiment)) as Experiment; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Experiment() / Experiment.new instead') + static Experiment create() => Experiment._(); + static $pb.GeneratedMessage $_createMessage() => Experiment._(); + @$core.override + Experiment createEmptyInstance() => Experiment._(); + @$core.pragma('dart2js:noInline') + static Experiment getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Experiment.$_createMessage); + static Experiment? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get id => $_getSZ(0); + @$pb.TagNumber(1) + set id($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get location => $_getSZ(1); + @$pb.TagNumber(2) + set location($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasLocation() => $_has(1); + @$pb.TagNumber(2) + void clearLocation() => $_clearField(2); + + @$pb.TagNumber(3) + $core.String get hypothesis => $_getSZ(2); + @$pb.TagNumber(3) + set hypothesis($core.String value) => $_setString(2, value); + @$pb.TagNumber(3) + $core.bool hasHypothesis() => $_has(2); + @$pb.TagNumber(3) + void clearHypothesis() => $_clearField(3); + + @$pb.TagNumber(4) + Treatment get treatment => $_getN(3); + @$pb.TagNumber(4) + set treatment(Treatment value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasTreatment() => $_has(3); + @$pb.TagNumber(4) + void clearTreatment() => $_clearField(4); + @$pb.TagNumber(4) + Treatment ensureTreatment() => $_ensure(3); + + @$pb.TagNumber(5) + ExperimentPolicy get policy => $_getN(4); + @$pb.TagNumber(5) + set policy(ExperimentPolicy value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasPolicy() => $_has(4); + @$pb.TagNumber(5) + void clearPolicy() => $_clearField(5); + @$pb.TagNumber(5) + ExperimentPolicy ensurePolicy() => $_ensure(4); + + @$pb.TagNumber(6) + Evidence get baseline => $_getN(5); + @$pb.TagNumber(6) + set baseline(Evidence value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasBaseline() => $_has(5); + @$pb.TagNumber(6) + void clearBaseline() => $_clearField(6); + @$pb.TagNumber(6) + Evidence ensureBaseline() => $_ensure(5); + + /// Randomised host order; phases treat a growing prefix of it. + @$pb.TagNumber(7) + $pb.PbList<$core.String> get cohortOrder => $_getList(6); + + @$pb.TagNumber(8) + $pb.PbList get phases => $_getList(7); + + @$pb.TagNumber(9) + ExperimentStatus get status => $_getN(8); + @$pb.TagNumber(9) + set status(ExperimentStatus value) => $_setField(9, value); + @$pb.TagNumber(9) + $core.bool hasStatus() => $_has(8); + @$pb.TagNumber(9) + void clearStatus() => $_clearField(9); + + @$pb.TagNumber(10) + $fixnum.Int64 get revision => $_getI64(9); + @$pb.TagNumber(10) + set revision($fixnum.Int64 value) => $_setInt64(9, value); + @$pb.TagNumber(10) + $core.bool hasRevision() => $_has(9); + @$pb.TagNumber(10) + void clearRevision() => $_clearField(10); + + @$pb.TagNumber(11) + $0.Timestamp get proposedAt => $_getN(10); + @$pb.TagNumber(11) + set proposedAt($0.Timestamp value) => $_setField(11, value); + @$pb.TagNumber(11) + $core.bool hasProposedAt() => $_has(10); + @$pb.TagNumber(11) + void clearProposedAt() => $_clearField(11); + @$pb.TagNumber(11) + $0.Timestamp ensureProposedAt() => $_ensure(10); + + @$pb.TagNumber(12) + Evidence get latestEvidence => $_getN(11); + @$pb.TagNumber(12) + set latestEvidence(Evidence value) => $_setField(12, value); + @$pb.TagNumber(12) + $core.bool hasLatestEvidence() => $_has(11); + @$pb.TagNumber(12) + void clearLatestEvidence() => $_clearField(12); + @$pb.TagNumber(12) + Evidence ensureLatestEvidence() => $_ensure(11); + + @$pb.TagNumber(13) + Outcome get latestOutcome => $_getN(12); + @$pb.TagNumber(13) + set latestOutcome(Outcome value) => $_setField(13, value); + @$pb.TagNumber(13) + $core.bool hasLatestOutcome() => $_has(12); + @$pb.TagNumber(13) + void clearLatestOutcome() => $_clearField(13); + + /// When the controller last changed this experiment. Terminal experiments + /// suppress rediscovery of their destination for a day after this instant. + @$pb.TagNumber(14) + $0.Timestamp get updatedAt => $_getN(13); + @$pb.TagNumber(14) + set updatedAt($0.Timestamp value) => $_setField(14, value); + @$pb.TagNumber(14) + $core.bool hasUpdatedAt() => $_has(13); + @$pb.TagNumber(14) + void clearUpdatedAt() => $_clearField(14); + @$pb.TagNumber(14) + $0.Timestamp ensureUpdatedAt() => $_ensure(13); +} + +class TreatmentExt { + static final role = $pb.Extension( + _omitMessageNames ? '' : 'google.protobuf.MethodOptions', + _omitFieldNames ? '' : 'role', + 51002, + $pb.PbFieldType.OE, + defaultOrMaker: Role.ROLE_UNSPECIFIED, + valueOf: Role.valueOf, + enumValues: Role.values); + static void registerAllExtensions($pb.ExtensionRegistry registry) { + registry.add(role); + } +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/gen/dart/xtcp_treatment/v1/treatment.pbenum.dart b/gen/dart/xtcp_treatment/v1/treatment.pbenum.dart new file mode 100644 index 000000000..d108c6737 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/treatment.pbenum.dart @@ -0,0 +1,236 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/treatment.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +/// Role is the certificate class an RPC requires. The server resolves the +/// caller's SPIFFE identity once per call and compares it with this option; +/// a method without a declaration is refused for everyone (fail closed). +class Role extends $pb.ProtobufEnum { + static const Role ROLE_UNSPECIFIED = + Role._(0, _omitEnumNames ? '' : 'ROLE_UNSPECIFIED'); + + /// spiffe://xtcp/agent//; may only speak for its own agent_id. + static const Role ROLE_AGENT = Role._(1, _omitEnumNames ? '' : 'ROLE_AGENT'); + + /// spiffe://xtcp/operator/; recorded as the audit actor. + static const Role ROLE_OPERATOR = + Role._(2, _omitEnumNames ? '' : 'ROLE_OPERATOR'); + + static const $core.List values = [ + ROLE_UNSPECIFIED, + ROLE_AGENT, + ROLE_OPERATOR, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 2); + static Role? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const Role._(super.value, super.name); +} + +class AssignmentMode extends $pb.ProtobufEnum { + static const AssignmentMode ASSIGNMENT_MODE_UNSPECIFIED = + AssignmentMode._(0, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_UNSPECIFIED'); + static const AssignmentMode ASSIGNMENT_MODE_TRIAL = + AssignmentMode._(1, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_TRIAL'); + static const AssignmentMode ASSIGNMENT_MODE_STABLE = + AssignmentMode._(2, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_STABLE'); + static const AssignmentMode ASSIGNMENT_MODE_SUSPENDED = + AssignmentMode._(3, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_SUSPENDED'); + static const AssignmentMode ASSIGNMENT_MODE_RETIRED = + AssignmentMode._(4, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_RETIRED'); + + static const $core.List values = [ + ASSIGNMENT_MODE_UNSPECIFIED, + ASSIGNMENT_MODE_TRIAL, + ASSIGNMENT_MODE_STABLE, + ASSIGNMENT_MODE_SUSPENDED, + ASSIGNMENT_MODE_RETIRED, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 4); + static AssignmentMode? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const AssignmentMode._(super.value, super.name); +} + +class ApplyStatus extends $pb.ProtobufEnum { + static const ApplyStatus APPLY_STATUS_UNSPECIFIED = + ApplyStatus._(0, _omitEnumNames ? '' : 'APPLY_STATUS_UNSPECIFIED'); + static const ApplyStatus APPLY_STATUS_PENDING = + ApplyStatus._(1, _omitEnumNames ? '' : 'APPLY_STATUS_PENDING'); + static const ApplyStatus APPLY_STATUS_VERIFIED = + ApplyStatus._(2, _omitEnumNames ? '' : 'APPLY_STATUS_VERIFIED'); + static const ApplyStatus APPLY_STATUS_REMOVED = + ApplyStatus._(3, _omitEnumNames ? '' : 'APPLY_STATUS_REMOVED'); + static const ApplyStatus APPLY_STATUS_EXPIRED = + ApplyStatus._(4, _omitEnumNames ? '' : 'APPLY_STATUS_EXPIRED'); + static const ApplyStatus APPLY_STATUS_FAILED = + ApplyStatus._(5, _omitEnumNames ? '' : 'APPLY_STATUS_FAILED'); + + static const $core.List values = [ + APPLY_STATUS_UNSPECIFIED, + APPLY_STATUS_PENDING, + APPLY_STATUS_VERIFIED, + APPLY_STATUS_REMOVED, + APPLY_STATUS_EXPIRED, + APPLY_STATUS_FAILED, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 5); + static ApplyStatus? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const ApplyStatus._(super.value, super.name); +} + +/// Outcome is the result of evaluating one evidence window against a phase, +/// or the standing of a completed treatment under drift monitoring. Only +/// BENEFICIAL, SAFETY_ONLY and FINAL_SAFETY can advance a phase, and only +/// after an operator review; HARMFUL and EXPIRED withdraw automatically. +class Outcome extends $pb.ProtobufEnum { + static const Outcome OUTCOME_UNSPECIFIED = + Outcome._(0, _omitEnumNames ? '' : 'OUTCOME_UNSPECIFIED'); + + /// Analysis of a proposal that has no phase yet. + static const Outcome OUTCOME_BASELINE = + Outcome._(1, _omitEnumNames ? '' : 'OUTCOME_BASELINE'); + + /// Not every treated host has verified the assignment. + static const Outcome OUTCOME_AWAITING_APPLICATION = + Outcome._(2, _omitEnumNames ? '' : 'OUTCOME_AWAITING_APPLICATION'); + + /// Treated hosts have not yet carried enough exposed sockets. + static const Outcome OUTCOME_AWAITING_EXPOSURE = + Outcome._(3, _omitEnumNames ? '' : 'OUTCOME_AWAITING_EXPOSURE'); + static const Outcome OUTCOME_INSUFFICIENT_DURATION = + Outcome._(4, _omitEnumNames ? '' : 'OUTCOME_INSUFFICIENT_DURATION'); + static const Outcome OUTCOME_INSUFFICIENT_DATA = + Outcome._(5, _omitEnumNames ? '' : 'OUTCOME_INSUFFICIENT_DATA'); + static const Outcome OUTCOME_INSUFFICIENT_CONTROLS = + Outcome._(6, _omitEnumNames ? '' : 'OUTCOME_INSUFFICIENT_CONTROLS'); + static const Outcome OUTCOME_STALE = + Outcome._(7, _omitEnumNames ? '' : 'OUTCOME_STALE'); + + /// No evidence source was available for this maintenance pass. + static const Outcome OUTCOME_UNAVAILABLE = + Outcome._(8, _omitEnumNames ? '' : 'OUTCOME_UNAVAILABLE'); + static const Outcome OUTCOME_INCONCLUSIVE = + Outcome._(9, _omitEnumNames ? '' : 'OUTCOME_INCONCLUSIVE'); + + /// Cohort too small for a causal estimate; no regression observed. + static const Outcome OUTCOME_SAFETY_ONLY = + Outcome._(10, _omitEnumNames ? '' : 'OUTCOME_SAFETY_ONLY'); + + /// Final 100% phase: no controls remain; no regression observed. + static const Outcome OUTCOME_FINAL_SAFETY = + Outcome._(11, _omitEnumNames ? '' : 'OUTCOME_FINAL_SAFETY'); + static const Outcome OUTCOME_BENEFICIAL = + Outcome._(12, _omitEnumNames ? '' : 'OUTCOME_BENEFICIAL'); + static const Outcome OUTCOME_HARMFUL = + Outcome._(13, _omitEnumNames ? '' : 'OUTCOME_HARMFUL'); + static const Outcome OUTCOME_EXPIRED = + Outcome._(14, _omitEnumNames ? '' : 'OUTCOME_EXPIRED'); + + /// Completed treatment under drift monitoring. + static const Outcome OUTCOME_STABLE_OBSERVED = + Outcome._(15, _omitEnumNames ? '' : 'OUTCOME_STABLE_OBSERVED'); + static const Outcome OUTCOME_STABLE_EVIDENCE_INCOMPLETE = + Outcome._(16, _omitEnumNames ? '' : 'OUTCOME_STABLE_EVIDENCE_INCOMPLETE'); + static const Outcome OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED = Outcome._( + 17, _omitEnumNames ? '' : 'OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED'); + + /// Every treated host has verified the assignment; the observation window + /// is open and no evidence has been evaluated yet. + static const Outcome OUTCOME_OBSERVING = + Outcome._(18, _omitEnumNames ? '' : 'OUTCOME_OBSERVING'); + + static const $core.List values = [ + OUTCOME_UNSPECIFIED, + OUTCOME_BASELINE, + OUTCOME_AWAITING_APPLICATION, + OUTCOME_AWAITING_EXPOSURE, + OUTCOME_INSUFFICIENT_DURATION, + OUTCOME_INSUFFICIENT_DATA, + OUTCOME_INSUFFICIENT_CONTROLS, + OUTCOME_STALE, + OUTCOME_UNAVAILABLE, + OUTCOME_INCONCLUSIVE, + OUTCOME_SAFETY_ONLY, + OUTCOME_FINAL_SAFETY, + OUTCOME_BENEFICIAL, + OUTCOME_HARMFUL, + OUTCOME_EXPIRED, + OUTCOME_STABLE_OBSERVED, + OUTCOME_STABLE_EVIDENCE_INCOMPLETE, + OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED, + OUTCOME_OBSERVING, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 18); + static Outcome? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const Outcome._(super.value, super.name); +} + +class ExperimentStatus extends $pb.ProtobufEnum { + static const ExperimentStatus EXPERIMENT_STATUS_UNSPECIFIED = + ExperimentStatus._( + 0, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_UNSPECIFIED'); + static const ExperimentStatus EXPERIMENT_STATUS_PROPOSED = + ExperimentStatus._(1, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_PROPOSED'); + static const ExperimentStatus EXPERIMENT_STATUS_RUNNING = + ExperimentStatus._(2, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_RUNNING'); + static const ExperimentStatus EXPERIMENT_STATUS_PAUSED = + ExperimentStatus._(3, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_PAUSED'); + static const ExperimentStatus EXPERIMENT_STATUS_SUSPENDED = + ExperimentStatus._( + 4, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_SUSPENDED'); + static const ExperimentStatus EXPERIMENT_STATUS_COMPLETE = + ExperimentStatus._(5, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_COMPLETE'); + static const ExperimentStatus EXPERIMENT_STATUS_RETIRED = + ExperimentStatus._(6, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_RETIRED'); + static const ExperimentStatus EXPERIMENT_STATUS_ROLLED_BACK = + ExperimentStatus._( + 7, _omitEnumNames ? '' : 'EXPERIMENT_STATUS_ROLLED_BACK'); + + static const $core.List values = [ + EXPERIMENT_STATUS_UNSPECIFIED, + EXPERIMENT_STATUS_PROPOSED, + EXPERIMENT_STATUS_RUNNING, + EXPERIMENT_STATUS_PAUSED, + EXPERIMENT_STATUS_SUSPENDED, + EXPERIMENT_STATUS_COMPLETE, + EXPERIMENT_STATUS_RETIRED, + EXPERIMENT_STATUS_ROLLED_BACK, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 7); + static ExperimentStatus? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const ExperimentStatus._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/gen/dart/xtcp_treatment/v1/treatment.pbjson.dart b/gen/dart/xtcp_treatment/v1/treatment.pbjson.dart new file mode 100644 index 000000000..44fea2b21 --- /dev/null +++ b/gen/dart/xtcp_treatment/v1/treatment.pbjson.dart @@ -0,0 +1,983 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment/v1/treatment.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use roleDescriptor instead') +const Role$json = { + '1': 'Role', + '2': [ + {'1': 'ROLE_UNSPECIFIED', '2': 0}, + {'1': 'ROLE_AGENT', '2': 1}, + {'1': 'ROLE_OPERATOR', '2': 2}, + ], +}; + +/// Descriptor for `Role`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List roleDescriptor = $convert.base64Decode( + 'CgRSb2xlEhQKEFJPTEVfVU5TUEVDSUZJRUQQABIOCgpST0xFX0FHRU5UEAESEQoNUk9MRV9PUE' + 'VSQVRPUhAC'); + +@$core.Deprecated('Use assignmentModeDescriptor instead') +const AssignmentMode$json = { + '1': 'AssignmentMode', + '2': [ + {'1': 'ASSIGNMENT_MODE_UNSPECIFIED', '2': 0}, + {'1': 'ASSIGNMENT_MODE_TRIAL', '2': 1}, + {'1': 'ASSIGNMENT_MODE_STABLE', '2': 2}, + {'1': 'ASSIGNMENT_MODE_SUSPENDED', '2': 3}, + {'1': 'ASSIGNMENT_MODE_RETIRED', '2': 4}, + ], +}; + +/// Descriptor for `AssignmentMode`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List assignmentModeDescriptor = $convert.base64Decode( + 'Cg5Bc3NpZ25tZW50TW9kZRIfChtBU1NJR05NRU5UX01PREVfVU5TUEVDSUZJRUQQABIZChVBU1' + 'NJR05NRU5UX01PREVfVFJJQUwQARIaChZBU1NJR05NRU5UX01PREVfU1RBQkxFEAISHQoZQVNT' + 'SUdOTUVOVF9NT0RFX1NVU1BFTkRFRBADEhsKF0FTU0lHTk1FTlRfTU9ERV9SRVRJUkVEEAQ='); + +@$core.Deprecated('Use applyStatusDescriptor instead') +const ApplyStatus$json = { + '1': 'ApplyStatus', + '2': [ + {'1': 'APPLY_STATUS_UNSPECIFIED', '2': 0}, + {'1': 'APPLY_STATUS_PENDING', '2': 1}, + {'1': 'APPLY_STATUS_VERIFIED', '2': 2}, + {'1': 'APPLY_STATUS_REMOVED', '2': 3}, + {'1': 'APPLY_STATUS_EXPIRED', '2': 4}, + {'1': 'APPLY_STATUS_FAILED', '2': 5}, + ], +}; + +/// Descriptor for `ApplyStatus`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List applyStatusDescriptor = $convert.base64Decode( + 'CgtBcHBseVN0YXR1cxIcChhBUFBMWV9TVEFUVVNfVU5TUEVDSUZJRUQQABIYChRBUFBMWV9TVE' + 'FUVVNfUEVORElORxABEhkKFUFQUExZX1NUQVRVU19WRVJJRklFRBACEhgKFEFQUExZX1NUQVRV' + 'U19SRU1PVkVEEAMSGAoUQVBQTFlfU1RBVFVTX0VYUElSRUQQBBIXChNBUFBMWV9TVEFUVVNfRk' + 'FJTEVEEAU='); + +@$core.Deprecated('Use outcomeDescriptor instead') +const Outcome$json = { + '1': 'Outcome', + '2': [ + {'1': 'OUTCOME_UNSPECIFIED', '2': 0}, + {'1': 'OUTCOME_BASELINE', '2': 1}, + {'1': 'OUTCOME_AWAITING_APPLICATION', '2': 2}, + {'1': 'OUTCOME_AWAITING_EXPOSURE', '2': 3}, + {'1': 'OUTCOME_INSUFFICIENT_DURATION', '2': 4}, + {'1': 'OUTCOME_INSUFFICIENT_DATA', '2': 5}, + {'1': 'OUTCOME_INSUFFICIENT_CONTROLS', '2': 6}, + {'1': 'OUTCOME_STALE', '2': 7}, + {'1': 'OUTCOME_UNAVAILABLE', '2': 8}, + {'1': 'OUTCOME_INCONCLUSIVE', '2': 9}, + {'1': 'OUTCOME_SAFETY_ONLY', '2': 10}, + {'1': 'OUTCOME_FINAL_SAFETY', '2': 11}, + {'1': 'OUTCOME_BENEFICIAL', '2': 12}, + {'1': 'OUTCOME_HARMFUL', '2': 13}, + {'1': 'OUTCOME_EXPIRED', '2': 14}, + {'1': 'OUTCOME_STABLE_OBSERVED', '2': 15}, + {'1': 'OUTCOME_STABLE_EVIDENCE_INCOMPLETE', '2': 16}, + {'1': 'OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED', '2': 17}, + {'1': 'OUTCOME_OBSERVING', '2': 18}, + ], +}; + +/// Descriptor for `Outcome`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List outcomeDescriptor = $convert.base64Decode( + 'CgdPdXRjb21lEhcKE09VVENPTUVfVU5TUEVDSUZJRUQQABIUChBPVVRDT01FX0JBU0VMSU5FEA' + 'ESIAocT1VUQ09NRV9BV0FJVElOR19BUFBMSUNBVElPThACEh0KGU9VVENPTUVfQVdBSVRJTkdf' + 'RVhQT1NVUkUQAxIhCh1PVVRDT01FX0lOU1VGRklDSUVOVF9EVVJBVElPThAEEh0KGU9VVENPTU' + 'VfSU5TVUZGSUNJRU5UX0RBVEEQBRIhCh1PVVRDT01FX0lOU1VGRklDSUVOVF9DT05UUk9MUxAG' + 'EhEKDU9VVENPTUVfU1RBTEUQBxIXChNPVVRDT01FX1VOQVZBSUxBQkxFEAgSGAoUT1VUQ09NRV' + '9JTkNPTkNMVVNJVkUQCRIXChNPVVRDT01FX1NBRkVUWV9PTkxZEAoSGAoUT1VUQ09NRV9GSU5B' + 'TF9TQUZFVFkQCxIWChJPVVRDT01FX0JFTkVGSUNJQUwQDBITCg9PVVRDT01FX0hBUk1GVUwQDR' + 'ITCg9PVVRDT01FX0VYUElSRUQQDhIbChdPVVRDT01FX1NUQUJMRV9PQlNFUlZFRBAPEiYKIk9V' + 'VENPTUVfU1RBQkxFX0VWSURFTkNFX0lOQ09NUExFVEUQEBItCilPVVRDT01FX1NUQUJMRV9SRU' + 'dSRVNTSU9OX1JFVklFV19SRVFVSVJFRBAREhUKEU9VVENPTUVfT0JTRVJWSU5HEBI='); + +@$core.Deprecated('Use experimentStatusDescriptor instead') +const ExperimentStatus$json = { + '1': 'ExperimentStatus', + '2': [ + {'1': 'EXPERIMENT_STATUS_UNSPECIFIED', '2': 0}, + {'1': 'EXPERIMENT_STATUS_PROPOSED', '2': 1}, + {'1': 'EXPERIMENT_STATUS_RUNNING', '2': 2}, + {'1': 'EXPERIMENT_STATUS_PAUSED', '2': 3}, + {'1': 'EXPERIMENT_STATUS_SUSPENDED', '2': 4}, + {'1': 'EXPERIMENT_STATUS_COMPLETE', '2': 5}, + {'1': 'EXPERIMENT_STATUS_RETIRED', '2': 6}, + {'1': 'EXPERIMENT_STATUS_ROLLED_BACK', '2': 7}, + ], +}; + +/// Descriptor for `ExperimentStatus`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List experimentStatusDescriptor = $convert.base64Decode( + 'ChBFeHBlcmltZW50U3RhdHVzEiEKHUVYUEVSSU1FTlRfU1RBVFVTX1VOU1BFQ0lGSUVEEAASHg' + 'oaRVhQRVJJTUVOVF9TVEFUVVNfUFJPUE9TRUQQARIdChlFWFBFUklNRU5UX1NUQVRVU19SVU5O' + 'SU5HEAISHAoYRVhQRVJJTUVOVF9TVEFUVVNfUEFVU0VEEAMSHwobRVhQRVJJTUVOVF9TVEFUVV' + 'NfU1VTUEVOREVEEAQSHgoaRVhQRVJJTUVOVF9TVEFUVVNfQ09NUExFVEUQBRIdChlFWFBFUklN' + 'RU5UX1NUQVRVU19SRVRJUkVEEAYSIQodRVhQRVJJTUVOVF9TVEFUVVNfUk9MTEVEX0JBQ0sQBw' + '=='); + +@$core.Deprecated('Use tCPSettingsDescriptor instead') +const TCPSettings$json = { + '1': 'TCPSettings', + '2': [ + { + '1': 'congestion_control', + '3': 1, + '4': 1, + '5': 9, + '8': {}, + '9': 0, + '10': 'congestionControl', + '17': true + }, + {'1': 'congestion_lock', '3': 2, '4': 1, '5': 8, '10': 'congestionLock'}, + { + '1': 'rto_min_ms', + '3': 3, + '4': 1, + '5': 13, + '8': {}, + '9': 1, + '10': 'rtoMinMs', + '17': true + }, + { + '1': 'initial_congestion_window', + '3': 4, + '4': 1, + '5': 13, + '8': {}, + '9': 2, + '10': 'initialCongestionWindow', + '17': true + }, + { + '1': 'initial_receive_window', + '3': 5, + '4': 1, + '5': 13, + '8': {}, + '9': 3, + '10': 'initialReceiveWindow', + '17': true + }, + { + '1': 'quick_ack', + '3': 6, + '4': 1, + '5': 8, + '9': 4, + '10': 'quickAck', + '17': true + }, + {'1': 'ecn', '3': 7, '4': 1, '5': 8, '9': 5, '10': 'ecn', '17': true}, + ], + '7': {}, + '8': [ + {'1': '_congestion_control'}, + {'1': '_rto_min_ms'}, + {'1': '_initial_congestion_window'}, + {'1': '_initial_receive_window'}, + {'1': '_quick_ack'}, + {'1': '_ecn'}, + ], +}; + +/// Descriptor for `TCPSettings`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List tCPSettingsDescriptor = $convert.base64Decode( + 'CgtUQ1BTZXR0aW5ncxJZChJjb25nZXN0aW9uX2NvbnRyb2wYASABKAlCJbpIInIgGA8yHF5bYS' + '16QS1aMC05XVthLXpBLVowLTlfLi1dKiRIAFIRY29uZ2VzdGlvbkNvbnRyb2yIAQESJwoPY29u' + 'Z2VzdGlvbl9sb2NrGAIgASgIUg5jb25nZXN0aW9uTG9jaxIuCgpydG9fbWluX21zGAMgASgNQg' + 'u6SAgqBhjAqQcoAUgBUghydG9NaW5Nc4gBARJLChlpbml0aWFsX2Nvbmdlc3Rpb25fd2luZG93' + 'GAQgASgNQgq6SAcqBRiACCgBSAJSF2luaXRpYWxDb25nZXN0aW9uV2luZG93iAEBEkUKFmluaX' + 'RpYWxfcmVjZWl2ZV93aW5kb3cYBSABKA1CCrpIByoFGIAIKAFIA1IUaW5pdGlhbFJlY2VpdmVX' + 'aW5kb3eIAQESIAoJcXVpY2tfYWNrGAYgASgISARSCHF1aWNrQWNriAEBEhUKA2VjbhgHIAEoCE' + 'gFUgNlY26IAQE6hwO6SIMDGvMBChZ0Y3Bfc2V0dGluZ3Mubm9uX2VtcHR5Ei9hIHRyZWF0bWVu' + 'dCBtdXN0IHNldCBhdCBsZWFzdCBvbmUgVENQIHBhcmFtZXRlchqnAWhhcyh0aGlzLmNvbmdlc3' + 'Rpb25fY29udHJvbCkgfHwgaGFzKHRoaXMucnRvX21pbl9tcykgfHwgaGFzKHRoaXMuaW5pdGlh' + 'bF9jb25nZXN0aW9uX3dpbmRvdykgfHwgaGFzKHRoaXMuaW5pdGlhbF9yZWNlaXZlX3dpbmRvdy' + 'kgfHwgaGFzKHRoaXMucXVpY2tfYWNrKSB8fCBoYXModGhpcy5lY24pGooBCiR0Y3Bfc2V0dGlu' + 'Z3MubG9ja19yZXF1aXJlc19hbGdvcml0aG0SK2Nvbmdlc3Rpb25fbG9jayByZXF1aXJlcyBjb2' + '5nZXN0aW9uX2NvbnRyb2waNSF0aGlzLmNvbmdlc3Rpb25fbG9jayB8fCBoYXModGhpcy5jb25n' + 'ZXN0aW9uX2NvbnRyb2wpQhUKE19jb25nZXN0aW9uX2NvbnRyb2xCDQoLX3J0b19taW5fbXNCHA' + 'oaX2luaXRpYWxfY29uZ2VzdGlvbl93aW5kb3dCGQoXX2luaXRpYWxfcmVjZWl2ZV93aW5kb3dC' + 'DAoKX3F1aWNrX2Fja0IGCgRfZWNu'); + +@$core.Deprecated('Use treatmentDescriptor instead') +const Treatment$json = { + '1': 'Treatment', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'id'}, + {'1': 'revision', '3': 2, '4': 1, '5': 4, '8': {}, '10': 'revision'}, + {'1': 'destination', '3': 3, '4': 1, '5': 9, '8': {}, '10': 'destination'}, + { + '1': 'settings', + '3': 4, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.TCPSettings', + '8': {}, + '10': 'settings' + }, + { + '1': 'ecn_fabric_verified', + '3': 5, + '4': 1, + '5': 8, + '10': 'ecnFabricVerified' + }, + ], + '7': {}, +}; + +/// Descriptor for `Treatment`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List treatmentDescriptor = $convert.base64Decode( + 'CglUcmVhdG1lbnQSOQoCaWQYASABKAlCKbpIJnIkMiJeW2EtekEtWjAtOV1bYS16QS1aMC05Xy' + '4tXXswLDEyN30kUgJpZBIjCghyZXZpc2lvbhgCIAEoBEIHukgEMgIgAFIIcmV2aXNpb24SLAoL' + 'ZGVzdGluYXRpb24YAyABKAlCCrpIB3IFGDHoAQFSC2Rlc3RpbmF0aW9uEkIKCHNldHRpbmdzGA' + 'QgASgLMh4ueHRjcF90cmVhdG1lbnQudjEuVENQU2V0dGluZ3NCBrpIA8gBAVIIc2V0dGluZ3MS' + 'LgoTZWNuX2ZhYnJpY192ZXJpZmllZBgFIAEoCFIRZWNuRmFicmljVmVyaWZpZWQ6yAG6SMQBGs' + 'EBChx0cmVhdG1lbnQuZGN0Y3BfcmVxdWlyZXNfZWNuEkFEQ1RDUCByZXF1aXJlcyBpbmRlcGVu' + 'ZGVudGx5IHZlcmlmaWVkIEVDTiBmYWJyaWMgYW5kIGV4cGxpY2l0IEVDThpedGhpcy5zZXR0aW' + '5ncy5jb25nZXN0aW9uX2NvbnRyb2wgIT0gJ2RjdGNwJyB8fCAodGhpcy5lY25fZmFicmljX3Zl' + 'cmlmaWVkICYmIHRoaXMuc2V0dGluZ3MuZWNuKQ=='); + +@$core.Deprecated('Use assignmentDescriptor instead') +const Assignment$json = { + '1': 'Assignment', + '2': [ + { + '1': 'experiment_id', + '3': 2, + '4': 1, + '5': 9, + '8': {}, + '10': 'experimentId' + }, + { + '1': 'treatment', + '3': 3, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Treatment', + '8': {}, + '10': 'treatment' + }, + { + '1': 'mode', + '3': 4, + '4': 1, + '5': 14, + '6': '.xtcp_treatment.v1.AssignmentMode', + '8': {}, + '10': 'mode' + }, + { + '1': 'lease_expires_at', + '3': 5, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'leaseExpiresAt' + }, + { + '1': 'predecessor', + '3': 6, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Treatment', + '10': 'predecessor' + }, + {'1': 'generation', '3': 7, '4': 1, '5': 4, '8': {}, '10': 'generation'}, + ], + '7': {}, + '9': [ + {'1': 1, '2': 2}, + ], + '10': ['id'], +}; + +/// Descriptor for `Assignment`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List assignmentDescriptor = $convert.base64Decode( + 'CgpBc3NpZ25tZW50Ek4KDWV4cGVyaW1lbnRfaWQYAiABKAlCKbpIJnIkMiJeW2EtekEtWjAtOV' + '1bYS16QS1aMC05Xy4tXXswLDEyN30kUgxleHBlcmltZW50SWQSQgoJdHJlYXRtZW50GAMgASgL' + 'MhwueHRjcF90cmVhdG1lbnQudjEuVHJlYXRtZW50Qga6SAPIAQFSCXRyZWF0bWVudBJBCgRtb2' + 'RlGAQgASgOMiEueHRjcF90cmVhdG1lbnQudjEuQXNzaWdubWVudE1vZGVCCrpIB4IBBBABIABS' + 'BG1vZGUSRAoQbGVhc2VfZXhwaXJlc19hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3' + 'RhbXBSDmxlYXNlRXhwaXJlc0F0Ej4KC3ByZWRlY2Vzc29yGAYgASgLMhwueHRjcF90cmVhdG1l' + 'bnQudjEuVHJlYXRtZW50UgtwcmVkZWNlc3NvchInCgpnZW5lcmF0aW9uGAcgASgEQge6SAQyAi' + 'AAUgpnZW5lcmF0aW9uOq0CukipAhp9Ch9hc3NpZ25tZW50LnRyaWFsX3JlcXVpcmVzX2xlYXNl' + 'EixhIHRyaWFsIGFzc2lnbm1lbnQgcmVxdWlyZXMgbGVhc2VfZXhwaXJlc19hdBosdGhpcy5tb2' + 'RlICE9IDEgfHwgaGFzKHRoaXMubGVhc2VfZXhwaXJlc19hdCkapwEKImFzc2lnbm1lbnQucHJl' + 'ZGVjZXNzb3JfZGVzdGluYXRpb24SK3ByZWRlY2Vzc29yIG11c3QgY292ZXIgdGhlIHNhbWUgZG' + 'VzdGluYXRpb24aVCFoYXModGhpcy5wcmVkZWNlc3NvcikgfHwgdGhpcy5wcmVkZWNlc3Nvci5k' + 'ZXN0aW5hdGlvbiA9PSB0aGlzLnRyZWF0bWVudC5kZXN0aW5hdGlvbkoECAEQAlICaWQ='); + +@$core.Deprecated('Use desiredStateDescriptor instead') +const DesiredState$json = { + '1': 'DesiredState', + '2': [ + {'1': 'agent_id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'agentId'}, + {'1': 'revision', '3': 2, '4': 1, '5': 4, '8': {}, '10': 'revision'}, + {'1': 'suspended', '3': 3, '4': 1, '5': 8, '10': 'suspended'}, + { + '1': 'assignments', + '3': 4, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.Assignment', + '8': {}, + '10': 'assignments' + }, + { + '1': 'issued_at', + '3': 5, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '8': {}, + '10': 'issuedAt' + }, + ], +}; + +/// Descriptor for `DesiredState`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List desiredStateDescriptor = $convert.base64Decode( + 'CgxEZXNpcmVkU3RhdGUSRAoIYWdlbnRfaWQYASABKAlCKbpIJnIkMiJeW2EtekEtWjAtOV1bYS' + '16QS1aMC05Xy4tXXswLDEyN30kUgdhZ2VudElkEiMKCHJldmlzaW9uGAIgASgEQge6SAQyAiAA' + 'UghyZXZpc2lvbhIcCglzdXNwZW5kZWQYAyABKAhSCXN1c3BlbmRlZBJKCgthc3NpZ25tZW50cx' + 'gEIAMoCzIdLnh0Y3BfdHJlYXRtZW50LnYxLkFzc2lnbm1lbnRCCbpIBpIBAxCAIFILYXNzaWdu' + 'bWVudHMSPwoJaXNzdWVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEIGuk' + 'gDyAEBUghpc3N1ZWRBdA=='); + +@$core.Deprecated('Use capabilitiesDescriptor instead') +const Capabilities$json = { + '1': 'Capabilities', + '2': [ + {'1': 'boot_id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'bootId'}, + { + '1': 'kernel_release', + '3': 2, + '4': 1, + '5': 9, + '8': {}, + '10': 'kernelRelease' + }, + { + '1': 'congestion_algorithms', + '3': 3, + '4': 3, + '5': 9, + '8': {}, + '10': 'congestionAlgorithms' + }, + { + '1': 'simple_host_routing', + '3': 4, + '4': 1, + '5': 8, + '10': 'simpleHostRouting' + }, + {'1': 'actuator_enabled', '3': 5, '4': 1, '5': 8, '10': 'actuatorEnabled'}, + { + '1': 'collection_id', + '3': 6, + '4': 1, + '5': 9, + '8': {}, + '10': 'collectionId' + }, + ], +}; + +/// Descriptor for `Capabilities`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List capabilitiesDescriptor = $convert.base64Decode( + 'CgxDYXBhYmlsaXRpZXMSQgoHYm9vdF9pZBgBIAEoCUIpukgmciQyIl5bYS16QS1aMC05XVthLX' + 'pBLVowLTlfLi1dezAsMTI3fSRSBmJvb3RJZBIvCg5rZXJuZWxfcmVsZWFzZRgCIAEoCUIIukgF' + 'cgMYgAJSDWtlcm5lbFJlbGVhc2USQwoVY29uZ2VzdGlvbl9hbGdvcml0aG1zGAMgAygJQg66SA' + 'uSAQgQQCIEcgIYD1IUY29uZ2VzdGlvbkFsZ29yaXRobXMSLgoTc2ltcGxlX2hvc3Rfcm91dGlu' + 'ZxgEIAEoCFIRc2ltcGxlSG9zdFJvdXRpbmcSKQoQYWN0dWF0b3JfZW5hYmxlZBgFIAEoCFIPYW' + 'N0dWF0b3JFbmFibGVkEjoKDWNvbGxlY3Rpb25faWQYBiABKAlCFbpIEnIQMg5eWzAtOWEtZl17' + 'MzJ9JFIMY29sbGVjdGlvbklk'); + +@$core.Deprecated('Use applicationRecordDescriptor instead') +const ApplicationRecord$json = { + '1': 'ApplicationRecord', + '2': [ + { + '1': 'assignment', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Assignment', + '8': {}, + '10': 'assignment' + }, + {'1': 'desired_revision', '3': 2, '4': 1, '5': 4, '10': 'desiredRevision'}, + { + '1': 'status', + '3': 3, + '4': 1, + '5': 14, + '6': '.xtcp_treatment.v1.ApplyStatus', + '8': {}, + '10': 'status' + }, + { + '1': 'received_at', + '3': 4, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'receivedAt' + }, + { + '1': 'attempted_at', + '3': 5, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'attemptedAt' + }, + { + '1': 'applied_at', + '3': 6, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'appliedAt' + }, + { + '1': 'verified_at', + '3': 7, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'verifiedAt' + }, + { + '1': 'removed_at', + '3': 8, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'removedAt' + }, + {'1': 'error', '3': 9, '4': 1, '5': 9, '8': {}, '10': 'error'}, + { + '1': 'installed_route', + '3': 10, + '4': 1, + '5': 12, + '8': {}, + '10': 'installedRoute' + }, + { + '1': 'installed_boot_id', + '3': 11, + '4': 1, + '5': 9, + '8': {}, + '10': 'installedBootId' + }, + {'1': 'expired_latched', '3': 12, '4': 1, '5': 8, '10': 'expiredLatched'}, + ], +}; + +/// Descriptor for `ApplicationRecord`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List applicationRecordDescriptor = $convert.base64Decode( + 'ChFBcHBsaWNhdGlvblJlY29yZBJFCgphc3NpZ25tZW50GAEgASgLMh0ueHRjcF90cmVhdG1lbn' + 'QudjEuQXNzaWdubWVudEIGukgDyAEBUgphc3NpZ25tZW50EikKEGRlc2lyZWRfcmV2aXNpb24Y' + 'AiABKARSD2Rlc2lyZWRSZXZpc2lvbhJACgZzdGF0dXMYAyABKA4yHi54dGNwX3RyZWF0bWVudC' + '52MS5BcHBseVN0YXR1c0IIukgFggECEAFSBnN0YXR1cxI7CgtyZWNlaXZlZF9hdBgEIAEoCzIa' + 'Lmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBSCnJlY2VpdmVkQXQSPQoMYXR0ZW1wdGVkX2F0GA' + 'UgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcFILYXR0ZW1wdGVkQXQSOQoKYXBwbGll' + 'ZF9hdBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBSCWFwcGxpZWRBdBI7Cgt2ZX' + 'JpZmllZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBSCnZlcmlmaWVkQXQS' + 'OQoKcmVtb3ZlZF9hdBgIIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBSCXJlbW92ZW' + 'RBdBIeCgVlcnJvchgJIAEoCUIIukgFcgMYgCBSBWVycm9yEjEKD2luc3RhbGxlZF9yb3V0ZRgK' + 'IAEoDEIIukgFegMYgCBSDmluc3RhbGxlZFJvdXRlEjQKEWluc3RhbGxlZF9ib290X2lkGAsgAS' + 'gJQgi6SAVyAxiAAVIPaW5zdGFsbGVkQm9vdElkEicKD2V4cGlyZWRfbGF0Y2hlZBgMIAEoCFIO' + 'ZXhwaXJlZExhdGNoZWQ='); + +@$core.Deprecated('Use localStateDescriptor instead') +const LocalState$json = { + '1': 'LocalState', + '2': [ + { + '1': 'desired', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.DesiredState', + '10': 'desired' + }, + { + '1': 'locally_suspended', + '3': 2, + '4': 1, + '5': 8, + '10': 'locallySuspended' + }, + { + '1': 'suspension_reason', + '3': 3, + '4': 1, + '5': 9, + '8': {}, + '10': 'suspensionReason' + }, + { + '1': 'records', + '3': 4, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.ApplicationRecord', + '8': {}, + '10': 'records' + }, + { + '1': 'updated_at', + '3': 5, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'updatedAt' + }, + ], +}; + +/// Descriptor for `LocalState`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List localStateDescriptor = $convert.base64Decode( + 'CgpMb2NhbFN0YXRlEjkKB2Rlc2lyZWQYASABKAsyHy54dGNwX3RyZWF0bWVudC52MS5EZXNpcm' + 'VkU3RhdGVSB2Rlc2lyZWQSKwoRbG9jYWxseV9zdXNwZW5kZWQYAiABKAhSEGxvY2FsbHlTdXNw' + 'ZW5kZWQSNQoRc3VzcGVuc2lvbl9yZWFzb24YAyABKAlCCLpIBXIDGIAIUhBzdXNwZW5zaW9uUm' + 'Vhc29uEkkKB3JlY29yZHMYBCADKAsyJC54dGNwX3RyZWF0bWVudC52MS5BcHBsaWNhdGlvblJl' + 'Y29yZEIJukgGkgEDEIBAUgdyZWNvcmRzEjkKCnVwZGF0ZWRfYXQYBSABKAsyGi5nb29nbGUucH' + 'JvdG9idWYuVGltZXN0YW1wUgl1cGRhdGVkQXQ='); + +@$core.Deprecated('Use hostEvidenceDescriptor instead') +const HostEvidence$json = { + '1': 'HostEvidence', + '2': [ + {'1': 'agent_id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'agentId'}, + {'1': 'sockets', '3': 2, '4': 1, '5': 4, '10': 'sockets'}, + {'1': 'bytes_acked', '3': 3, '4': 1, '5': 4, '10': 'bytesAcked'}, + {'1': 'goodput_bps', '3': 4, '4': 1, '5': 1, '8': {}, '10': 'goodputBps'}, + { + '1': 'retransmission_ratio', + '3': 5, + '4': 1, + '5': 1, + '8': {}, + '10': 'retransmissionRatio' + }, + {'1': 'rtt_p95_ms', '3': 6, '4': 1, '5': 1, '8': {}, '10': 'rttP95Ms'}, + {'1': 'exposed_sockets', '3': 7, '4': 1, '5': 4, '10': 'exposedSockets'}, + { + '1': 'collection_healthy', + '3': 8, + '4': 1, + '5': 8, + '10': 'collectionHealthy' + }, + {'1': 'unbound_sockets', '3': 9, '4': 1, '5': 4, '10': 'unboundSockets'}, + ], + '7': {}, +}; + +/// Descriptor for `HostEvidence`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List hostEvidenceDescriptor = $convert.base64Decode( + 'CgxIb3N0RXZpZGVuY2USRAoIYWdlbnRfaWQYASABKAlCKbpIJnIkMiJeW2EtekEtWjAtOV1bYS' + '16QS1aMC05Xy4tXXswLDEyN30kUgdhZ2VudElkEhgKB3NvY2tldHMYAiABKARSB3NvY2tldHMS' + 'HwoLYnl0ZXNfYWNrZWQYAyABKARSCmJ5dGVzQWNrZWQSMQoLZ29vZHB1dF9icHMYBCABKAFCEL' + 'pIDRILQAEpAAAAAAAAAABSCmdvb2RwdXRCcHMSQwoUcmV0cmFuc21pc3Npb25fcmF0aW8YBSAB' + 'KAFCELpIDRILQAEpAAAAAAAAAABSE3JldHJhbnNtaXNzaW9uUmF0aW8SLgoKcnR0X3A5NV9tcx' + 'gGIAEoAUIQukgNEgtAASkAAAAAAAAAAFIIcnR0UDk1TXMSJwoPZXhwb3NlZF9zb2NrZXRzGAcg' + 'ASgEUg5leHBvc2VkU29ja2V0cxItChJjb2xsZWN0aW9uX2hlYWx0aHkYCCABKAhSEWNvbGxlY3' + 'Rpb25IZWFsdGh5EicKD3VuYm91bmRfc29ja2V0cxgJIAEoBFIOdW5ib3VuZFNvY2tldHM6eLpI' + 'dRpzCiRob3N0X2V2aWRlbmNlLmV4cG9zZWRfd2l0aGluX3NvY2tldHMSJWV4cG9zZWRfc29ja2' + 'V0cyBjYW5ub3QgZXhjZWVkIHNvY2tldHMaJHRoaXMuZXhwb3NlZF9zb2NrZXRzIDw9IHRoaXMu' + 'c29ja2V0cw=='); + +@$core.Deprecated('Use evidenceDescriptor instead') +const Evidence$json = { + '1': 'Evidence', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'id'}, + { + '1': 'analyzed_at', + '3': 2, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '8': {}, + '10': 'analyzedAt' + }, + { + '1': 'window_start', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '8': {}, + '10': 'windowStart' + }, + { + '1': 'window_end', + '3': 4, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '8': {}, + '10': 'windowEnd' + }, + { + '1': 'query_version', + '3': 5, + '4': 1, + '5': 9, + '8': {}, + '10': 'queryVersion' + }, + { + '1': 'enrichment_version', + '3': 6, + '4': 1, + '5': 9, + '8': {}, + '10': 'enrichmentVersion' + }, + { + '1': 'hosts', + '3': 7, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.HostEvidence', + '8': {}, + '10': 'hosts' + }, + { + '1': 'artifact_sha256', + '3': 8, + '4': 1, + '5': 9, + '8': {}, + '10': 'artifactSha256' + }, + ], + '7': {}, +}; + +/// Descriptor for `Evidence`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evidenceDescriptor = $convert.base64Decode( + 'CghFdmlkZW5jZRI5CgJpZBgBIAEoCUIpukgmciQyIl5bYS16QS1aMC05XVthLXpBLVowLTlfLi' + '1dezAsMTI3fSRSAmlkEkMKC2FuYWx5emVkX2F0GAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp' + 'bWVzdGFtcEIGukgDyAEBUgphbmFseXplZEF0EkUKDHdpbmRvd19zdGFydBgDIAEoCzIaLmdvb2' + 'dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCBrpIA8gBAVILd2luZG93U3RhcnQSQQoKd2luZG93X2Vu' + 'ZBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCBrpIA8gBAVIJd2luZG93RW5kEi' + '8KDXF1ZXJ5X3ZlcnNpb24YBSABKAlCCrpIB3IFEAEYgAJSDHF1ZXJ5VmVyc2lvbhI3ChJlbnJp' + 'Y2htZW50X3ZlcnNpb24YBiABKAlCCLpIBXIDGIACUhFlbnJpY2htZW50VmVyc2lvbhJCCgVob3' + 'N0cxgHIAMoCzIfLnh0Y3BfdHJlYXRtZW50LnYxLkhvc3RFdmlkZW5jZUILukgIkgEFCAEQkE5S' + 'BWhvc3RzEj4KD2FydGlmYWN0X3NoYTI1NhgIIAEoCUIVukgSchAyDl5bMC05YS1mXXs2NH0kUg' + '5hcnRpZmFjdFNoYTI1Njq3AbpIswEasAEKEWV2aWRlbmNlLmludGVydmFsEk93aW5kb3dfZW5k' + 'IG11c3QgZm9sbG93IHdpbmRvd19zdGFydCBhbmQgYW5hbHl6ZWRfYXQgbXVzdCBub3QgcHJlY2' + 'VkZSB3aW5kb3dfZW5kGkp0aGlzLndpbmRvd19lbmQgPiB0aGlzLndpbmRvd19zdGFydCAmJiB0' + 'aGlzLmFuYWx5emVkX2F0ID49IHRoaXMud2luZG93X2VuZA=='); + +@$core.Deprecated('Use experimentPolicyDescriptor instead') +const ExperimentPolicy$json = { + '1': 'ExperimentPolicy', + '2': [ + { + '1': 'minimum_observation', + '3': 1, + '4': 1, + '5': 11, + '6': '.google.protobuf.Duration', + '8': {}, + '10': 'minimumObservation' + }, + { + '1': 'maximum_phase', + '3': 2, + '4': 1, + '5': 11, + '6': '.google.protobuf.Duration', + '8': {}, + '10': 'maximumPhase' + }, + { + '1': 'minimum_sockets_per_host', + '3': 3, + '4': 1, + '5': 4, + '8': {}, + '10': 'minimumSocketsPerHost' + }, + { + '1': 'minimum_bytes_per_host', + '3': 4, + '4': 1, + '5': 4, + '8': {}, + '10': 'minimumBytesPerHost' + }, + { + '1': 'minimum_treated_hosts', + '3': 5, + '4': 1, + '5': 13, + '8': {}, + '10': 'minimumTreatedHosts' + }, + { + '1': 'minimum_improvement', + '3': 6, + '4': 1, + '5': 1, + '8': {}, + '10': 'minimumImprovement' + }, + { + '1': 'maximum_retransmission_increase', + '3': 7, + '4': 1, + '5': 1, + '8': {}, + '10': 'maximumRetransmissionIncrease' + }, + { + '1': 'maximum_rtt_increase', + '3': 8, + '4': 1, + '5': 1, + '8': {}, + '10': 'maximumRttIncrease' + }, + { + '1': 'maximum_evidence_age', + '3': 9, + '4': 1, + '5': 11, + '6': '.google.protobuf.Duration', + '8': {}, + '10': 'maximumEvidenceAge' + }, + ], + '7': {}, +}; + +/// Descriptor for `ExperimentPolicy`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List experimentPolicyDescriptor = $convert.base64Decode( + 'ChBFeHBlcmltZW50UG9saWN5El0KE21pbmltdW1fb2JzZXJ2YXRpb24YASABKAsyGS5nb29nbG' + 'UucHJvdG9idWYuRHVyYXRpb25CEbpIDsgBAaoBCCIECID1JCoAUhJtaW5pbXVtT2JzZXJ2YXRp' + 'b24SUQoNbWF4aW11bV9waGFzZRgCIAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkIRuk' + 'gOyAEBqgEIIgQIgPUkKgBSDG1heGltdW1QaGFzZRJAChhtaW5pbXVtX3NvY2tldHNfcGVyX2hv' + 'c3QYAyABKARCB7pIBDICIABSFW1pbmltdW1Tb2NrZXRzUGVySG9zdBI8ChZtaW5pbXVtX2J5dG' + 'VzX3Blcl9ob3N0GAQgASgEQge6SAQyAiAAUhNtaW5pbXVtQnl0ZXNQZXJIb3N0Ej4KFW1pbmlt' + 'dW1fdHJlYXRlZF9ob3N0cxgFIAEoDUIKukgHKgUYkE4oAlITbWluaW11bVRyZWF0ZWRIb3N0cx' + 'JKChNtaW5pbXVtX2ltcHJvdmVtZW50GAYgASgBQhm6SBYSFEABGQAAAAAAAPA/KQAAAAAAAAAA' + 'UhJtaW5pbXVtSW1wcm92ZW1lbnQSYQofbWF4aW11bV9yZXRyYW5zbWlzc2lvbl9pbmNyZWFzZR' + 'gHIAEoAUIZukgWEhRAARkAAAAAAADwPykAAAAAAAAAAFIdbWF4aW11bVJldHJhbnNtaXNzaW9u' + 'SW5jcmVhc2USSwoUbWF4aW11bV9ydHRfaW5jcmVhc2UYCCABKAFCGbpIFhIUQAEZAAAAAAAA8D' + '8pAAAAAAAAAABSEm1heGltdW1SdHRJbmNyZWFzZRJeChRtYXhpbXVtX2V2aWRlbmNlX2FnZRgJ' + 'IAEoCzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbkIRukgOyAEBqgEIIgQIgPUkKgBSEm1heG' + 'ltdW1FdmlkZW5jZUFnZTqJAbpIhQEaggEKH3BvbGljeS5vYnNlcnZhdGlvbl93aXRoaW5fcGhh' + 'c2USL21pbmltdW1fb2JzZXJ2YXRpb24gY2Fubm90IGV4Y2VlZCBtYXhpbXVtX3BoYXNlGi50aG' + 'lzLm1pbmltdW1fb2JzZXJ2YXRpb24gPD0gdGhpcy5tYXhpbXVtX3BoYXNl'); + +@$core.Deprecated('Use phaseDescriptor instead') +const Phase$json = { + '1': 'Phase', + '2': [ + { + '1': 'target_hosts', + '3': 1, + '4': 1, + '5': 13, + '8': {}, + '10': 'targetHosts' + }, + { + '1': 'issued_at', + '3': 2, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'issuedAt' + }, + { + '1': 'observation_started_at', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'observationStartedAt' + }, + { + '1': 'evaluated_at', + '3': 4, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'evaluatedAt' + }, + { + '1': 'evidence', + '3': 5, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Evidence', + '10': 'evidence' + }, + { + '1': 'outcome', + '3': 6, + '4': 1, + '5': 14, + '6': '.xtcp_treatment.v1.Outcome', + '8': {}, + '10': 'outcome' + }, + {'1': 'reviewer', '3': 7, '4': 1, '5': 9, '8': {}, '10': 'reviewer'}, + {'1': 'reason', '3': 8, '4': 1, '5': 9, '8': {}, '10': 'reason'}, + ], +}; + +/// Descriptor for `Phase`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List phaseDescriptor = $convert.base64Decode( + 'CgVQaGFzZRItCgx0YXJnZXRfaG9zdHMYASABKA1CCrpIByoFGJBOKAFSC3RhcmdldEhvc3RzEj' + 'cKCWlzc3VlZF9hdBgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBSCGlzc3VlZEF0' + 'ElAKFm9ic2VydmF0aW9uX3N0YXJ0ZWRfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZX' + 'N0YW1wUhRvYnNlcnZhdGlvblN0YXJ0ZWRBdBI9CgxldmFsdWF0ZWRfYXQYBCABKAsyGi5nb29n' + 'bGUucHJvdG9idWYuVGltZXN0YW1wUgtldmFsdWF0ZWRBdBI3CghldmlkZW5jZRgFIAEoCzIbLn' + 'h0Y3BfdHJlYXRtZW50LnYxLkV2aWRlbmNlUghldmlkZW5jZRI+CgdvdXRjb21lGAYgASgOMhou' + 'eHRjcF90cmVhdG1lbnQudjEuT3V0Y29tZUIIukgFggECEAFSB291dGNvbWUSJAoIcmV2aWV3ZX' + 'IYByABKAlCCLpIBXIDGIABUghyZXZpZXdlchIgCgZyZWFzb24YCCABKAlCCLpIBXIDGIAgUgZy' + 'ZWFzb24='); + +@$core.Deprecated('Use experimentDescriptor instead') +const Experiment$json = { + '1': 'Experiment', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 9, '8': {}, '10': 'id'}, + {'1': 'location', '3': 2, '4': 1, '5': 9, '8': {}, '10': 'location'}, + {'1': 'hypothesis', '3': 3, '4': 1, '5': 9, '8': {}, '10': 'hypothesis'}, + { + '1': 'treatment', + '3': 4, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Treatment', + '8': {}, + '10': 'treatment' + }, + { + '1': 'policy', + '3': 5, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.ExperimentPolicy', + '8': {}, + '10': 'policy' + }, + { + '1': 'baseline', + '3': 6, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Evidence', + '8': {}, + '10': 'baseline' + }, + {'1': 'cohort_order', '3': 7, '4': 3, '5': 9, '8': {}, '10': 'cohortOrder'}, + { + '1': 'phases', + '3': 8, + '4': 3, + '5': 11, + '6': '.xtcp_treatment.v1.Phase', + '8': {}, + '10': 'phases' + }, + { + '1': 'status', + '3': 9, + '4': 1, + '5': 14, + '6': '.xtcp_treatment.v1.ExperimentStatus', + '8': {}, + '10': 'status' + }, + {'1': 'revision', '3': 10, '4': 1, '5': 4, '10': 'revision'}, + { + '1': 'proposed_at', + '3': 11, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'proposedAt' + }, + { + '1': 'latest_evidence', + '3': 12, + '4': 1, + '5': 11, + '6': '.xtcp_treatment.v1.Evidence', + '10': 'latestEvidence' + }, + { + '1': 'latest_outcome', + '3': 13, + '4': 1, + '5': 14, + '6': '.xtcp_treatment.v1.Outcome', + '8': {}, + '10': 'latestOutcome' + }, + { + '1': 'updated_at', + '3': 14, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'updatedAt' + }, + ], +}; + +/// Descriptor for `Experiment`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List experimentDescriptor = $convert.base64Decode( + 'CgpFeHBlcmltZW50EjkKAmlkGAEgASgJQim6SCZyJDIiXlthLXpBLVowLTldW2EtekEtWjAtOV' + '8uLV17MCwxMjd9JFICaWQSRQoIbG9jYXRpb24YAiABKAlCKbpIJnIkMiJeW2EtekEtWjAtOV1b' + 'YS16QS1aMC05Xy4tXXswLDEyN30kUghsb2NhdGlvbhIqCgpoeXBvdGhlc2lzGAMgASgJQgq6SA' + 'dyBRABGIBAUgpoeXBvdGhlc2lzEkIKCXRyZWF0bWVudBgEIAEoCzIcLnh0Y3BfdHJlYXRtZW50' + 'LnYxLlRyZWF0bWVudEIGukgDyAEBUgl0cmVhdG1lbnQSQwoGcG9saWN5GAUgASgLMiMueHRjcF' + '90cmVhdG1lbnQudjEuRXhwZXJpbWVudFBvbGljeUIGukgDyAEBUgZwb2xpY3kSPwoIYmFzZWxp' + 'bmUYBiABKAsyGy54dGNwX3RyZWF0bWVudC52MS5FdmlkZW5jZUIGukgDyAEBUghiYXNlbGluZR' + 'JYCgxjb2hvcnRfb3JkZXIYByADKAlCNbpIMpIBLwgDEJBOGAEiJnIkMiJeW2EtekEtWjAtOV1b' + 'YS16QS1aMC05Xy4tXXswLDEyN30kUgtjb2hvcnRPcmRlchI6CgZwaGFzZXMYCCADKAsyGC54dG' + 'NwX3RyZWF0bWVudC52MS5QaGFzZUIIukgFkgECEEBSBnBoYXNlcxJFCgZzdGF0dXMYCSABKA4y' + 'Iy54dGNwX3RyZWF0bWVudC52MS5FeHBlcmltZW50U3RhdHVzQgi6SAWCAQIQAVIGc3RhdHVzEh' + 'oKCHJldmlzaW9uGAogASgEUghyZXZpc2lvbhI7Cgtwcm9wb3NlZF9hdBgLIAEoCzIaLmdvb2ds' + 'ZS5wcm90b2J1Zi5UaW1lc3RhbXBSCnByb3Bvc2VkQXQSRAoPbGF0ZXN0X2V2aWRlbmNlGAwgAS' + 'gLMhsueHRjcF90cmVhdG1lbnQudjEuRXZpZGVuY2VSDmxhdGVzdEV2aWRlbmNlEksKDmxhdGVz' + 'dF9vdXRjb21lGA0gASgOMhoueHRjcF90cmVhdG1lbnQudjEuT3V0Y29tZUIIukgFggECEAFSDW' + 'xhdGVzdE91dGNvbWUSOQoKdXBkYXRlZF9hdBgOIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l' + 'c3RhbXBSCXVwZGF0ZWRBdA=='); diff --git a/gen/dart/xtcp_treatment_journal/v1/journal.pb.dart b/gen/dart/xtcp_treatment_journal/v1/journal.pb.dart new file mode 100644 index 000000000..f1c732af0 --- /dev/null +++ b/gen/dart/xtcp_treatment_journal/v1/journal.pb.dart @@ -0,0 +1,871 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment_journal/v1/journal.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart' + as $0; + +import 'journal.pbenum.dart'; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'journal.pbenum.dart'; + +/// TCPSettings mirrors xtcp_treatment.v1.TCPSettings; presence is meaningful. +class TCPSettings extends $pb.GeneratedMessage { + factory TCPSettings({ + $core.String? congestionControl, + $core.bool? congestionLock, + $core.int? rtoMinMs, + $core.int? initialCongestionWindow, + $core.int? initialReceiveWindow, + $core.bool? quickAck, + $core.bool? ecn, + }) { + final result = TCPSettings._(); + if (congestionControl != null) result.congestionControl = congestionControl; + if (congestionLock != null) result.congestionLock = congestionLock; + if (rtoMinMs != null) result.rtoMinMs = rtoMinMs; + if (initialCongestionWindow != null) + result.initialCongestionWindow = initialCongestionWindow; + if (initialReceiveWindow != null) + result.initialReceiveWindow = initialReceiveWindow; + if (quickAck != null) result.quickAck = quickAck; + if (ecn != null) result.ecn = ecn; + return result; + } + + TCPSettings._(); + + factory TCPSettings.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + TCPSettings()..mergeFromBuffer(data, registry); + factory TCPSettings.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + TCPSettings()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'TCPSettings', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'xtcp_treatment_journal.v1'), + createEmptyInstance: TCPSettings.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'congestionControl') + ..aOB(2, _omitFieldNames ? '' : 'congestionLock') + ..aI(3, _omitFieldNames ? '' : 'rtoMinMs', fieldType: $pb.PbFieldType.OU3) + ..aI(4, _omitFieldNames ? '' : 'initialCongestionWindow', + fieldType: $pb.PbFieldType.OU3) + ..aI(5, _omitFieldNames ? '' : 'initialReceiveWindow', + fieldType: $pb.PbFieldType.OU3) + ..aOB(6, _omitFieldNames ? '' : 'quickAck') + ..aOB(7, _omitFieldNames ? '' : 'ecn') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TCPSettings clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TCPSettings copyWith(void Function(TCPSettings) updates) => + super.copyWith((message) => updates(message as TCPSettings)) + as TCPSettings; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use TCPSettings() / TCPSettings.new instead') + static TCPSettings create() => TCPSettings._(); + static $pb.GeneratedMessage $_createMessage() => TCPSettings._(); + @$core.override + TCPSettings createEmptyInstance() => TCPSettings._(); + @$core.pragma('dart2js:noInline') + static TCPSettings getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor( + TCPSettings.$_createMessage); + static TCPSettings? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get congestionControl => $_getSZ(0); + @$pb.TagNumber(1) + set congestionControl($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasCongestionControl() => $_has(0); + @$pb.TagNumber(1) + void clearCongestionControl() => $_clearField(1); + + @$pb.TagNumber(2) + $core.bool get congestionLock => $_getBF(1); + @$pb.TagNumber(2) + set congestionLock($core.bool value) => $_setBool(1, value); + @$pb.TagNumber(2) + $core.bool hasCongestionLock() => $_has(1); + @$pb.TagNumber(2) + void clearCongestionLock() => $_clearField(2); + + @$pb.TagNumber(3) + $core.int get rtoMinMs => $_getIZ(2); + @$pb.TagNumber(3) + set rtoMinMs($core.int value) => $_setUnsignedInt32(2, value); + @$pb.TagNumber(3) + $core.bool hasRtoMinMs() => $_has(2); + @$pb.TagNumber(3) + void clearRtoMinMs() => $_clearField(3); + + @$pb.TagNumber(4) + $core.int get initialCongestionWindow => $_getIZ(3); + @$pb.TagNumber(4) + set initialCongestionWindow($core.int value) => $_setUnsignedInt32(3, value); + @$pb.TagNumber(4) + $core.bool hasInitialCongestionWindow() => $_has(3); + @$pb.TagNumber(4) + void clearInitialCongestionWindow() => $_clearField(4); + + @$pb.TagNumber(5) + $core.int get initialReceiveWindow => $_getIZ(4); + @$pb.TagNumber(5) + set initialReceiveWindow($core.int value) => $_setUnsignedInt32(4, value); + @$pb.TagNumber(5) + $core.bool hasInitialReceiveWindow() => $_has(4); + @$pb.TagNumber(5) + void clearInitialReceiveWindow() => $_clearField(5); + + @$pb.TagNumber(6) + $core.bool get quickAck => $_getBF(5); + @$pb.TagNumber(6) + set quickAck($core.bool value) => $_setBool(5, value); + @$pb.TagNumber(6) + $core.bool hasQuickAck() => $_has(5); + @$pb.TagNumber(6) + void clearQuickAck() => $_clearField(6); + + @$pb.TagNumber(7) + $core.bool get ecn => $_getBF(6); + @$pb.TagNumber(7) + set ecn($core.bool value) => $_setBool(6, value); + @$pb.TagNumber(7) + $core.bool hasEcn() => $_has(6); + @$pb.TagNumber(7) + void clearEcn() => $_clearField(7); +} + +class Treatment extends $pb.GeneratedMessage { + factory Treatment({ + $core.String? id, + $fixnum.Int64? revision, + $core.String? destination, + TCPSettings? settings, + $core.bool? ecnFabricVerified, + }) { + final result = Treatment._(); + if (id != null) result.id = id; + if (revision != null) result.revision = revision; + if (destination != null) result.destination = destination; + if (settings != null) result.settings = settings; + if (ecnFabricVerified != null) result.ecnFabricVerified = ecnFabricVerified; + return result; + } + + Treatment._(); + + factory Treatment.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Treatment()..mergeFromBuffer(data, registry); + factory Treatment.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Treatment()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Treatment', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'xtcp_treatment_journal.v1'), + createEmptyInstance: Treatment.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'id') + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'revision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOS(3, _omitFieldNames ? '' : 'destination') + ..aOM(4, _omitFieldNames ? '' : 'settings', + subBuilder: TCPSettings.$_createMessage) + ..aOB(5, _omitFieldNames ? '' : 'ecnFabricVerified') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Treatment clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Treatment copyWith(void Function(Treatment) updates) => + super.copyWith((message) => updates(message as Treatment)) as Treatment; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Treatment() / Treatment.new instead') + static Treatment create() => Treatment._(); + static $pb.GeneratedMessage $_createMessage() => Treatment._(); + @$core.override + Treatment createEmptyInstance() => Treatment._(); + @$core.pragma('dart2js:noInline') + static Treatment getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Treatment.$_createMessage); + static Treatment? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get id => $_getSZ(0); + @$pb.TagNumber(1) + set id($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get revision => $_getI64(1); + @$pb.TagNumber(2) + set revision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasRevision() => $_has(1); + @$pb.TagNumber(2) + void clearRevision() => $_clearField(2); + + /// Canonical /32 or /128 host prefix. + @$pb.TagNumber(3) + $core.String get destination => $_getSZ(2); + @$pb.TagNumber(3) + set destination($core.String value) => $_setString(2, value); + @$pb.TagNumber(3) + $core.bool hasDestination() => $_has(2); + @$pb.TagNumber(3) + void clearDestination() => $_clearField(3); + + @$pb.TagNumber(4) + TCPSettings get settings => $_getN(3); + @$pb.TagNumber(4) + set settings(TCPSettings value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasSettings() => $_has(3); + @$pb.TagNumber(4) + void clearSettings() => $_clearField(4); + @$pb.TagNumber(4) + TCPSettings ensureSettings() => $_ensure(3); + + @$pb.TagNumber(5) + $core.bool get ecnFabricVerified => $_getBF(4); + @$pb.TagNumber(5) + set ecnFabricVerified($core.bool value) => $_setBool(4, value); + @$pb.TagNumber(5) + $core.bool hasEcnFabricVerified() => $_has(4); + @$pb.TagNumber(5) + void clearEcnFabricVerified() => $_clearField(5); +} + +class Assignment extends $pb.GeneratedMessage { + factory Assignment({ + $core.String? experimentId, + Treatment? treatment, + AssignmentMode? mode, + $0.Timestamp? leaseExpiresAt, + Treatment? predecessor, + $fixnum.Int64? generation, + }) { + final result = Assignment._(); + if (experimentId != null) result.experimentId = experimentId; + if (treatment != null) result.treatment = treatment; + if (mode != null) result.mode = mode; + if (leaseExpiresAt != null) result.leaseExpiresAt = leaseExpiresAt; + if (predecessor != null) result.predecessor = predecessor; + if (generation != null) result.generation = generation; + return result; + } + + Assignment._(); + + factory Assignment.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Assignment()..mergeFromBuffer(data, registry); + factory Assignment.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Assignment()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Assignment', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'xtcp_treatment_journal.v1'), + createEmptyInstance: Assignment.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'experimentId') + ..aOM(2, _omitFieldNames ? '' : 'treatment', + subBuilder: Treatment.$_createMessage) + ..aE(3, _omitFieldNames ? '' : 'mode', + enumValues: AssignmentMode.values) + ..aOM<$0.Timestamp>(4, _omitFieldNames ? '' : 'leaseExpiresAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM(5, _omitFieldNames ? '' : 'predecessor', + subBuilder: Treatment.$_createMessage) + ..a<$fixnum.Int64>( + 6, _omitFieldNames ? '' : 'generation', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Assignment clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Assignment copyWith(void Function(Assignment) updates) => + super.copyWith((message) => updates(message as Assignment)) as Assignment; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Assignment() / Assignment.new instead') + static Assignment create() => Assignment._(); + static $pb.GeneratedMessage $_createMessage() => Assignment._(); + @$core.override + Assignment createEmptyInstance() => Assignment._(); + @$core.pragma('dart2js:noInline') + static Assignment getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Assignment.$_createMessage); + static Assignment? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get experimentId => $_getSZ(0); + @$pb.TagNumber(1) + set experimentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasExperimentId() => $_has(0); + @$pb.TagNumber(1) + void clearExperimentId() => $_clearField(1); + + @$pb.TagNumber(2) + Treatment get treatment => $_getN(1); + @$pb.TagNumber(2) + set treatment(Treatment value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasTreatment() => $_has(1); + @$pb.TagNumber(2) + void clearTreatment() => $_clearField(2); + @$pb.TagNumber(2) + Treatment ensureTreatment() => $_ensure(1); + + @$pb.TagNumber(3) + AssignmentMode get mode => $_getN(2); + @$pb.TagNumber(3) + set mode(AssignmentMode value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasMode() => $_has(2); + @$pb.TagNumber(3) + void clearMode() => $_clearField(3); + + @$pb.TagNumber(4) + $0.Timestamp get leaseExpiresAt => $_getN(3); + @$pb.TagNumber(4) + set leaseExpiresAt($0.Timestamp value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasLeaseExpiresAt() => $_has(3); + @$pb.TagNumber(4) + void clearLeaseExpiresAt() => $_clearField(4); + @$pb.TagNumber(4) + $0.Timestamp ensureLeaseExpiresAt() => $_ensure(3); + + @$pb.TagNumber(5) + Treatment get predecessor => $_getN(4); + @$pb.TagNumber(5) + set predecessor(Treatment value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasPredecessor() => $_has(4); + @$pb.TagNumber(5) + void clearPredecessor() => $_clearField(5); + @$pb.TagNumber(5) + Treatment ensurePredecessor() => $_ensure(4); + + @$pb.TagNumber(6) + $fixnum.Int64 get generation => $_getI64(5); + @$pb.TagNumber(6) + set generation($fixnum.Int64 value) => $_setInt64(5, value); + @$pb.TagNumber(6) + $core.bool hasGeneration() => $_has(5); + @$pb.TagNumber(6) + void clearGeneration() => $_clearField(6); +} + +/// Desired is the controller's last accepted snapshot for this agent. The +/// agent identity lives on the Journal header. +class Desired extends $pb.GeneratedMessage { + factory Desired({ + $fixnum.Int64? revision, + $core.bool? suspended, + $0.Timestamp? issuedAt, + $core.Iterable? assignments, + }) { + final result = Desired._(); + if (revision != null) result.revision = revision; + if (suspended != null) result.suspended = suspended; + if (issuedAt != null) result.issuedAt = issuedAt; + if (assignments != null) result.assignments.addAll(assignments); + return result; + } + + Desired._(); + + factory Desired.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Desired()..mergeFromBuffer(data, registry); + factory Desired.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Desired()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Desired', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'xtcp_treatment_journal.v1'), + createEmptyInstance: Desired.$_createMessage) + ..a<$fixnum.Int64>( + 1, _omitFieldNames ? '' : 'revision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOB(2, _omitFieldNames ? '' : 'suspended') + ..aOM<$0.Timestamp>(3, _omitFieldNames ? '' : 'issuedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..pPM(4, _omitFieldNames ? '' : 'assignments', + subBuilder: Assignment.$_createMessage) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Desired clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Desired copyWith(void Function(Desired) updates) => + super.copyWith((message) => updates(message as Desired)) as Desired; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Desired() / Desired.new instead') + static Desired create() => Desired._(); + static $pb.GeneratedMessage $_createMessage() => Desired._(); + @$core.override + Desired createEmptyInstance() => Desired._(); + @$core.pragma('dart2js:noInline') + static Desired getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Desired.$_createMessage); + static Desired? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get revision => $_getI64(0); + @$pb.TagNumber(1) + set revision($fixnum.Int64 value) => $_setInt64(0, value); + @$pb.TagNumber(1) + $core.bool hasRevision() => $_has(0); + @$pb.TagNumber(1) + void clearRevision() => $_clearField(1); + + @$pb.TagNumber(2) + $core.bool get suspended => $_getBF(1); + @$pb.TagNumber(2) + set suspended($core.bool value) => $_setBool(1, value); + @$pb.TagNumber(2) + $core.bool hasSuspended() => $_has(1); + @$pb.TagNumber(2) + void clearSuspended() => $_clearField(2); + + @$pb.TagNumber(3) + $0.Timestamp get issuedAt => $_getN(2); + @$pb.TagNumber(3) + set issuedAt($0.Timestamp value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasIssuedAt() => $_has(2); + @$pb.TagNumber(3) + void clearIssuedAt() => $_clearField(3); + @$pb.TagNumber(3) + $0.Timestamp ensureIssuedAt() => $_ensure(2); + + @$pb.TagNumber(4) + $pb.PbList get assignments => $_getList(3); +} + +/// Record is the agent's account of one assignment plus the kernel-local +/// facts (installed route bytes, installing boot) that never leave the host. +class Record extends $pb.GeneratedMessage { + factory Record({ + Assignment? assignment, + $fixnum.Int64? desiredRevision, + ApplyStatus? status, + $0.Timestamp? receivedAt, + $0.Timestamp? attemptedAt, + $0.Timestamp? appliedAt, + $0.Timestamp? verifiedAt, + $0.Timestamp? removedAt, + $core.String? error, + $core.List<$core.int>? installedRoute, + $core.String? installedBootId, + $core.bool? expiredLatched, + }) { + final result = Record._(); + if (assignment != null) result.assignment = assignment; + if (desiredRevision != null) result.desiredRevision = desiredRevision; + if (status != null) result.status = status; + if (receivedAt != null) result.receivedAt = receivedAt; + if (attemptedAt != null) result.attemptedAt = attemptedAt; + if (appliedAt != null) result.appliedAt = appliedAt; + if (verifiedAt != null) result.verifiedAt = verifiedAt; + if (removedAt != null) result.removedAt = removedAt; + if (error != null) result.error = error; + if (installedRoute != null) result.installedRoute = installedRoute; + if (installedBootId != null) result.installedBootId = installedBootId; + if (expiredLatched != null) result.expiredLatched = expiredLatched; + return result; + } + + Record._(); + + factory Record.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Record()..mergeFromBuffer(data, registry); + factory Record.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Record()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Record', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'xtcp_treatment_journal.v1'), + createEmptyInstance: Record.$_createMessage) + ..aOM(1, _omitFieldNames ? '' : 'assignment', + subBuilder: Assignment.$_createMessage) + ..a<$fixnum.Int64>( + 2, _omitFieldNames ? '' : 'desiredRevision', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aE(3, _omitFieldNames ? '' : 'status', + enumValues: ApplyStatus.values) + ..aOM<$0.Timestamp>(4, _omitFieldNames ? '' : 'receivedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(5, _omitFieldNames ? '' : 'attemptedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(6, _omitFieldNames ? '' : 'appliedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(7, _omitFieldNames ? '' : 'verifiedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOM<$0.Timestamp>(8, _omitFieldNames ? '' : 'removedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOS(9, _omitFieldNames ? '' : 'error') + ..a<$core.List<$core.int>>( + 10, _omitFieldNames ? '' : 'installedRoute', $pb.PbFieldType.OY) + ..aOS(11, _omitFieldNames ? '' : 'installedBootId') + ..aOB(12, _omitFieldNames ? '' : 'expiredLatched') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Record clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Record copyWith(void Function(Record) updates) => + super.copyWith((message) => updates(message as Record)) as Record; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Record() / Record.new instead') + static Record create() => Record._(); + static $pb.GeneratedMessage $_createMessage() => Record._(); + @$core.override + Record createEmptyInstance() => Record._(); + @$core.pragma('dart2js:noInline') + static Record getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Record.$_createMessage); + static Record? _defaultInstance; + + @$pb.TagNumber(1) + Assignment get assignment => $_getN(0); + @$pb.TagNumber(1) + set assignment(Assignment value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasAssignment() => $_has(0); + @$pb.TagNumber(1) + void clearAssignment() => $_clearField(1); + @$pb.TagNumber(1) + Assignment ensureAssignment() => $_ensure(0); + + @$pb.TagNumber(2) + $fixnum.Int64 get desiredRevision => $_getI64(1); + @$pb.TagNumber(2) + set desiredRevision($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasDesiredRevision() => $_has(1); + @$pb.TagNumber(2) + void clearDesiredRevision() => $_clearField(2); + + @$pb.TagNumber(3) + ApplyStatus get status => $_getN(2); + @$pb.TagNumber(3) + set status(ApplyStatus value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasStatus() => $_has(2); + @$pb.TagNumber(3) + void clearStatus() => $_clearField(3); + + @$pb.TagNumber(4) + $0.Timestamp get receivedAt => $_getN(3); + @$pb.TagNumber(4) + set receivedAt($0.Timestamp value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasReceivedAt() => $_has(3); + @$pb.TagNumber(4) + void clearReceivedAt() => $_clearField(4); + @$pb.TagNumber(4) + $0.Timestamp ensureReceivedAt() => $_ensure(3); + + @$pb.TagNumber(5) + $0.Timestamp get attemptedAt => $_getN(4); + @$pb.TagNumber(5) + set attemptedAt($0.Timestamp value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasAttemptedAt() => $_has(4); + @$pb.TagNumber(5) + void clearAttemptedAt() => $_clearField(5); + @$pb.TagNumber(5) + $0.Timestamp ensureAttemptedAt() => $_ensure(4); + + @$pb.TagNumber(6) + $0.Timestamp get appliedAt => $_getN(5); + @$pb.TagNumber(6) + set appliedAt($0.Timestamp value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasAppliedAt() => $_has(5); + @$pb.TagNumber(6) + void clearAppliedAt() => $_clearField(6); + @$pb.TagNumber(6) + $0.Timestamp ensureAppliedAt() => $_ensure(5); + + @$pb.TagNumber(7) + $0.Timestamp get verifiedAt => $_getN(6); + @$pb.TagNumber(7) + set verifiedAt($0.Timestamp value) => $_setField(7, value); + @$pb.TagNumber(7) + $core.bool hasVerifiedAt() => $_has(6); + @$pb.TagNumber(7) + void clearVerifiedAt() => $_clearField(7); + @$pb.TagNumber(7) + $0.Timestamp ensureVerifiedAt() => $_ensure(6); + + @$pb.TagNumber(8) + $0.Timestamp get removedAt => $_getN(7); + @$pb.TagNumber(8) + set removedAt($0.Timestamp value) => $_setField(8, value); + @$pb.TagNumber(8) + $core.bool hasRemovedAt() => $_has(7); + @$pb.TagNumber(8) + void clearRemovedAt() => $_clearField(8); + @$pb.TagNumber(8) + $0.Timestamp ensureRemovedAt() => $_ensure(7); + + @$pb.TagNumber(9) + $core.String get error => $_getSZ(8); + @$pb.TagNumber(9) + set error($core.String value) => $_setString(8, value); + @$pb.TagNumber(9) + $core.bool hasError() => $_has(8); + @$pb.TagNumber(9) + void clearError() => $_clearField(9); + + /// Locally planned canonical netlink route body, the only thing Remove will + /// ever be asked to withdraw. + @$pb.TagNumber(10) + $core.List<$core.int> get installedRoute => $_getN(9); + @$pb.TagNumber(10) + set installedRoute($core.List<$core.int> value) => $_setBytes(9, value); + @$pb.TagNumber(10) + $core.bool hasInstalledRoute() => $_has(9); + @$pb.TagNumber(10) + void clearInstalledRoute() => $_clearField(10); + + @$pb.TagNumber(11) + $core.String get installedBootId => $_getSZ(10); + @$pb.TagNumber(11) + set installedBootId($core.String value) => $_setString(10, value); + @$pb.TagNumber(11) + $core.bool hasInstalledBootId() => $_has(10); + @$pb.TagNumber(11) + void clearInstalledBootId() => $_clearField(11); + + @$pb.TagNumber(12) + $core.bool get expiredLatched => $_getBF(11); + @$pb.TagNumber(12) + set expiredLatched($core.bool value) => $_setBool(11, value); + @$pb.TagNumber(12) + $core.bool hasExpiredLatched() => $_has(11); + @$pb.TagNumber(12) + void clearExpiredLatched() => $_clearField(12); +} + +/// Journal is the atomic snapshot in /state.textproto. The header +/// identifies the writer so a journal can never be reconciled for another +/// agent and so a telemetry-only daemon can attribute records from it. +class Journal extends $pb.GeneratedMessage { + factory Journal({ + $core.String? agentId, + $core.String? location, + $core.String? bootId, + Desired? desired, + $core.bool? locallySuspended, + $core.String? suspensionReason, + $core.Iterable? records, + $0.Timestamp? updatedAt, + $core.String? collectionId, + }) { + final result = Journal._(); + if (agentId != null) result.agentId = agentId; + if (location != null) result.location = location; + if (bootId != null) result.bootId = bootId; + if (desired != null) result.desired = desired; + if (locallySuspended != null) result.locallySuspended = locallySuspended; + if (suspensionReason != null) result.suspensionReason = suspensionReason; + if (records != null) result.records.addAll(records); + if (updatedAt != null) result.updatedAt = updatedAt; + if (collectionId != null) result.collectionId = collectionId; + return result; + } + + Journal._(); + + factory Journal.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Journal()..mergeFromBuffer(data, registry); + factory Journal.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + Journal()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Journal', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'xtcp_treatment_journal.v1'), + createEmptyInstance: Journal.$_createMessage) + ..aOS(1, _omitFieldNames ? '' : 'agentId') + ..aOS(2, _omitFieldNames ? '' : 'location') + ..aOS(3, _omitFieldNames ? '' : 'bootId') + ..aOM(4, _omitFieldNames ? '' : 'desired', + subBuilder: Desired.$_createMessage) + ..aOB(5, _omitFieldNames ? '' : 'locallySuspended') + ..aOS(6, _omitFieldNames ? '' : 'suspensionReason') + ..pPM(7, _omitFieldNames ? '' : 'records', + subBuilder: Record.$_createMessage) + ..aOM<$0.Timestamp>(8, _omitFieldNames ? '' : 'updatedAt', + subBuilder: $0.Timestamp.$_createMessage) + ..aOS(9, _omitFieldNames ? '' : 'collectionId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Journal clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Journal copyWith(void Function(Journal) updates) => + super.copyWith((message) => updates(message as Journal)) as Journal; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + @$core.Deprecated('Use Journal() / Journal.new instead') + static Journal create() => Journal._(); + static $pb.GeneratedMessage $_createMessage() => Journal._(); + @$core.override + Journal createEmptyInstance() => Journal._(); + @$core.pragma('dart2js:noInline') + static Journal getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(Journal.$_createMessage); + static Journal? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get agentId => $_getSZ(0); + @$pb.TagNumber(1) + set agentId($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasAgentId() => $_has(0); + @$pb.TagNumber(1) + void clearAgentId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get location => $_getSZ(1); + @$pb.TagNumber(2) + set location($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasLocation() => $_has(1); + @$pb.TagNumber(2) + void clearLocation() => $_clearField(2); + + /// Boot that last wrote the journal; per-record installed_boot_id says + /// which boot installed each route. + @$pb.TagNumber(3) + $core.String get bootId => $_getSZ(2); + @$pb.TagNumber(3) + set bootId($core.String value) => $_setString(2, value); + @$pb.TagNumber(3) + $core.bool hasBootId() => $_has(2); + @$pb.TagNumber(3) + void clearBootId() => $_clearField(3); + + @$pb.TagNumber(4) + Desired get desired => $_getN(3); + @$pb.TagNumber(4) + set desired(Desired value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasDesired() => $_has(3); + @$pb.TagNumber(4) + void clearDesired() => $_clearField(4); + @$pb.TagNumber(4) + Desired ensureDesired() => $_ensure(3); + + @$pb.TagNumber(5) + $core.bool get locallySuspended => $_getBF(4); + @$pb.TagNumber(5) + set locallySuspended($core.bool value) => $_setBool(4, value); + @$pb.TagNumber(5) + $core.bool hasLocallySuspended() => $_has(4); + @$pb.TagNumber(5) + void clearLocallySuspended() => $_clearField(5); + + @$pb.TagNumber(6) + $core.String get suspensionReason => $_getSZ(5); + @$pb.TagNumber(6) + set suspensionReason($core.String value) => $_setString(5, value); + @$pb.TagNumber(6) + $core.bool hasSuspensionReason() => $_has(5); + @$pb.TagNumber(6) + void clearSuspensionReason() => $_clearField(6); + + @$pb.TagNumber(7) + $pb.PbList get records => $_getList(6); + + @$pb.TagNumber(8) + $0.Timestamp get updatedAt => $_getN(7); + @$pb.TagNumber(8) + set updatedAt($0.Timestamp value) => $_setField(8, value); + @$pb.TagNumber(8) + $core.bool hasUpdatedAt() => $_has(7); + @$pb.TagNumber(8) + void clearUpdatedAt() => $_clearField(8); + @$pb.TagNumber(8) + $0.Timestamp ensureUpdatedAt() => $_ensure(7); + + /// Per-process nonce of the agent that owns the journal. The agent writes + /// it; the watchdog preserves it; a telemetry-only daemon stamps it into + /// records as collection_id. + @$pb.TagNumber(9) + $core.String get collectionId => $_getSZ(8); + @$pb.TagNumber(9) + set collectionId($core.String value) => $_setString(8, value); + @$pb.TagNumber(9) + $core.bool hasCollectionId() => $_has(8); + @$pb.TagNumber(9) + void clearCollectionId() => $_clearField(9); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/gen/dart/xtcp_treatment_journal/v1/journal.pbenum.dart b/gen/dart/xtcp_treatment_journal/v1/journal.pbenum.dart new file mode 100644 index 000000000..ec1794e14 --- /dev/null +++ b/gen/dart/xtcp_treatment_journal/v1/journal.pbenum.dart @@ -0,0 +1,77 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment_journal/v1/journal.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class AssignmentMode extends $pb.ProtobufEnum { + static const AssignmentMode ASSIGNMENT_MODE_UNSPECIFIED = + AssignmentMode._(0, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_UNSPECIFIED'); + static const AssignmentMode ASSIGNMENT_MODE_TRIAL = + AssignmentMode._(1, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_TRIAL'); + static const AssignmentMode ASSIGNMENT_MODE_STABLE = + AssignmentMode._(2, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_STABLE'); + static const AssignmentMode ASSIGNMENT_MODE_SUSPENDED = + AssignmentMode._(3, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_SUSPENDED'); + static const AssignmentMode ASSIGNMENT_MODE_RETIRED = + AssignmentMode._(4, _omitEnumNames ? '' : 'ASSIGNMENT_MODE_RETIRED'); + + static const $core.List values = [ + ASSIGNMENT_MODE_UNSPECIFIED, + ASSIGNMENT_MODE_TRIAL, + ASSIGNMENT_MODE_STABLE, + ASSIGNMENT_MODE_SUSPENDED, + ASSIGNMENT_MODE_RETIRED, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 4); + static AssignmentMode? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const AssignmentMode._(super.value, super.name); +} + +class ApplyStatus extends $pb.ProtobufEnum { + static const ApplyStatus APPLY_STATUS_UNSPECIFIED = + ApplyStatus._(0, _omitEnumNames ? '' : 'APPLY_STATUS_UNSPECIFIED'); + static const ApplyStatus APPLY_STATUS_PENDING = + ApplyStatus._(1, _omitEnumNames ? '' : 'APPLY_STATUS_PENDING'); + static const ApplyStatus APPLY_STATUS_VERIFIED = + ApplyStatus._(2, _omitEnumNames ? '' : 'APPLY_STATUS_VERIFIED'); + static const ApplyStatus APPLY_STATUS_REMOVED = + ApplyStatus._(3, _omitEnumNames ? '' : 'APPLY_STATUS_REMOVED'); + static const ApplyStatus APPLY_STATUS_EXPIRED = + ApplyStatus._(4, _omitEnumNames ? '' : 'APPLY_STATUS_EXPIRED'); + static const ApplyStatus APPLY_STATUS_FAILED = + ApplyStatus._(5, _omitEnumNames ? '' : 'APPLY_STATUS_FAILED'); + + static const $core.List values = [ + APPLY_STATUS_UNSPECIFIED, + APPLY_STATUS_PENDING, + APPLY_STATUS_VERIFIED, + APPLY_STATUS_REMOVED, + APPLY_STATUS_EXPIRED, + APPLY_STATUS_FAILED, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 5); + static ApplyStatus? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const ApplyStatus._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/gen/dart/xtcp_treatment_journal/v1/journal.pbjson.dart b/gen/dart/xtcp_treatment_journal/v1/journal.pbjson.dart new file mode 100644 index 000000000..a89954db8 --- /dev/null +++ b/gen/dart/xtcp_treatment_journal/v1/journal.pbjson.dart @@ -0,0 +1,391 @@ +// This is a generated file - do not edit. +// +// Generated from xtcp_treatment_journal/v1/journal.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use assignmentModeDescriptor instead') +const AssignmentMode$json = { + '1': 'AssignmentMode', + '2': [ + {'1': 'ASSIGNMENT_MODE_UNSPECIFIED', '2': 0}, + {'1': 'ASSIGNMENT_MODE_TRIAL', '2': 1}, + {'1': 'ASSIGNMENT_MODE_STABLE', '2': 2}, + {'1': 'ASSIGNMENT_MODE_SUSPENDED', '2': 3}, + {'1': 'ASSIGNMENT_MODE_RETIRED', '2': 4}, + ], +}; + +/// Descriptor for `AssignmentMode`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List assignmentModeDescriptor = $convert.base64Decode( + 'Cg5Bc3NpZ25tZW50TW9kZRIfChtBU1NJR05NRU5UX01PREVfVU5TUEVDSUZJRUQQABIZChVBU1' + 'NJR05NRU5UX01PREVfVFJJQUwQARIaChZBU1NJR05NRU5UX01PREVfU1RBQkxFEAISHQoZQVNT' + 'SUdOTUVOVF9NT0RFX1NVU1BFTkRFRBADEhsKF0FTU0lHTk1FTlRfTU9ERV9SRVRJUkVEEAQ='); + +@$core.Deprecated('Use applyStatusDescriptor instead') +const ApplyStatus$json = { + '1': 'ApplyStatus', + '2': [ + {'1': 'APPLY_STATUS_UNSPECIFIED', '2': 0}, + {'1': 'APPLY_STATUS_PENDING', '2': 1}, + {'1': 'APPLY_STATUS_VERIFIED', '2': 2}, + {'1': 'APPLY_STATUS_REMOVED', '2': 3}, + {'1': 'APPLY_STATUS_EXPIRED', '2': 4}, + {'1': 'APPLY_STATUS_FAILED', '2': 5}, + ], +}; + +/// Descriptor for `ApplyStatus`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List applyStatusDescriptor = $convert.base64Decode( + 'CgtBcHBseVN0YXR1cxIcChhBUFBMWV9TVEFUVVNfVU5TUEVDSUZJRUQQABIYChRBUFBMWV9TVE' + 'FUVVNfUEVORElORxABEhkKFUFQUExZX1NUQVRVU19WRVJJRklFRBACEhgKFEFQUExZX1NUQVRV' + 'U19SRU1PVkVEEAMSGAoUQVBQTFlfU1RBVFVTX0VYUElSRUQQBBIXChNBUFBMWV9TVEFUVVNfRk' + 'FJTEVEEAU='); + +@$core.Deprecated('Use tCPSettingsDescriptor instead') +const TCPSettings$json = { + '1': 'TCPSettings', + '2': [ + { + '1': 'congestion_control', + '3': 1, + '4': 1, + '5': 9, + '9': 0, + '10': 'congestionControl', + '17': true + }, + {'1': 'congestion_lock', '3': 2, '4': 1, '5': 8, '10': 'congestionLock'}, + { + '1': 'rto_min_ms', + '3': 3, + '4': 1, + '5': 13, + '9': 1, + '10': 'rtoMinMs', + '17': true + }, + { + '1': 'initial_congestion_window', + '3': 4, + '4': 1, + '5': 13, + '9': 2, + '10': 'initialCongestionWindow', + '17': true + }, + { + '1': 'initial_receive_window', + '3': 5, + '4': 1, + '5': 13, + '9': 3, + '10': 'initialReceiveWindow', + '17': true + }, + { + '1': 'quick_ack', + '3': 6, + '4': 1, + '5': 8, + '9': 4, + '10': 'quickAck', + '17': true + }, + {'1': 'ecn', '3': 7, '4': 1, '5': 8, '9': 5, '10': 'ecn', '17': true}, + ], + '8': [ + {'1': '_congestion_control'}, + {'1': '_rto_min_ms'}, + {'1': '_initial_congestion_window'}, + {'1': '_initial_receive_window'}, + {'1': '_quick_ack'}, + {'1': '_ecn'}, + ], +}; + +/// Descriptor for `TCPSettings`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List tCPSettingsDescriptor = $convert.base64Decode( + 'CgtUQ1BTZXR0aW5ncxIyChJjb25nZXN0aW9uX2NvbnRyb2wYASABKAlIAFIRY29uZ2VzdGlvbk' + 'NvbnRyb2yIAQESJwoPY29uZ2VzdGlvbl9sb2NrGAIgASgIUg5jb25nZXN0aW9uTG9jaxIhCgpy' + 'dG9fbWluX21zGAMgASgNSAFSCHJ0b01pbk1ziAEBEj8KGWluaXRpYWxfY29uZ2VzdGlvbl93aW' + '5kb3cYBCABKA1IAlIXaW5pdGlhbENvbmdlc3Rpb25XaW5kb3eIAQESOQoWaW5pdGlhbF9yZWNl' + 'aXZlX3dpbmRvdxgFIAEoDUgDUhRpbml0aWFsUmVjZWl2ZVdpbmRvd4gBARIgCglxdWlja19hY2' + 'sYBiABKAhIBFIIcXVpY2tBY2uIAQESFQoDZWNuGAcgASgISAVSA2VjbogBAUIVChNfY29uZ2Vz' + 'dGlvbl9jb250cm9sQg0KC19ydG9fbWluX21zQhwKGl9pbml0aWFsX2Nvbmdlc3Rpb25fd2luZG' + '93QhkKF19pbml0aWFsX3JlY2VpdmVfd2luZG93QgwKCl9xdWlja19hY2tCBgoEX2Vjbg=='); + +@$core.Deprecated('Use treatmentDescriptor instead') +const Treatment$json = { + '1': 'Treatment', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, + {'1': 'revision', '3': 2, '4': 1, '5': 4, '10': 'revision'}, + {'1': 'destination', '3': 3, '4': 1, '5': 9, '10': 'destination'}, + { + '1': 'settings', + '3': 4, + '4': 1, + '5': 11, + '6': '.xtcp_treatment_journal.v1.TCPSettings', + '10': 'settings' + }, + { + '1': 'ecn_fabric_verified', + '3': 5, + '4': 1, + '5': 8, + '10': 'ecnFabricVerified' + }, + ], +}; + +/// Descriptor for `Treatment`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List treatmentDescriptor = $convert.base64Decode( + 'CglUcmVhdG1lbnQSDgoCaWQYASABKAlSAmlkEhoKCHJldmlzaW9uGAIgASgEUghyZXZpc2lvbh' + 'IgCgtkZXN0aW5hdGlvbhgDIAEoCVILZGVzdGluYXRpb24SQgoIc2V0dGluZ3MYBCABKAsyJi54' + 'dGNwX3RyZWF0bWVudF9qb3VybmFsLnYxLlRDUFNldHRpbmdzUghzZXR0aW5ncxIuChNlY25fZm' + 'FicmljX3ZlcmlmaWVkGAUgASgIUhFlY25GYWJyaWNWZXJpZmllZA=='); + +@$core.Deprecated('Use assignmentDescriptor instead') +const Assignment$json = { + '1': 'Assignment', + '2': [ + {'1': 'experiment_id', '3': 1, '4': 1, '5': 9, '10': 'experimentId'}, + { + '1': 'treatment', + '3': 2, + '4': 1, + '5': 11, + '6': '.xtcp_treatment_journal.v1.Treatment', + '10': 'treatment' + }, + { + '1': 'mode', + '3': 3, + '4': 1, + '5': 14, + '6': '.xtcp_treatment_journal.v1.AssignmentMode', + '10': 'mode' + }, + { + '1': 'lease_expires_at', + '3': 4, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'leaseExpiresAt' + }, + { + '1': 'predecessor', + '3': 5, + '4': 1, + '5': 11, + '6': '.xtcp_treatment_journal.v1.Treatment', + '10': 'predecessor' + }, + {'1': 'generation', '3': 6, '4': 1, '5': 4, '10': 'generation'}, + ], +}; + +/// Descriptor for `Assignment`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List assignmentDescriptor = $convert.base64Decode( + 'CgpBc3NpZ25tZW50EiMKDWV4cGVyaW1lbnRfaWQYASABKAlSDGV4cGVyaW1lbnRJZBJCCgl0cm' + 'VhdG1lbnQYAiABKAsyJC54dGNwX3RyZWF0bWVudF9qb3VybmFsLnYxLlRyZWF0bWVudFIJdHJl' + 'YXRtZW50Ej0KBG1vZGUYAyABKA4yKS54dGNwX3RyZWF0bWVudF9qb3VybmFsLnYxLkFzc2lnbm' + '1lbnRNb2RlUgRtb2RlEkQKEGxlYXNlX2V4cGlyZXNfYXQYBCABKAsyGi5nb29nbGUucHJvdG9i' + 'dWYuVGltZXN0YW1wUg5sZWFzZUV4cGlyZXNBdBJGCgtwcmVkZWNlc3NvchgFIAEoCzIkLnh0Y3' + 'BfdHJlYXRtZW50X2pvdXJuYWwudjEuVHJlYXRtZW50UgtwcmVkZWNlc3NvchIeCgpnZW5lcmF0' + 'aW9uGAYgASgEUgpnZW5lcmF0aW9u'); + +@$core.Deprecated('Use desiredDescriptor instead') +const Desired$json = { + '1': 'Desired', + '2': [ + {'1': 'revision', '3': 1, '4': 1, '5': 4, '10': 'revision'}, + {'1': 'suspended', '3': 2, '4': 1, '5': 8, '10': 'suspended'}, + { + '1': 'issued_at', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'issuedAt' + }, + { + '1': 'assignments', + '3': 4, + '4': 3, + '5': 11, + '6': '.xtcp_treatment_journal.v1.Assignment', + '10': 'assignments' + }, + ], +}; + +/// Descriptor for `Desired`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List desiredDescriptor = $convert.base64Decode( + 'CgdEZXNpcmVkEhoKCHJldmlzaW9uGAEgASgEUghyZXZpc2lvbhIcCglzdXNwZW5kZWQYAiABKA' + 'hSCXN1c3BlbmRlZBI3Cglpc3N1ZWRfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0' + 'YW1wUghpc3N1ZWRBdBJHCgthc3NpZ25tZW50cxgEIAMoCzIlLnh0Y3BfdHJlYXRtZW50X2pvdX' + 'JuYWwudjEuQXNzaWdubWVudFILYXNzaWdubWVudHM='); + +@$core.Deprecated('Use recordDescriptor instead') +const Record$json = { + '1': 'Record', + '2': [ + { + '1': 'assignment', + '3': 1, + '4': 1, + '5': 11, + '6': '.xtcp_treatment_journal.v1.Assignment', + '10': 'assignment' + }, + {'1': 'desired_revision', '3': 2, '4': 1, '5': 4, '10': 'desiredRevision'}, + { + '1': 'status', + '3': 3, + '4': 1, + '5': 14, + '6': '.xtcp_treatment_journal.v1.ApplyStatus', + '10': 'status' + }, + { + '1': 'received_at', + '3': 4, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'receivedAt' + }, + { + '1': 'attempted_at', + '3': 5, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'attemptedAt' + }, + { + '1': 'applied_at', + '3': 6, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'appliedAt' + }, + { + '1': 'verified_at', + '3': 7, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'verifiedAt' + }, + { + '1': 'removed_at', + '3': 8, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'removedAt' + }, + {'1': 'error', '3': 9, '4': 1, '5': 9, '10': 'error'}, + {'1': 'installed_route', '3': 10, '4': 1, '5': 12, '10': 'installedRoute'}, + { + '1': 'installed_boot_id', + '3': 11, + '4': 1, + '5': 9, + '10': 'installedBootId' + }, + {'1': 'expired_latched', '3': 12, '4': 1, '5': 8, '10': 'expiredLatched'}, + ], +}; + +/// Descriptor for `Record`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List recordDescriptor = $convert.base64Decode( + 'CgZSZWNvcmQSRQoKYXNzaWdubWVudBgBIAEoCzIlLnh0Y3BfdHJlYXRtZW50X2pvdXJuYWwudj' + 'EuQXNzaWdubWVudFIKYXNzaWdubWVudBIpChBkZXNpcmVkX3JldmlzaW9uGAIgASgEUg9kZXNp' + 'cmVkUmV2aXNpb24SPgoGc3RhdHVzGAMgASgOMiYueHRjcF90cmVhdG1lbnRfam91cm5hbC52MS' + '5BcHBseVN0YXR1c1IGc3RhdHVzEjsKC3JlY2VpdmVkX2F0GAQgASgLMhouZ29vZ2xlLnByb3Rv' + 'YnVmLlRpbWVzdGFtcFIKcmVjZWl2ZWRBdBI9CgxhdHRlbXB0ZWRfYXQYBSABKAsyGi5nb29nbG' + 'UucHJvdG9idWYuVGltZXN0YW1wUgthdHRlbXB0ZWRBdBI5CgphcHBsaWVkX2F0GAYgASgLMhou' + 'Z29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcFIJYXBwbGllZEF0EjsKC3ZlcmlmaWVkX2F0GAcgAS' + 'gLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcFIKdmVyaWZpZWRBdBI5CgpyZW1vdmVkX2F0' + 'GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcFIJcmVtb3ZlZEF0EhQKBWVycm9yGA' + 'kgASgJUgVlcnJvchInCg9pbnN0YWxsZWRfcm91dGUYCiABKAxSDmluc3RhbGxlZFJvdXRlEioK' + 'EWluc3RhbGxlZF9ib290X2lkGAsgASgJUg9pbnN0YWxsZWRCb290SWQSJwoPZXhwaXJlZF9sYX' + 'RjaGVkGAwgASgIUg5leHBpcmVkTGF0Y2hlZA=='); + +@$core.Deprecated('Use journalDescriptor instead') +const Journal$json = { + '1': 'Journal', + '2': [ + {'1': 'agent_id', '3': 1, '4': 1, '5': 9, '10': 'agentId'}, + {'1': 'location', '3': 2, '4': 1, '5': 9, '10': 'location'}, + {'1': 'boot_id', '3': 3, '4': 1, '5': 9, '10': 'bootId'}, + { + '1': 'desired', + '3': 4, + '4': 1, + '5': 11, + '6': '.xtcp_treatment_journal.v1.Desired', + '10': 'desired' + }, + { + '1': 'locally_suspended', + '3': 5, + '4': 1, + '5': 8, + '10': 'locallySuspended' + }, + { + '1': 'suspension_reason', + '3': 6, + '4': 1, + '5': 9, + '10': 'suspensionReason' + }, + { + '1': 'records', + '3': 7, + '4': 3, + '5': 11, + '6': '.xtcp_treatment_journal.v1.Record', + '10': 'records' + }, + { + '1': 'updated_at', + '3': 8, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '10': 'updatedAt' + }, + {'1': 'collection_id', '3': 9, '4': 1, '5': 9, '10': 'collectionId'}, + ], +}; + +/// Descriptor for `Journal`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List journalDescriptor = $convert.base64Decode( + 'CgdKb3VybmFsEhkKCGFnZW50X2lkGAEgASgJUgdhZ2VudElkEhoKCGxvY2F0aW9uGAIgASgJUg' + 'hsb2NhdGlvbhIXCgdib290X2lkGAMgASgJUgZib290SWQSPAoHZGVzaXJlZBgEIAEoCzIiLnh0' + 'Y3BfdHJlYXRtZW50X2pvdXJuYWwudjEuRGVzaXJlZFIHZGVzaXJlZBIrChFsb2NhbGx5X3N1c3' + 'BlbmRlZBgFIAEoCFIQbG9jYWxseVN1c3BlbmRlZBIrChFzdXNwZW5zaW9uX3JlYXNvbhgGIAEo' + 'CVIQc3VzcGVuc2lvblJlYXNvbhI7CgdyZWNvcmRzGAcgAygLMiEueHRjcF90cmVhdG1lbnRfam' + '91cm5hbC52MS5SZWNvcmRSB3JlY29yZHMSOQoKdXBkYXRlZF9hdBgIIAEoCzIaLmdvb2dsZS5w' + 'cm90b2J1Zi5UaW1lc3RhbXBSCXVwZGF0ZWRBdBIjCg1jb2xsZWN0aW9uX2lkGAkgASgJUgxjb2' + 'xsZWN0aW9uSWQ='); diff --git a/gen/go/xtcp_flat_record/xtcp_flat_record.pb.go b/gen/go/xtcp_flat_record/xtcp_flat_record.pb.go index 1d806cdd0..6cf7a6456 100644 --- a/gen/go/xtcp_flat_record/xtcp_flat_record.pb.go +++ b/gen/go/xtcp_flat_record/xtcp_flat_record.pb.go @@ -52,7 +52,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc (unknown) +// protoc v7.36.2 // source: xtcp_flat_record/v1/xtcp_flat_record.proto package xtcp_flat_record @@ -265,6 +265,17 @@ type XtcpFlatRecord struct { // -location flag or LOCATION env. Constant for every record from one // daemon instance. Location string `protobuf:"bytes,21,opt,name=location,proto3" json:"location,omitempty"` + // Controller provenance. Empty/zero means observation-only legacy producer. + AgentId string `protobuf:"bytes,22,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + HostBootId string `protobuf:"bytes,23,opt,name=host_boot_id,json=hostBootId,proto3" json:"host_boot_id,omitempty"` + CollectionId string `protobuf:"bytes,24,opt,name=collection_id,json=collectionId,proto3" json:"collection_id,omitempty"` + TreatmentStateRevision uint64 `protobuf:"varint,25,opt,name=treatment_state_revision,json=treatmentStateRevision,proto3" json:"treatment_state_revision,omitempty"` + TreatmentAssignmentId string `protobuf:"bytes,26,opt,name=treatment_assignment_id,json=treatmentAssignmentId,proto3" json:"treatment_assignment_id,omitempty"` + TreatmentGeneration uint64 `protobuf:"varint,27,opt,name=treatment_generation,json=treatmentGeneration,proto3" json:"treatment_generation,omitempty"` + TreatmentAppliedTimestampNs int64 `protobuf:"varint,28,opt,name=treatment_applied_timestamp_ns,json=treatmentAppliedTimestampNs,proto3" json:"treatment_applied_timestamp_ns,omitempty"` + // True only when the observed socket algorithm matches a verified route + // assignment in this namespace. This does not prove initial-window exposure. + TreatmentAlgorithmExposed bool `protobuf:"varint,29,opt,name=treatment_algorithm_exposed,json=treatmentAlgorithmExposed,proto3" json:"treatment_algorithm_exposed,omitempty"` // ---- metadata: network namespace identity (30s) -------------------------- // network namespace — best-effort human name (bind-mount name, else a // container-derived name, else "netns:[]"). Not a stable key; use @@ -606,6 +617,62 @@ func (x *XtcpFlatRecord) GetLocation() string { return "" } +func (x *XtcpFlatRecord) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +func (x *XtcpFlatRecord) GetHostBootId() string { + if x != nil { + return x.HostBootId + } + return "" +} + +func (x *XtcpFlatRecord) GetCollectionId() string { + if x != nil { + return x.CollectionId + } + return "" +} + +func (x *XtcpFlatRecord) GetTreatmentStateRevision() uint64 { + if x != nil { + return x.TreatmentStateRevision + } + return 0 +} + +func (x *XtcpFlatRecord) GetTreatmentAssignmentId() string { + if x != nil { + return x.TreatmentAssignmentId + } + return "" +} + +func (x *XtcpFlatRecord) GetTreatmentGeneration() uint64 { + if x != nil { + return x.TreatmentGeneration + } + return 0 +} + +func (x *XtcpFlatRecord) GetTreatmentAppliedTimestampNs() int64 { + if x != nil { + return x.TreatmentAppliedTimestampNs + } + return 0 +} + +func (x *XtcpFlatRecord) GetTreatmentAlgorithmExposed() bool { + if x != nil { + return x.TreatmentAlgorithmExposed + } + return false +} + func (x *XtcpFlatRecord) GetNetns() string { if x != nil { return x.Netns @@ -1942,14 +2009,23 @@ const file_xtcp_flat_record_v1_xtcp_flat_record_proto_rawDesc = "" + "*xtcp_flat_record/v1/xtcp_flat_record.proto\x12\x13xtcp_flat_record.v1\"A\n" + "\bEnvelope\x125\n" + "\x03row\x18\n" + - " \x03(\v2#.xtcp_flat_record.v1.XtcpFlatRecordR\x03row\"\xbaI\n" + + " \x03(\v2#.xtcp_flat_record.v1.XtcpFlatRecordR\x03row\"\xc6L\n" + "\x0eXtcpFlatRecord\x12%\n" + "\x0eschema_version\x18\x01 \x01(\rR\rschemaVersion\x12%\n" + "\x0edaemon_version\x18\x02 \x01(\tR\rdaemonVersion\x12!\n" + "\ftimestamp_ns\x18\n" + " \x01(\x03R\vtimestampNs\x12\x1a\n" + "\bhostname\x18\x14 \x01(\tR\bhostname\x12\x1a\n" + - "\blocation\x18\x15 \x01(\tR\blocation\x12\x14\n" + + "\blocation\x18\x15 \x01(\tR\blocation\x12\x19\n" + + "\bagent_id\x18\x16 \x01(\tR\aagentId\x12 \n" + + "\fhost_boot_id\x18\x17 \x01(\tR\n" + + "hostBootId\x12#\n" + + "\rcollection_id\x18\x18 \x01(\tR\fcollectionId\x128\n" + + "\x18treatment_state_revision\x18\x19 \x01(\x04R\x16treatmentStateRevision\x126\n" + + "\x17treatment_assignment_id\x18\x1a \x01(\tR\x15treatmentAssignmentId\x121\n" + + "\x14treatment_generation\x18\x1b \x01(\x04R\x13treatmentGeneration\x12C\n" + + "\x1etreatment_applied_timestamp_ns\x18\x1c \x01(\x03R\x1btreatmentAppliedTimestampNs\x12>\n" + + "\x1btreatment_algorithm_exposed\x18\x1d \x01(\bR\x19treatmentAlgorithmExposed\x12\x14\n" + "\x05netns\x18\x1e \x01(\tR\x05netns\x12\x1f\n" + "\vnetns_inode\x18\x1f \x01(\x04R\n" + "netnsInode\x12\x12\n" + @@ -2147,8 +2223,7 @@ const file_xtcp_flat_record_v1_xtcp_flat_record_proto_rawDesc = "" + "\x10xtcp_flat_record\x18\x01 \x01(\v2#.xtcp_flat_record.v1.XtcpFlatRecordR\x0extcpFlatRecord2\xed\x01\n" + "\x15XTCPFlatRecordService\x12b\n" + "\vFlatRecords\x12'.xtcp_flat_record.v1.FlatRecordsRequest\x1a(.xtcp_flat_record.v1.FlatRecordsResponse0\x01\x12p\n" + - "\x0fPollFlatRecords\x12+.xtcp_flat_record.v1.PollFlatRecordsRequest\x1a,.xtcp_flat_record.v1.PollFlatRecordsResponse(\x010\x01B\xcd\x01\n" + - "\x17com.xtcp_flat_record.v1B\x13XtcpFlatRecordProtoP\x01Z8github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record\xa2\x02\x03XXX\xaa\x02\x11XtcpFlatRecord.V1\xca\x02\x11XtcpFlatRecord\\V1\xe2\x02\x1dXtcpFlatRecord\\V1\\GPBMetadata\xea\x02\x12XtcpFlatRecord::V1b\x06proto3" + "\x0fPollFlatRecords\x12+.xtcp_flat_record.v1.PollFlatRecordsRequest\x1a,.xtcp_flat_record.v1.PollFlatRecordsResponse(\x010\x01B:Z8github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_recordb\x06proto3" var ( file_xtcp_flat_record_v1_xtcp_flat_record_proto_rawDescOnce sync.Once diff --git a/gen/go/xtcp_flat_record/xtcp_flat_record_vtproto.pb.go b/gen/go/xtcp_flat_record/xtcp_flat_record_vtproto.pb.go index a98c2897d..cf625e899 100644 --- a/gen/go/xtcp_flat_record/xtcp_flat_record_vtproto.pb.go +++ b/gen/go/xtcp_flat_record/xtcp_flat_record_vtproto.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. -// protoc-gen-go-vtproto version: (devel) +// protoc-gen-go-vtproto version: v0.6.1-0.20240319094008-0393e58bdf10 // source: xtcp_flat_record/v1/xtcp_flat_record.proto package xtcp_flat_record @@ -1328,6 +1328,75 @@ func (m *XtcpFlatRecord) MarshalToSizedBufferVT(dAtA []byte) (int, error) { i-- dAtA[i] = 0xf2 } + if m.TreatmentAlgorithmExposed { + i-- + if m.TreatmentAlgorithmExposed { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xe8 + } + if m.TreatmentAppliedTimestampNs != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.TreatmentAppliedTimestampNs)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xe0 + } + if m.TreatmentGeneration != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.TreatmentGeneration)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xd8 + } + if len(m.TreatmentAssignmentId) > 0 { + i -= len(m.TreatmentAssignmentId) + copy(dAtA[i:], m.TreatmentAssignmentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.TreatmentAssignmentId))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xd2 + } + if m.TreatmentStateRevision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.TreatmentStateRevision)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xc8 + } + if len(m.CollectionId) > 0 { + i -= len(m.CollectionId) + copy(dAtA[i:], m.CollectionId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.CollectionId))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xc2 + } + if len(m.HostBootId) > 0 { + i -= len(m.HostBootId) + copy(dAtA[i:], m.HostBootId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.HostBootId))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xba + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xb2 + } if len(m.Location) > 0 { i -= len(m.Location) copy(dAtA[i:], m.Location) @@ -1558,6 +1627,34 @@ func (m *XtcpFlatRecord) SizeVT() (n int) { if l > 0 { n += 2 + l + protohelpers.SizeOfVarint(uint64(l)) } + l = len(m.AgentId) + if l > 0 { + n += 2 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.HostBootId) + if l > 0 { + n += 2 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.CollectionId) + if l > 0 { + n += 2 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.TreatmentStateRevision != 0 { + n += 2 + protohelpers.SizeOfVarint(uint64(m.TreatmentStateRevision)) + } + l = len(m.TreatmentAssignmentId) + if l > 0 { + n += 2 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.TreatmentGeneration != 0 { + n += 2 + protohelpers.SizeOfVarint(uint64(m.TreatmentGeneration)) + } + if m.TreatmentAppliedTimestampNs != 0 { + n += 2 + protohelpers.SizeOfVarint(uint64(m.TreatmentAppliedTimestampNs)) + } + if m.TreatmentAlgorithmExposed { + n += 3 + } l = len(m.Netns) if l > 0 { n += 2 + l + protohelpers.SizeOfVarint(uint64(l)) @@ -2392,6 +2489,211 @@ func (m *XtcpFlatRecord) UnmarshalVT(dAtA []byte) error { } m.Location = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 22: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 23: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HostBootId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HostBootId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 24: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CollectionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CollectionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 25: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TreatmentStateRevision", wireType) + } + m.TreatmentStateRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TreatmentStateRevision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 26: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TreatmentAssignmentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TreatmentAssignmentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 27: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TreatmentGeneration", wireType) + } + m.TreatmentGeneration = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TreatmentGeneration |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 28: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TreatmentAppliedTimestampNs", wireType) + } + m.TreatmentAppliedTimestampNs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TreatmentAppliedTimestampNs |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 29: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TreatmentAlgorithmExposed", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.TreatmentAlgorithmExposed = bool(v != 0) case 30: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Netns", wireType) diff --git a/gen/go/xtcp_treatment/agent.pb.go b/gen/go/xtcp_treatment/agent.pb.go new file mode 100644 index 000000000..8e4a544dc --- /dev/null +++ b/gen/go/xtcp_treatment/agent.pb.go @@ -0,0 +1,440 @@ +// +// xTCP - treatment agent service +// +// The outbound-only RPC surface an agent uses: check in with observed state, +// fetch the authoritative desired state, and watch for revision hints. Every +// method requires an agent certificate whose SPIFFE id matches agent_id and +// whose location matches the request; see pkg/treatment/identity. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc (unknown) +// source: xtcp_treatment/v1/agent.proto + +package xtcp_treatment + +import ( + _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CheckInRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + AgentId string `protobuf:"bytes,1,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + Location string `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` + Capabilities *Capabilities `protobuf:"bytes,3,opt,name=capabilities,proto3" json:"capabilities,omitempty"` + DesiredRevision uint64 `protobuf:"varint,4,opt,name=desired_revision,json=desiredRevision,proto3" json:"desired_revision,omitempty"` + Records []*ApplicationRecord `protobuf:"bytes,5,rep,name=records,proto3" json:"records,omitempty"` + LocallySuspended bool `protobuf:"varint,6,opt,name=locally_suspended,json=locallySuspended,proto3" json:"locally_suspended,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckInRequest) Reset() { + *x = CheckInRequest{} + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckInRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckInRequest) ProtoMessage() {} + +func (x *CheckInRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckInRequest.ProtoReflect.Descriptor instead. +func (*CheckInRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_agent_proto_rawDescGZIP(), []int{0} +} + +func (x *CheckInRequest) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +func (x *CheckInRequest) GetLocation() string { + if x != nil { + return x.Location + } + return "" +} + +func (x *CheckInRequest) GetCapabilities() *Capabilities { + if x != nil { + return x.Capabilities + } + return nil +} + +func (x *CheckInRequest) GetDesiredRevision() uint64 { + if x != nil { + return x.DesiredRevision + } + return 0 +} + +func (x *CheckInRequest) GetRecords() []*ApplicationRecord { + if x != nil { + return x.Records + } + return nil +} + +func (x *CheckInRequest) GetLocallySuspended() bool { + if x != nil { + return x.LocallySuspended + } + return false +} + +type CheckInResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Desired *DesiredState `protobuf:"bytes,1,opt,name=desired,proto3" json:"desired,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CheckInResponse) Reset() { + *x = CheckInResponse{} + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckInResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckInResponse) ProtoMessage() {} + +func (x *CheckInResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckInResponse.ProtoReflect.Descriptor instead. +func (*CheckInResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_agent_proto_rawDescGZIP(), []int{1} +} + +func (x *CheckInResponse) GetDesired() *DesiredState { + if x != nil { + return x.Desired + } + return nil +} + +type GetDesiredStateRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + AgentId string `protobuf:"bytes,1,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetDesiredStateRequest) Reset() { + *x = GetDesiredStateRequest{} + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetDesiredStateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetDesiredStateRequest) ProtoMessage() {} + +func (x *GetDesiredStateRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetDesiredStateRequest.ProtoReflect.Descriptor instead. +func (*GetDesiredStateRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_agent_proto_rawDescGZIP(), []int{2} +} + +func (x *GetDesiredStateRequest) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +type GetDesiredStateResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Desired *DesiredState `protobuf:"bytes,1,opt,name=desired,proto3" json:"desired,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetDesiredStateResponse) Reset() { + *x = GetDesiredStateResponse{} + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetDesiredStateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetDesiredStateResponse) ProtoMessage() {} + +func (x *GetDesiredStateResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetDesiredStateResponse.ProtoReflect.Descriptor instead. +func (*GetDesiredStateResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_agent_proto_rawDescGZIP(), []int{3} +} + +func (x *GetDesiredStateResponse) GetDesired() *DesiredState { + if x != nil { + return x.Desired + } + return nil +} + +type WatchDesiredStateRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + AgentId string `protobuf:"bytes,1,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + AfterRevision uint64 `protobuf:"varint,2,opt,name=after_revision,json=afterRevision,proto3" json:"after_revision,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchDesiredStateRequest) Reset() { + *x = WatchDesiredStateRequest{} + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchDesiredStateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchDesiredStateRequest) ProtoMessage() {} + +func (x *WatchDesiredStateRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatchDesiredStateRequest.ProtoReflect.Descriptor instead. +func (*WatchDesiredStateRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_agent_proto_rawDescGZIP(), []int{4} +} + +func (x *WatchDesiredStateRequest) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +func (x *WatchDesiredStateRequest) GetAfterRevision() uint64 { + if x != nil { + return x.AfterRevision + } + return 0 +} + +type WatchDesiredStateResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Revision uint64 `protobuf:"varint,1,opt,name=revision,proto3" json:"revision,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchDesiredStateResponse) Reset() { + *x = WatchDesiredStateResponse{} + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchDesiredStateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchDesiredStateResponse) ProtoMessage() {} + +func (x *WatchDesiredStateResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_agent_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WatchDesiredStateResponse.ProtoReflect.Descriptor instead. +func (*WatchDesiredStateResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_agent_proto_rawDescGZIP(), []int{5} +} + +func (x *WatchDesiredStateResponse) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +var File_xtcp_treatment_v1_agent_proto protoreflect.FileDescriptor + +const file_xtcp_treatment_v1_agent_proto_rawDesc = "" + + "\n" + + "\x1dxtcp_treatment/v1/agent.proto\x12\x11xtcp_treatment.v1\x1a\x1bbuf/validate/validate.proto\x1a!xtcp_treatment/v1/treatment.proto\"\x8d\x03\n" + + "\x0eCheckInRequest\x12D\n" + + "\bagent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\aagentId\x12E\n" + + "\blocation\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\blocation\x12K\n" + + "\fcapabilities\x18\x03 \x01(\v2\x1f.xtcp_treatment.v1.CapabilitiesB\x06\xbaH\x03\xc8\x01\x01R\fcapabilities\x12)\n" + + "\x10desired_revision\x18\x04 \x01(\x04R\x0fdesiredRevision\x12I\n" + + "\arecords\x18\x05 \x03(\v2$.xtcp_treatment.v1.ApplicationRecordB\t\xbaH\x06\x92\x01\x03\x10\x80@R\arecords\x12+\n" + + "\x11locally_suspended\x18\x06 \x01(\bR\x10locallySuspended\"L\n" + + "\x0fCheckInResponse\x129\n" + + "\adesired\x18\x01 \x01(\v2\x1f.xtcp_treatment.v1.DesiredStateR\adesired\"^\n" + + "\x16GetDesiredStateRequest\x12D\n" + + "\bagent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\aagentId\"T\n" + + "\x17GetDesiredStateResponse\x129\n" + + "\adesired\x18\x01 \x01(\v2\x1f.xtcp_treatment.v1.DesiredStateR\adesired\"\x87\x01\n" + + "\x18WatchDesiredStateRequest\x12D\n" + + "\bagent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\aagentId\x12%\n" + + "\x0eafter_revision\x18\x02 \x01(\x04R\rafterRevision\"7\n" + + "\x19WatchDesiredStateResponse\x12\x1a\n" + + "\brevision\x18\x01 \x01(\x04R\brevision2\xd5\x02\n" + + "\x13AgentControlService\x12V\n" + + "\aCheckIn\x12!.xtcp_treatment.v1.CheckInRequest\x1a\".xtcp_treatment.v1.CheckInResponse\"\x04\xd0\xf3\x18\x01\x12n\n" + + "\x0fGetDesiredState\x12).xtcp_treatment.v1.GetDesiredStateRequest\x1a*.xtcp_treatment.v1.GetDesiredStateResponse\"\x04\xd0\xf3\x18\x01\x12v\n" + + "\x11WatchDesiredState\x12+.xtcp_treatment.v1.WatchDesiredStateRequest\x1a,.xtcp_treatment.v1.WatchDesiredStateResponse\"\x04\xd0\xf3\x18\x010\x01B\xbc\x01\n" + + "\x15com.xtcp_treatment.v1B\n" + + "AgentProtoP\x01Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\xa2\x02\x03XXX\xaa\x02\x10XtcpTreatment.V1\xca\x02\x10XtcpTreatment\\V1\xe2\x02\x1cXtcpTreatment\\V1\\GPBMetadata\xea\x02\x11XtcpTreatment::V1b\x06proto3" + +var ( + file_xtcp_treatment_v1_agent_proto_rawDescOnce sync.Once + file_xtcp_treatment_v1_agent_proto_rawDescData []byte +) + +func file_xtcp_treatment_v1_agent_proto_rawDescGZIP() []byte { + file_xtcp_treatment_v1_agent_proto_rawDescOnce.Do(func() { + file_xtcp_treatment_v1_agent_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_xtcp_treatment_v1_agent_proto_rawDesc), len(file_xtcp_treatment_v1_agent_proto_rawDesc))) + }) + return file_xtcp_treatment_v1_agent_proto_rawDescData +} + +var file_xtcp_treatment_v1_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_xtcp_treatment_v1_agent_proto_goTypes = []any{ + (*CheckInRequest)(nil), // 0: xtcp_treatment.v1.CheckInRequest + (*CheckInResponse)(nil), // 1: xtcp_treatment.v1.CheckInResponse + (*GetDesiredStateRequest)(nil), // 2: xtcp_treatment.v1.GetDesiredStateRequest + (*GetDesiredStateResponse)(nil), // 3: xtcp_treatment.v1.GetDesiredStateResponse + (*WatchDesiredStateRequest)(nil), // 4: xtcp_treatment.v1.WatchDesiredStateRequest + (*WatchDesiredStateResponse)(nil), // 5: xtcp_treatment.v1.WatchDesiredStateResponse + (*Capabilities)(nil), // 6: xtcp_treatment.v1.Capabilities + (*ApplicationRecord)(nil), // 7: xtcp_treatment.v1.ApplicationRecord + (*DesiredState)(nil), // 8: xtcp_treatment.v1.DesiredState +} +var file_xtcp_treatment_v1_agent_proto_depIdxs = []int32{ + 6, // 0: xtcp_treatment.v1.CheckInRequest.capabilities:type_name -> xtcp_treatment.v1.Capabilities + 7, // 1: xtcp_treatment.v1.CheckInRequest.records:type_name -> xtcp_treatment.v1.ApplicationRecord + 8, // 2: xtcp_treatment.v1.CheckInResponse.desired:type_name -> xtcp_treatment.v1.DesiredState + 8, // 3: xtcp_treatment.v1.GetDesiredStateResponse.desired:type_name -> xtcp_treatment.v1.DesiredState + 0, // 4: xtcp_treatment.v1.AgentControlService.CheckIn:input_type -> xtcp_treatment.v1.CheckInRequest + 2, // 5: xtcp_treatment.v1.AgentControlService.GetDesiredState:input_type -> xtcp_treatment.v1.GetDesiredStateRequest + 4, // 6: xtcp_treatment.v1.AgentControlService.WatchDesiredState:input_type -> xtcp_treatment.v1.WatchDesiredStateRequest + 1, // 7: xtcp_treatment.v1.AgentControlService.CheckIn:output_type -> xtcp_treatment.v1.CheckInResponse + 3, // 8: xtcp_treatment.v1.AgentControlService.GetDesiredState:output_type -> xtcp_treatment.v1.GetDesiredStateResponse + 5, // 9: xtcp_treatment.v1.AgentControlService.WatchDesiredState:output_type -> xtcp_treatment.v1.WatchDesiredStateResponse + 7, // [7:10] is the sub-list for method output_type + 4, // [4:7] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_xtcp_treatment_v1_agent_proto_init() } +func file_xtcp_treatment_v1_agent_proto_init() { + if File_xtcp_treatment_v1_agent_proto != nil { + return + } + file_xtcp_treatment_v1_treatment_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_xtcp_treatment_v1_agent_proto_rawDesc), len(file_xtcp_treatment_v1_agent_proto_rawDesc)), + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_xtcp_treatment_v1_agent_proto_goTypes, + DependencyIndexes: file_xtcp_treatment_v1_agent_proto_depIdxs, + MessageInfos: file_xtcp_treatment_v1_agent_proto_msgTypes, + }.Build() + File_xtcp_treatment_v1_agent_proto = out.File + file_xtcp_treatment_v1_agent_proto_goTypes = nil + file_xtcp_treatment_v1_agent_proto_depIdxs = nil +} diff --git a/gen/go/xtcp_treatment/agent.pb.gw.go b/gen/go/xtcp_treatment/agent.pb.gw.go new file mode 100644 index 000000000..8686a944a --- /dev/null +++ b/gen/go/xtcp_treatment/agent.pb.gw.go @@ -0,0 +1,272 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: xtcp_treatment/v1/agent.proto + +/* +Package xtcp_treatment is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package xtcp_treatment + +import ( + "context" + "errors" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) + +func request_AgentControlService_CheckIn_0(ctx context.Context, marshaler runtime.Marshaler, client AgentControlServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq CheckInRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.CheckIn(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_AgentControlService_CheckIn_0(ctx context.Context, marshaler runtime.Marshaler, server AgentControlServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq CheckInRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.CheckIn(ctx, &protoReq) + return msg, metadata, err +} + +func request_AgentControlService_GetDesiredState_0(ctx context.Context, marshaler runtime.Marshaler, client AgentControlServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetDesiredStateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.GetDesiredState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_AgentControlService_GetDesiredState_0(ctx context.Context, marshaler runtime.Marshaler, server AgentControlServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetDesiredStateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.GetDesiredState(ctx, &protoReq) + return msg, metadata, err +} + +func request_AgentControlService_WatchDesiredState_0(ctx context.Context, marshaler runtime.Marshaler, client AgentControlServiceClient, req *http.Request, pathParams map[string]string) (AgentControlService_WatchDesiredStateClient, runtime.ServerMetadata, error) { + var ( + protoReq WatchDesiredStateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + stream, err := client.WatchDesiredState(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil +} + +// RegisterAgentControlServiceHandlerServer registers the http handlers for service AgentControlService to "mux". +// UnaryRPC :call AgentControlServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAgentControlServiceHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. +func RegisterAgentControlServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AgentControlServiceServer) error { + mux.Handle(http.MethodPost, pattern_AgentControlService_CheckIn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/xtcp_treatment.v1.AgentControlService/CheckIn", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.AgentControlService/CheckIn")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_AgentControlService_CheckIn_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_AgentControlService_CheckIn_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_AgentControlService_GetDesiredState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/xtcp_treatment.v1.AgentControlService/GetDesiredState", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.AgentControlService/GetDesiredState")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_AgentControlService_GetDesiredState_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_AgentControlService_GetDesiredState_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + + mux.Handle(http.MethodPost, pattern_AgentControlService_WatchDesiredState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + + return nil +} + +// RegisterAgentControlServiceHandlerFromEndpoint is same as RegisterAgentControlServiceHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterAgentControlServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.NewClient(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + return RegisterAgentControlServiceHandler(ctx, mux, conn) +} + +// RegisterAgentControlServiceHandler registers the http handlers for service AgentControlService to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterAgentControlServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterAgentControlServiceHandlerClient(ctx, mux, NewAgentControlServiceClient(conn)) +} + +// RegisterAgentControlServiceHandlerClient registers the http handlers for service AgentControlService +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "AgentControlServiceClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "AgentControlServiceClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "AgentControlServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. +func RegisterAgentControlServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AgentControlServiceClient) error { + mux.Handle(http.MethodPost, pattern_AgentControlService_CheckIn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.AgentControlService/CheckIn", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.AgentControlService/CheckIn")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_AgentControlService_CheckIn_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_AgentControlService_CheckIn_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_AgentControlService_GetDesiredState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.AgentControlService/GetDesiredState", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.AgentControlService/GetDesiredState")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_AgentControlService_GetDesiredState_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_AgentControlService_GetDesiredState_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_AgentControlService_WatchDesiredState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.AgentControlService/WatchDesiredState", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.AgentControlService/WatchDesiredState")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_AgentControlService_WatchDesiredState_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_AgentControlService_WatchDesiredState_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) + }) + return nil +} + +var ( + pattern_AgentControlService_CheckIn_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.AgentControlService", "CheckIn"}, "")) + pattern_AgentControlService_GetDesiredState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.AgentControlService", "GetDesiredState"}, "")) + pattern_AgentControlService_WatchDesiredState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.AgentControlService", "WatchDesiredState"}, "")) +) + +var ( + forward_AgentControlService_CheckIn_0 = runtime.ForwardResponseMessage + forward_AgentControlService_GetDesiredState_0 = runtime.ForwardResponseMessage + forward_AgentControlService_WatchDesiredState_0 = runtime.ForwardResponseStream +) diff --git a/gen/go/xtcp_treatment/agent_grpc.pb.go b/gen/go/xtcp_treatment/agent_grpc.pb.go new file mode 100644 index 000000000..29cf28db9 --- /dev/null +++ b/gen/go/xtcp_treatment/agent_grpc.pb.go @@ -0,0 +1,209 @@ +// +// xTCP - treatment agent service +// +// The outbound-only RPC surface an agent uses: check in with observed state, +// fetch the authoritative desired state, and watch for revision hints. Every +// method requires an agent certificate whose SPIFFE id matches agent_id and +// whose location matches the request; see pkg/treatment/identity. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc (unknown) +// source: xtcp_treatment/v1/agent.proto + +package xtcp_treatment + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + AgentControlService_CheckIn_FullMethodName = "/xtcp_treatment.v1.AgentControlService/CheckIn" + AgentControlService_GetDesiredState_FullMethodName = "/xtcp_treatment.v1.AgentControlService/GetDesiredState" + AgentControlService_WatchDesiredState_FullMethodName = "/xtcp_treatment.v1.AgentControlService/WatchDesiredState" +) + +// AgentControlServiceClient is the client API for AgentControlService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AgentControlServiceClient interface { + CheckIn(ctx context.Context, in *CheckInRequest, opts ...grpc.CallOption) (*CheckInResponse, error) + GetDesiredState(ctx context.Context, in *GetDesiredStateRequest, opts ...grpc.CallOption) (*GetDesiredStateResponse, error) + WatchDesiredState(ctx context.Context, in *WatchDesiredStateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[WatchDesiredStateResponse], error) +} + +type agentControlServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAgentControlServiceClient(cc grpc.ClientConnInterface) AgentControlServiceClient { + return &agentControlServiceClient{cc} +} + +func (c *agentControlServiceClient) CheckIn(ctx context.Context, in *CheckInRequest, opts ...grpc.CallOption) (*CheckInResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CheckInResponse) + err := c.cc.Invoke(ctx, AgentControlService_CheckIn_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *agentControlServiceClient) GetDesiredState(ctx context.Context, in *GetDesiredStateRequest, opts ...grpc.CallOption) (*GetDesiredStateResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetDesiredStateResponse) + err := c.cc.Invoke(ctx, AgentControlService_GetDesiredState_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *agentControlServiceClient) WatchDesiredState(ctx context.Context, in *WatchDesiredStateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[WatchDesiredStateResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &AgentControlService_ServiceDesc.Streams[0], AgentControlService_WatchDesiredState_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[WatchDesiredStateRequest, WatchDesiredStateResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type AgentControlService_WatchDesiredStateClient = grpc.ServerStreamingClient[WatchDesiredStateResponse] + +// AgentControlServiceServer is the server API for AgentControlService service. +// All implementations must embed UnimplementedAgentControlServiceServer +// for forward compatibility. +type AgentControlServiceServer interface { + CheckIn(context.Context, *CheckInRequest) (*CheckInResponse, error) + GetDesiredState(context.Context, *GetDesiredStateRequest) (*GetDesiredStateResponse, error) + WatchDesiredState(*WatchDesiredStateRequest, grpc.ServerStreamingServer[WatchDesiredStateResponse]) error + mustEmbedUnimplementedAgentControlServiceServer() +} + +// UnimplementedAgentControlServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAgentControlServiceServer struct{} + +func (UnimplementedAgentControlServiceServer) CheckIn(context.Context, *CheckInRequest) (*CheckInResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CheckIn not implemented") +} +func (UnimplementedAgentControlServiceServer) GetDesiredState(context.Context, *GetDesiredStateRequest) (*GetDesiredStateResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetDesiredState not implemented") +} +func (UnimplementedAgentControlServiceServer) WatchDesiredState(*WatchDesiredStateRequest, grpc.ServerStreamingServer[WatchDesiredStateResponse]) error { + return status.Error(codes.Unimplemented, "method WatchDesiredState not implemented") +} +func (UnimplementedAgentControlServiceServer) mustEmbedUnimplementedAgentControlServiceServer() {} +func (UnimplementedAgentControlServiceServer) testEmbeddedByValue() {} + +// UnsafeAgentControlServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AgentControlServiceServer will +// result in compilation errors. +type UnsafeAgentControlServiceServer interface { + mustEmbedUnimplementedAgentControlServiceServer() +} + +func RegisterAgentControlServiceServer(s grpc.ServiceRegistrar, srv AgentControlServiceServer) { + // If the following call panics, it indicates UnimplementedAgentControlServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AgentControlService_ServiceDesc, srv) +} + +func _AgentControlService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckInRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentControlServiceServer).CheckIn(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AgentControlService_CheckIn_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentControlServiceServer).CheckIn(ctx, req.(*CheckInRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AgentControlService_GetDesiredState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetDesiredStateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AgentControlServiceServer).GetDesiredState(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AgentControlService_GetDesiredState_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AgentControlServiceServer).GetDesiredState(ctx, req.(*GetDesiredStateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AgentControlService_WatchDesiredState_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(WatchDesiredStateRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(AgentControlServiceServer).WatchDesiredState(m, &grpc.GenericServerStream[WatchDesiredStateRequest, WatchDesiredStateResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type AgentControlService_WatchDesiredStateServer = grpc.ServerStreamingServer[WatchDesiredStateResponse] + +// AgentControlService_ServiceDesc is the grpc.ServiceDesc for AgentControlService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AgentControlService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "xtcp_treatment.v1.AgentControlService", + HandlerType: (*AgentControlServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CheckIn", + Handler: _AgentControlService_CheckIn_Handler, + }, + { + MethodName: "GetDesiredState", + Handler: _AgentControlService_GetDesiredState_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "WatchDesiredState", + Handler: _AgentControlService_WatchDesiredState_Handler, + ServerStreams: true, + }, + }, + Metadata: "xtcp_treatment/v1/agent.proto", +} diff --git a/gen/go/xtcp_treatment/agent_vtproto.pb.go b/gen/go/xtcp_treatment/agent_vtproto.pb.go new file mode 100644 index 000000000..8045d7b0e --- /dev/null +++ b/gen/go/xtcp_treatment/agent_vtproto.pb.go @@ -0,0 +1,1072 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: (devel) +// source: xtcp_treatment/v1/agent.proto + +package xtcp_treatment + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *CheckInRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CheckInRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *CheckInRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.LocallySuspended { + i-- + if m.LocallySuspended { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + if len(m.Records) > 0 { + for iNdEx := len(m.Records) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Records[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + } + if m.DesiredRevision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DesiredRevision)) + i-- + dAtA[i] = 0x20 + } + if m.Capabilities != nil { + size, err := m.Capabilities.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + if len(m.Location) > 0 { + i -= len(m.Location) + copy(dAtA[i:], m.Location) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Location))) + i-- + dAtA[i] = 0x12 + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *CheckInResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CheckInResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *CheckInResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Desired != nil { + size, err := m.Desired.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetDesiredStateRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetDesiredStateRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetDesiredStateRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetDesiredStateResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetDesiredStateResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetDesiredStateResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Desired != nil { + size, err := m.Desired.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WatchDesiredStateRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WatchDesiredStateRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *WatchDesiredStateRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.AfterRevision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.AfterRevision)) + i-- + dAtA[i] = 0x10 + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WatchDesiredStateResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WatchDesiredStateResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *WatchDesiredStateResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Revision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Revision)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *CheckInRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Location) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Capabilities != nil { + l = m.Capabilities.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.DesiredRevision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.DesiredRevision)) + } + if len(m.Records) > 0 { + for _, e := range m.Records { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if m.LocallySuspended { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *CheckInResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Desired != nil { + l = m.Desired.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *GetDesiredStateRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *GetDesiredStateResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Desired != nil { + l = m.Desired.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *WatchDesiredStateRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.AfterRevision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.AfterRevision)) + } + n += len(m.unknownFields) + return n +} + +func (m *WatchDesiredStateResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Revision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Revision)) + } + n += len(m.unknownFields) + return n +} + +func (m *CheckInRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CheckInRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CheckInRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Location", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Location = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Capabilities", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Capabilities == nil { + m.Capabilities = &Capabilities{} + } + if err := m.Capabilities.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DesiredRevision", wireType) + } + m.DesiredRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DesiredRevision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Records = append(m.Records, &ApplicationRecord{}) + if err := m.Records[len(m.Records)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LocallySuspended", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.LocallySuspended = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CheckInResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CheckInResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CheckInResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Desired", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Desired == nil { + m.Desired = &DesiredState{} + } + if err := m.Desired.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetDesiredStateRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetDesiredStateRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetDesiredStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetDesiredStateResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetDesiredStateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetDesiredStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Desired", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Desired == nil { + m.Desired = &DesiredState{} + } + if err := m.Desired.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WatchDesiredStateRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WatchDesiredStateRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WatchDesiredStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AfterRevision", wireType) + } + m.AfterRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.AfterRevision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WatchDesiredStateResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WatchDesiredStateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WatchDesiredStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType) + } + m.Revision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Revision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/gen/go/xtcp_treatment/operator.pb.go b/gen/go/xtcp_treatment/operator.pb.go new file mode 100644 index 000000000..be280cd22 --- /dev/null +++ b/gen/go/xtcp_treatment/operator.pb.go @@ -0,0 +1,826 @@ +// +// xTCP - treatment operator service +// +// The authenticated review surface. Every mutation carries a request_id; +// repeating one with the same body replays the original response, repeating +// it with a different body is refused. Reviews also fence on the experiment +// revision the operator last saw. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc (unknown) +// source: xtcp_treatment/v1/operator.proto + +package xtcp_treatment + +import ( + _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ControlAction int32 + +const ( + ControlAction_CONTROL_ACTION_UNSPECIFIED ControlAction = 0 + ControlAction_CONTROL_ACTION_PAUSE ControlAction = 1 + ControlAction_CONTROL_ACTION_SUSPEND ControlAction = 2 + ControlAction_CONTROL_ACTION_RESUME ControlAction = 3 + ControlAction_CONTROL_ACTION_ROLLBACK ControlAction = 4 + ControlAction_CONTROL_ACTION_RETIRE ControlAction = 5 +) + +// Enum value maps for ControlAction. +var ( + ControlAction_name = map[int32]string{ + 0: "CONTROL_ACTION_UNSPECIFIED", + 1: "CONTROL_ACTION_PAUSE", + 2: "CONTROL_ACTION_SUSPEND", + 3: "CONTROL_ACTION_RESUME", + 4: "CONTROL_ACTION_ROLLBACK", + 5: "CONTROL_ACTION_RETIRE", + } + ControlAction_value = map[string]int32{ + "CONTROL_ACTION_UNSPECIFIED": 0, + "CONTROL_ACTION_PAUSE": 1, + "CONTROL_ACTION_SUSPEND": 2, + "CONTROL_ACTION_RESUME": 3, + "CONTROL_ACTION_ROLLBACK": 4, + "CONTROL_ACTION_RETIRE": 5, + } +) + +func (x ControlAction) Enum() *ControlAction { + p := new(ControlAction) + *p = x + return p +} + +func (x ControlAction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ControlAction) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_v1_operator_proto_enumTypes[0].Descriptor() +} + +func (ControlAction) Type() protoreflect.EnumType { + return &file_xtcp_treatment_v1_operator_proto_enumTypes[0] +} + +func (x ControlAction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ControlAction.Descriptor instead. +func (ControlAction) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{0} +} + +type ProposeRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Experiment *Experiment `protobuf:"bytes,1,opt,name=experiment,proto3" json:"experiment,omitempty"` + RequestId string `protobuf:"bytes,2,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProposeRequest) Reset() { + *x = ProposeRequest{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProposeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProposeRequest) ProtoMessage() {} + +func (x *ProposeRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProposeRequest.ProtoReflect.Descriptor instead. +func (*ProposeRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{0} +} + +func (x *ProposeRequest) GetExperiment() *Experiment { + if x != nil { + return x.Experiment + } + return nil +} + +func (x *ProposeRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +type ProposeResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Experiment *Experiment `protobuf:"bytes,1,opt,name=experiment,proto3" json:"experiment,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProposeResponse) Reset() { + *x = ProposeResponse{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProposeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProposeResponse) ProtoMessage() {} + +func (x *ProposeResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProposeResponse.ProtoReflect.Descriptor instead. +func (*ProposeResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{1} +} + +func (x *ProposeResponse) GetExperiment() *Experiment { + if x != nil { + return x.Experiment + } + return nil +} + +type AnalyzeRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExperimentId string `protobuf:"bytes,1,opt,name=experiment_id,json=experimentId,proto3" json:"experiment_id,omitempty"` + ExpectedRevision uint64 `protobuf:"varint,2,opt,name=expected_revision,json=expectedRevision,proto3" json:"expected_revision,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AnalyzeRequest) Reset() { + *x = AnalyzeRequest{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AnalyzeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnalyzeRequest) ProtoMessage() {} + +func (x *AnalyzeRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnalyzeRequest.ProtoReflect.Descriptor instead. +func (*AnalyzeRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{2} +} + +func (x *AnalyzeRequest) GetExperimentId() string { + if x != nil { + return x.ExperimentId + } + return "" +} + +func (x *AnalyzeRequest) GetExpectedRevision() uint64 { + if x != nil { + return x.ExpectedRevision + } + return 0 +} + +type AnalyzeResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Evidence *Evidence `protobuf:"bytes,1,opt,name=evidence,proto3" json:"evidence,omitempty"` + Outcome Outcome `protobuf:"varint,2,opt,name=outcome,proto3,enum=xtcp_treatment.v1.Outcome" json:"outcome,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AnalyzeResponse) Reset() { + *x = AnalyzeResponse{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AnalyzeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnalyzeResponse) ProtoMessage() {} + +func (x *AnalyzeResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnalyzeResponse.ProtoReflect.Descriptor instead. +func (*AnalyzeResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{3} +} + +func (x *AnalyzeResponse) GetEvidence() *Evidence { + if x != nil { + return x.Evidence + } + return nil +} + +func (x *AnalyzeResponse) GetOutcome() Outcome { + if x != nil { + return x.Outcome + } + return Outcome_OUTCOME_UNSPECIFIED +} + +type ReviewRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExperimentId string `protobuf:"bytes,1,opt,name=experiment_id,json=experimentId,proto3" json:"experiment_id,omitempty"` + ExpectedRevision uint64 `protobuf:"varint,2,opt,name=expected_revision,json=expectedRevision,proto3" json:"expected_revision,omitempty"` + Approve bool `protobuf:"varint,3,opt,name=approve,proto3" json:"approve,omitempty"` + Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` + RequestId string `protobuf:"bytes,5,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + // Initial review uses baseline; subsequent reviews require fresh evidence. + Evidence *Evidence `protobuf:"bytes,6,opt,name=evidence,proto3" json:"evidence,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReviewRequest) Reset() { + *x = ReviewRequest{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReviewRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReviewRequest) ProtoMessage() {} + +func (x *ReviewRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReviewRequest.ProtoReflect.Descriptor instead. +func (*ReviewRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{4} +} + +func (x *ReviewRequest) GetExperimentId() string { + if x != nil { + return x.ExperimentId + } + return "" +} + +func (x *ReviewRequest) GetExpectedRevision() uint64 { + if x != nil { + return x.ExpectedRevision + } + return 0 +} + +func (x *ReviewRequest) GetApprove() bool { + if x != nil { + return x.Approve + } + return false +} + +func (x *ReviewRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *ReviewRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *ReviewRequest) GetEvidence() *Evidence { + if x != nil { + return x.Evidence + } + return nil +} + +type ReviewResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Experiment *Experiment `protobuf:"bytes,1,opt,name=experiment,proto3" json:"experiment,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReviewResponse) Reset() { + *x = ReviewResponse{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReviewResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReviewResponse) ProtoMessage() {} + +func (x *ReviewResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReviewResponse.ProtoReflect.Descriptor instead. +func (*ReviewResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{5} +} + +func (x *ReviewResponse) GetExperiment() *Experiment { + if x != nil { + return x.Experiment + } + return nil +} + +type ControlRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExperimentId string `protobuf:"bytes,1,opt,name=experiment_id,json=experimentId,proto3" json:"experiment_id,omitempty"` + AgentId string `protobuf:"bytes,2,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + Location string `protobuf:"bytes,3,opt,name=location,proto3" json:"location,omitempty"` + Fleet bool `protobuf:"varint,4,opt,name=fleet,proto3" json:"fleet,omitempty"` + Action ControlAction `protobuf:"varint,5,opt,name=action,proto3,enum=xtcp_treatment.v1.ControlAction" json:"action,omitempty"` + Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + RequestId string `protobuf:"bytes,7,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ControlRequest) Reset() { + *x = ControlRequest{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ControlRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ControlRequest) ProtoMessage() {} + +func (x *ControlRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ControlRequest.ProtoReflect.Descriptor instead. +func (*ControlRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{6} +} + +func (x *ControlRequest) GetExperimentId() string { + if x != nil { + return x.ExperimentId + } + return "" +} + +func (x *ControlRequest) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +func (x *ControlRequest) GetLocation() string { + if x != nil { + return x.Location + } + return "" +} + +func (x *ControlRequest) GetFleet() bool { + if x != nil { + return x.Fleet + } + return false +} + +func (x *ControlRequest) GetAction() ControlAction { + if x != nil { + return x.Action + } + return ControlAction_CONTROL_ACTION_UNSPECIFIED +} + +func (x *ControlRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *ControlRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +type ControlResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + AffectedAgents uint32 `protobuf:"varint,1,opt,name=affected_agents,json=affectedAgents,proto3" json:"affected_agents,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ControlResponse) Reset() { + *x = ControlResponse{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ControlResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ControlResponse) ProtoMessage() {} + +func (x *ControlResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ControlResponse.ProtoReflect.Descriptor instead. +func (*ControlResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{7} +} + +func (x *ControlResponse) GetAffectedAgents() uint32 { + if x != nil { + return x.AffectedAgents + } + return 0 +} + +type InspectRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExperimentId string `protobuf:"bytes,1,opt,name=experiment_id,json=experimentId,proto3" json:"experiment_id,omitempty"` + AgentId string `protobuf:"bytes,2,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InspectRequest) Reset() { + *x = InspectRequest{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InspectRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InspectRequest) ProtoMessage() {} + +func (x *InspectRequest) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InspectRequest.ProtoReflect.Descriptor instead. +func (*InspectRequest) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{8} +} + +func (x *InspectRequest) GetExperimentId() string { + if x != nil { + return x.ExperimentId + } + return "" +} + +func (x *InspectRequest) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +type InspectResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Experiments []*Experiment `protobuf:"bytes,1,rep,name=experiments,proto3" json:"experiments,omitempty"` + Desired []*DesiredState `protobuf:"bytes,2,rep,name=desired,proto3" json:"desired,omitempty"` + Observed []*CheckInRequest `protobuf:"bytes,3,rep,name=observed,proto3" json:"observed,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InspectResponse) Reset() { + *x = InspectResponse{} + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InspectResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InspectResponse) ProtoMessage() {} + +func (x *InspectResponse) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_operator_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InspectResponse.ProtoReflect.Descriptor instead. +func (*InspectResponse) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_operator_proto_rawDescGZIP(), []int{9} +} + +func (x *InspectResponse) GetExperiments() []*Experiment { + if x != nil { + return x.Experiments + } + return nil +} + +func (x *InspectResponse) GetDesired() []*DesiredState { + if x != nil { + return x.Desired + } + return nil +} + +func (x *InspectResponse) GetObserved() []*CheckInRequest { + if x != nil { + return x.Observed + } + return nil +} + +var File_xtcp_treatment_v1_operator_proto protoreflect.FileDescriptor + +const file_xtcp_treatment_v1_operator_proto_rawDesc = "" + + "\n" + + " xtcp_treatment/v1/operator.proto\x12\x11xtcp_treatment.v1\x1a\x1bbuf/validate/validate.proto\x1a\x1dxtcp_treatment/v1/agent.proto\x1a!xtcp_treatment/v1/treatment.proto\"\xbb\x02\n" + + "\x0eProposeRequest\x12E\n" + + "\n" + + "experiment\x18\x01 \x01(\v2\x1d.xtcp_treatment.v1.ExperimentB\x06\xbaH\x03\xc8\x01\x01R\n" + + "experiment\x12H\n" + + "\n" + + "request_id\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\trequestId:\x97\x01\xbaH\x93\x01\x1a\x90\x01\n" + + "\x19propose.request_id_suffix\x12Mrequest_id must not end with .result (reserved for the paired response event)\x1a$!this.request_id.endsWith('.result')\"P\n" + + "\x0fProposeResponse\x12=\n" + + "\n" + + "experiment\x18\x01 \x01(\v2\x1d.xtcp_treatment.v1.ExperimentR\n" + + "experiment\"\x8d\x01\n" + + "\x0eAnalyzeRequest\x12N\n" + + "\rexperiment_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\fexperimentId\x12+\n" + + "\x11expected_revision\x18\x02 \x01(\x04R\x10expectedRevision\"\x80\x01\n" + + "\x0fAnalyzeResponse\x127\n" + + "\bevidence\x18\x01 \x01(\v2\x1b.xtcp_treatment.v1.EvidenceR\bevidence\x124\n" + + "\aoutcome\x18\x02 \x01(\x0e2\x1a.xtcp_treatment.v1.OutcomeR\aoutcome\"\xe6\x03\n" + + "\rReviewRequest\x12N\n" + + "\rexperiment_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\fexperimentId\x12+\n" + + "\x11expected_revision\x18\x02 \x01(\x04R\x10expectedRevision\x12\x18\n" + + "\aapprove\x18\x03 \x01(\bR\aapprove\x12\"\n" + + "\x06reason\x18\x04 \x01(\tB\n" + + "\xbaH\ar\x05\x10\x01\x18\x80 R\x06reason\x12H\n" + + "\n" + + "request_id\x18\x05 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\trequestId\x127\n" + + "\bevidence\x18\x06 \x01(\v2\x1b.xtcp_treatment.v1.EvidenceR\bevidence:\x96\x01\xbaH\x92\x01\x1a\x8f\x01\n" + + "\x18review.request_id_suffix\x12Mrequest_id must not end with .result (reserved for the paired response event)\x1a$!this.request_id.endsWith('.result')\"O\n" + + "\x0eReviewResponse\x12=\n" + + "\n" + + "experiment\x18\x01 \x01(\v2\x1d.xtcp_treatment.v1.ExperimentR\n" + + "experiment\"\xba\x06\n" + + "\x0eControlRequest\x12Q\n" + + "\rexperiment_id\x18\x01 \x01(\tB,\xbaH)\xd8\x01\x01r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\fexperimentId\x12G\n" + + "\bagent_id\x18\x02 \x01(\tB,\xbaH)\xd8\x01\x01r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\aagentId\x12H\n" + + "\blocation\x18\x03 \x01(\tB,\xbaH)\xd8\x01\x01r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\blocation\x12\x14\n" + + "\x05fleet\x18\x04 \x01(\bR\x05fleet\x12D\n" + + "\x06action\x18\x05 \x01(\x0e2 .xtcp_treatment.v1.ControlActionB\n" + + "\xbaH\a\x82\x01\x04\x10\x01 \x00R\x06action\x12\"\n" + + "\x06reason\x18\x06 \x01(\tB\n" + + "\xbaH\ar\x05\x10\x01\x18\x80 R\x06reason\x12H\n" + + "\n" + + "request_id\x18\a \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\trequestId:\xf7\x02\xbaH\xf3\x02\x1a\x90\x01\n" + + "\x19control.request_id_suffix\x12Mrequest_id must not end with .result (reserved for the paired response event)\x1a$!this.request_id.endsWith('.result')\x1a\xdd\x01\n" + + "\x14control.one_selector\x12Eexactly one of experiment_id, agent_id, location or fleet is required\x1a~(this.fleet ? 1 : 0) + (this.experiment_id != '' ? 1 : 0) + (this.agent_id != '' ? 1 : 0) + (this.location != '' ? 1 : 0) == 1\":\n" + + "\x0fControlResponse\x12'\n" + + "\x0faffected_agents\x18\x01 \x01(\rR\x0eaffectedAgents\"\xac\x01\n" + + "\x0eInspectRequest\x12Q\n" + + "\rexperiment_id\x18\x01 \x01(\tB,\xbaH)\xd8\x01\x01r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\fexperimentId\x12G\n" + + "\bagent_id\x18\x02 \x01(\tB,\xbaH)\xd8\x01\x01r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\aagentId\"\xcc\x01\n" + + "\x0fInspectResponse\x12?\n" + + "\vexperiments\x18\x01 \x03(\v2\x1d.xtcp_treatment.v1.ExperimentR\vexperiments\x129\n" + + "\adesired\x18\x02 \x03(\v2\x1f.xtcp_treatment.v1.DesiredStateR\adesired\x12=\n" + + "\bobserved\x18\x03 \x03(\v2!.xtcp_treatment.v1.CheckInRequestR\bobserved*\xb8\x01\n" + + "\rControlAction\x12\x1e\n" + + "\x1aCONTROL_ACTION_UNSPECIFIED\x10\x00\x12\x18\n" + + "\x14CONTROL_ACTION_PAUSE\x10\x01\x12\x1a\n" + + "\x16CONTROL_ACTION_SUSPEND\x10\x02\x12\x19\n" + + "\x15CONTROL_ACTION_RESUME\x10\x03\x12\x1b\n" + + "\x17CONTROL_ACTION_ROLLBACK\x10\x04\x12\x19\n" + + "\x15CONTROL_ACTION_RETIRE\x10\x052\xc6\x03\n" + + "\x0fOperatorService\x12V\n" + + "\aPropose\x12!.xtcp_treatment.v1.ProposeRequest\x1a\".xtcp_treatment.v1.ProposeResponse\"\x04\xd0\xf3\x18\x02\x12V\n" + + "\aAnalyze\x12!.xtcp_treatment.v1.AnalyzeRequest\x1a\".xtcp_treatment.v1.AnalyzeResponse\"\x04\xd0\xf3\x18\x02\x12S\n" + + "\x06Review\x12 .xtcp_treatment.v1.ReviewRequest\x1a!.xtcp_treatment.v1.ReviewResponse\"\x04\xd0\xf3\x18\x02\x12V\n" + + "\aControl\x12!.xtcp_treatment.v1.ControlRequest\x1a\".xtcp_treatment.v1.ControlResponse\"\x04\xd0\xf3\x18\x02\x12V\n" + + "\aInspect\x12!.xtcp_treatment.v1.InspectRequest\x1a\".xtcp_treatment.v1.InspectResponse\"\x04\xd0\xf3\x18\x02B\xbf\x01\n" + + "\x15com.xtcp_treatment.v1B\rOperatorProtoP\x01Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\xa2\x02\x03XXX\xaa\x02\x10XtcpTreatment.V1\xca\x02\x10XtcpTreatment\\V1\xe2\x02\x1cXtcpTreatment\\V1\\GPBMetadata\xea\x02\x11XtcpTreatment::V1b\x06proto3" + +var ( + file_xtcp_treatment_v1_operator_proto_rawDescOnce sync.Once + file_xtcp_treatment_v1_operator_proto_rawDescData []byte +) + +func file_xtcp_treatment_v1_operator_proto_rawDescGZIP() []byte { + file_xtcp_treatment_v1_operator_proto_rawDescOnce.Do(func() { + file_xtcp_treatment_v1_operator_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_xtcp_treatment_v1_operator_proto_rawDesc), len(file_xtcp_treatment_v1_operator_proto_rawDesc))) + }) + return file_xtcp_treatment_v1_operator_proto_rawDescData +} + +var file_xtcp_treatment_v1_operator_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_xtcp_treatment_v1_operator_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_xtcp_treatment_v1_operator_proto_goTypes = []any{ + (ControlAction)(0), // 0: xtcp_treatment.v1.ControlAction + (*ProposeRequest)(nil), // 1: xtcp_treatment.v1.ProposeRequest + (*ProposeResponse)(nil), // 2: xtcp_treatment.v1.ProposeResponse + (*AnalyzeRequest)(nil), // 3: xtcp_treatment.v1.AnalyzeRequest + (*AnalyzeResponse)(nil), // 4: xtcp_treatment.v1.AnalyzeResponse + (*ReviewRequest)(nil), // 5: xtcp_treatment.v1.ReviewRequest + (*ReviewResponse)(nil), // 6: xtcp_treatment.v1.ReviewResponse + (*ControlRequest)(nil), // 7: xtcp_treatment.v1.ControlRequest + (*ControlResponse)(nil), // 8: xtcp_treatment.v1.ControlResponse + (*InspectRequest)(nil), // 9: xtcp_treatment.v1.InspectRequest + (*InspectResponse)(nil), // 10: xtcp_treatment.v1.InspectResponse + (*Experiment)(nil), // 11: xtcp_treatment.v1.Experiment + (*Evidence)(nil), // 12: xtcp_treatment.v1.Evidence + (Outcome)(0), // 13: xtcp_treatment.v1.Outcome + (*DesiredState)(nil), // 14: xtcp_treatment.v1.DesiredState + (*CheckInRequest)(nil), // 15: xtcp_treatment.v1.CheckInRequest +} +var file_xtcp_treatment_v1_operator_proto_depIdxs = []int32{ + 11, // 0: xtcp_treatment.v1.ProposeRequest.experiment:type_name -> xtcp_treatment.v1.Experiment + 11, // 1: xtcp_treatment.v1.ProposeResponse.experiment:type_name -> xtcp_treatment.v1.Experiment + 12, // 2: xtcp_treatment.v1.AnalyzeResponse.evidence:type_name -> xtcp_treatment.v1.Evidence + 13, // 3: xtcp_treatment.v1.AnalyzeResponse.outcome:type_name -> xtcp_treatment.v1.Outcome + 12, // 4: xtcp_treatment.v1.ReviewRequest.evidence:type_name -> xtcp_treatment.v1.Evidence + 11, // 5: xtcp_treatment.v1.ReviewResponse.experiment:type_name -> xtcp_treatment.v1.Experiment + 0, // 6: xtcp_treatment.v1.ControlRequest.action:type_name -> xtcp_treatment.v1.ControlAction + 11, // 7: xtcp_treatment.v1.InspectResponse.experiments:type_name -> xtcp_treatment.v1.Experiment + 14, // 8: xtcp_treatment.v1.InspectResponse.desired:type_name -> xtcp_treatment.v1.DesiredState + 15, // 9: xtcp_treatment.v1.InspectResponse.observed:type_name -> xtcp_treatment.v1.CheckInRequest + 1, // 10: xtcp_treatment.v1.OperatorService.Propose:input_type -> xtcp_treatment.v1.ProposeRequest + 3, // 11: xtcp_treatment.v1.OperatorService.Analyze:input_type -> xtcp_treatment.v1.AnalyzeRequest + 5, // 12: xtcp_treatment.v1.OperatorService.Review:input_type -> xtcp_treatment.v1.ReviewRequest + 7, // 13: xtcp_treatment.v1.OperatorService.Control:input_type -> xtcp_treatment.v1.ControlRequest + 9, // 14: xtcp_treatment.v1.OperatorService.Inspect:input_type -> xtcp_treatment.v1.InspectRequest + 2, // 15: xtcp_treatment.v1.OperatorService.Propose:output_type -> xtcp_treatment.v1.ProposeResponse + 4, // 16: xtcp_treatment.v1.OperatorService.Analyze:output_type -> xtcp_treatment.v1.AnalyzeResponse + 6, // 17: xtcp_treatment.v1.OperatorService.Review:output_type -> xtcp_treatment.v1.ReviewResponse + 8, // 18: xtcp_treatment.v1.OperatorService.Control:output_type -> xtcp_treatment.v1.ControlResponse + 10, // 19: xtcp_treatment.v1.OperatorService.Inspect:output_type -> xtcp_treatment.v1.InspectResponse + 15, // [15:20] is the sub-list for method output_type + 10, // [10:15] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name +} + +func init() { file_xtcp_treatment_v1_operator_proto_init() } +func file_xtcp_treatment_v1_operator_proto_init() { + if File_xtcp_treatment_v1_operator_proto != nil { + return + } + file_xtcp_treatment_v1_agent_proto_init() + file_xtcp_treatment_v1_treatment_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_xtcp_treatment_v1_operator_proto_rawDesc), len(file_xtcp_treatment_v1_operator_proto_rawDesc)), + NumEnums: 1, + NumMessages: 10, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_xtcp_treatment_v1_operator_proto_goTypes, + DependencyIndexes: file_xtcp_treatment_v1_operator_proto_depIdxs, + EnumInfos: file_xtcp_treatment_v1_operator_proto_enumTypes, + MessageInfos: file_xtcp_treatment_v1_operator_proto_msgTypes, + }.Build() + File_xtcp_treatment_v1_operator_proto = out.File + file_xtcp_treatment_v1_operator_proto_goTypes = nil + file_xtcp_treatment_v1_operator_proto_depIdxs = nil +} diff --git a/gen/go/xtcp_treatment/operator.pb.gw.go b/gen/go/xtcp_treatment/operator.pb.gw.go new file mode 100644 index 000000000..7da6d7302 --- /dev/null +++ b/gen/go/xtcp_treatment/operator.pb.gw.go @@ -0,0 +1,421 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: xtcp_treatment/v1/operator.proto + +/* +Package xtcp_treatment is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package xtcp_treatment + +import ( + "context" + "errors" + "io" + "net/http" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// Suppress "imported and not used" errors +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) + +func request_OperatorService_Propose_0(ctx context.Context, marshaler runtime.Marshaler, client OperatorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ProposeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.Propose(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_OperatorService_Propose_0(ctx context.Context, marshaler runtime.Marshaler, server OperatorServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ProposeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Propose(ctx, &protoReq) + return msg, metadata, err +} + +func request_OperatorService_Analyze_0(ctx context.Context, marshaler runtime.Marshaler, client OperatorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq AnalyzeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.Analyze(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_OperatorService_Analyze_0(ctx context.Context, marshaler runtime.Marshaler, server OperatorServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq AnalyzeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Analyze(ctx, &protoReq) + return msg, metadata, err +} + +func request_OperatorService_Review_0(ctx context.Context, marshaler runtime.Marshaler, client OperatorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ReviewRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.Review(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_OperatorService_Review_0(ctx context.Context, marshaler runtime.Marshaler, server OperatorServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ReviewRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Review(ctx, &protoReq) + return msg, metadata, err +} + +func request_OperatorService_Control_0(ctx context.Context, marshaler runtime.Marshaler, client OperatorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ControlRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.Control(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_OperatorService_Control_0(ctx context.Context, marshaler runtime.Marshaler, server OperatorServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq ControlRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Control(ctx, &protoReq) + return msg, metadata, err +} + +func request_OperatorService_Inspect_0(ctx context.Context, marshaler runtime.Marshaler, client OperatorServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq InspectRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.Inspect(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_OperatorService_Inspect_0(ctx context.Context, marshaler runtime.Marshaler, server OperatorServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq InspectRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Inspect(ctx, &protoReq) + return msg, metadata, err +} + +// RegisterOperatorServiceHandlerServer registers the http handlers for service OperatorService to "mux". +// UnaryRPC :call OperatorServiceServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterOperatorServiceHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. +func RegisterOperatorServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server OperatorServiceServer) error { + mux.Handle(http.MethodPost, pattern_OperatorService_Propose_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Propose", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Propose")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_OperatorService_Propose_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Propose_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Analyze_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Analyze", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Analyze")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_OperatorService_Analyze_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Analyze_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Review_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Review", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Review")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_OperatorService_Review_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Review_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Control_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Control", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Control")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_OperatorService_Control_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Control_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Inspect_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Inspect", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Inspect")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_OperatorService_Inspect_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Inspect_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + + return nil +} + +// RegisterOperatorServiceHandlerFromEndpoint is same as RegisterOperatorServiceHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterOperatorServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.NewClient(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + return RegisterOperatorServiceHandler(ctx, mux, conn) +} + +// RegisterOperatorServiceHandler registers the http handlers for service OperatorService to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterOperatorServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterOperatorServiceHandlerClient(ctx, mux, NewOperatorServiceClient(conn)) +} + +// RegisterOperatorServiceHandlerClient registers the http handlers for service OperatorService +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "OperatorServiceClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "OperatorServiceClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "OperatorServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares. +func RegisterOperatorServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client OperatorServiceClient) error { + mux.Handle(http.MethodPost, pattern_OperatorService_Propose_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Propose", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Propose")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_OperatorService_Propose_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Propose_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Analyze_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Analyze", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Analyze")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_OperatorService_Analyze_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Analyze_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Review_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Review", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Review")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_OperatorService_Review_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Review_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Control_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Control", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Control")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_OperatorService_Control_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Control_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_OperatorService_Inspect_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/xtcp_treatment.v1.OperatorService/Inspect", runtime.WithHTTPPathPattern("/xtcp_treatment.v1.OperatorService/Inspect")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_OperatorService_Inspect_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_OperatorService_Inspect_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + return nil +} + +var ( + pattern_OperatorService_Propose_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.OperatorService", "Propose"}, "")) + pattern_OperatorService_Analyze_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.OperatorService", "Analyze"}, "")) + pattern_OperatorService_Review_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.OperatorService", "Review"}, "")) + pattern_OperatorService_Control_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.OperatorService", "Control"}, "")) + pattern_OperatorService_Inspect_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"xtcp_treatment.v1.OperatorService", "Inspect"}, "")) +) + +var ( + forward_OperatorService_Propose_0 = runtime.ForwardResponseMessage + forward_OperatorService_Analyze_0 = runtime.ForwardResponseMessage + forward_OperatorService_Review_0 = runtime.ForwardResponseMessage + forward_OperatorService_Control_0 = runtime.ForwardResponseMessage + forward_OperatorService_Inspect_0 = runtime.ForwardResponseMessage +) diff --git a/gen/go/xtcp_treatment/operator_grpc.pb.go b/gen/go/xtcp_treatment/operator_grpc.pb.go new file mode 100644 index 000000000..ef9606a04 --- /dev/null +++ b/gen/go/xtcp_treatment/operator_grpc.pb.go @@ -0,0 +1,281 @@ +// +// xTCP - treatment operator service +// +// The authenticated review surface. Every mutation carries a request_id; +// repeating one with the same body replays the original response, repeating +// it with a different body is refused. Reviews also fence on the experiment +// revision the operator last saw. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc (unknown) +// source: xtcp_treatment/v1/operator.proto + +package xtcp_treatment + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + OperatorService_Propose_FullMethodName = "/xtcp_treatment.v1.OperatorService/Propose" + OperatorService_Analyze_FullMethodName = "/xtcp_treatment.v1.OperatorService/Analyze" + OperatorService_Review_FullMethodName = "/xtcp_treatment.v1.OperatorService/Review" + OperatorService_Control_FullMethodName = "/xtcp_treatment.v1.OperatorService/Control" + OperatorService_Inspect_FullMethodName = "/xtcp_treatment.v1.OperatorService/Inspect" +) + +// OperatorServiceClient is the client API for OperatorService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type OperatorServiceClient interface { + Propose(ctx context.Context, in *ProposeRequest, opts ...grpc.CallOption) (*ProposeResponse, error) + Analyze(ctx context.Context, in *AnalyzeRequest, opts ...grpc.CallOption) (*AnalyzeResponse, error) + Review(ctx context.Context, in *ReviewRequest, opts ...grpc.CallOption) (*ReviewResponse, error) + Control(ctx context.Context, in *ControlRequest, opts ...grpc.CallOption) (*ControlResponse, error) + Inspect(ctx context.Context, in *InspectRequest, opts ...grpc.CallOption) (*InspectResponse, error) +} + +type operatorServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewOperatorServiceClient(cc grpc.ClientConnInterface) OperatorServiceClient { + return &operatorServiceClient{cc} +} + +func (c *operatorServiceClient) Propose(ctx context.Context, in *ProposeRequest, opts ...grpc.CallOption) (*ProposeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ProposeResponse) + err := c.cc.Invoke(ctx, OperatorService_Propose_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *operatorServiceClient) Analyze(ctx context.Context, in *AnalyzeRequest, opts ...grpc.CallOption) (*AnalyzeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AnalyzeResponse) + err := c.cc.Invoke(ctx, OperatorService_Analyze_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *operatorServiceClient) Review(ctx context.Context, in *ReviewRequest, opts ...grpc.CallOption) (*ReviewResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ReviewResponse) + err := c.cc.Invoke(ctx, OperatorService_Review_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *operatorServiceClient) Control(ctx context.Context, in *ControlRequest, opts ...grpc.CallOption) (*ControlResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ControlResponse) + err := c.cc.Invoke(ctx, OperatorService_Control_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *operatorServiceClient) Inspect(ctx context.Context, in *InspectRequest, opts ...grpc.CallOption) (*InspectResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(InspectResponse) + err := c.cc.Invoke(ctx, OperatorService_Inspect_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// OperatorServiceServer is the server API for OperatorService service. +// All implementations must embed UnimplementedOperatorServiceServer +// for forward compatibility. +type OperatorServiceServer interface { + Propose(context.Context, *ProposeRequest) (*ProposeResponse, error) + Analyze(context.Context, *AnalyzeRequest) (*AnalyzeResponse, error) + Review(context.Context, *ReviewRequest) (*ReviewResponse, error) + Control(context.Context, *ControlRequest) (*ControlResponse, error) + Inspect(context.Context, *InspectRequest) (*InspectResponse, error) + mustEmbedUnimplementedOperatorServiceServer() +} + +// UnimplementedOperatorServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedOperatorServiceServer struct{} + +func (UnimplementedOperatorServiceServer) Propose(context.Context, *ProposeRequest) (*ProposeResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Propose not implemented") +} +func (UnimplementedOperatorServiceServer) Analyze(context.Context, *AnalyzeRequest) (*AnalyzeResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Analyze not implemented") +} +func (UnimplementedOperatorServiceServer) Review(context.Context, *ReviewRequest) (*ReviewResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Review not implemented") +} +func (UnimplementedOperatorServiceServer) Control(context.Context, *ControlRequest) (*ControlResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Control not implemented") +} +func (UnimplementedOperatorServiceServer) Inspect(context.Context, *InspectRequest) (*InspectResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Inspect not implemented") +} +func (UnimplementedOperatorServiceServer) mustEmbedUnimplementedOperatorServiceServer() {} +func (UnimplementedOperatorServiceServer) testEmbeddedByValue() {} + +// UnsafeOperatorServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to OperatorServiceServer will +// result in compilation errors. +type UnsafeOperatorServiceServer interface { + mustEmbedUnimplementedOperatorServiceServer() +} + +func RegisterOperatorServiceServer(s grpc.ServiceRegistrar, srv OperatorServiceServer) { + // If the following call panics, it indicates UnimplementedOperatorServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&OperatorService_ServiceDesc, srv) +} + +func _OperatorService_Propose_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ProposeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OperatorServiceServer).Propose(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OperatorService_Propose_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OperatorServiceServer).Propose(ctx, req.(*ProposeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OperatorService_Analyze_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AnalyzeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OperatorServiceServer).Analyze(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OperatorService_Analyze_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OperatorServiceServer).Analyze(ctx, req.(*AnalyzeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OperatorService_Review_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReviewRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OperatorServiceServer).Review(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OperatorService_Review_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OperatorServiceServer).Review(ctx, req.(*ReviewRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OperatorService_Control_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ControlRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OperatorServiceServer).Control(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OperatorService_Control_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OperatorServiceServer).Control(ctx, req.(*ControlRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _OperatorService_Inspect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InspectRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(OperatorServiceServer).Inspect(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: OperatorService_Inspect_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(OperatorServiceServer).Inspect(ctx, req.(*InspectRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// OperatorService_ServiceDesc is the grpc.ServiceDesc for OperatorService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var OperatorService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "xtcp_treatment.v1.OperatorService", + HandlerType: (*OperatorServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Propose", + Handler: _OperatorService_Propose_Handler, + }, + { + MethodName: "Analyze", + Handler: _OperatorService_Analyze_Handler, + }, + { + MethodName: "Review", + Handler: _OperatorService_Review_Handler, + }, + { + MethodName: "Control", + Handler: _OperatorService_Control_Handler, + }, + { + MethodName: "Inspect", + Handler: _OperatorService_Inspect_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "xtcp_treatment/v1/operator.proto", +} diff --git a/gen/go/xtcp_treatment/operator_vtproto.pb.go b/gen/go/xtcp_treatment/operator_vtproto.pb.go new file mode 100644 index 000000000..f0811f73b --- /dev/null +++ b/gen/go/xtcp_treatment/operator_vtproto.pb.go @@ -0,0 +1,2083 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: (devel) +// source: xtcp_treatment/v1/operator.proto + +package xtcp_treatment + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *ProposeRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProposeRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ProposeRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.RequestId) > 0 { + i -= len(m.RequestId) + copy(dAtA[i:], m.RequestId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.RequestId))) + i-- + dAtA[i] = 0x12 + } + if m.Experiment != nil { + size, err := m.Experiment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ProposeResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ProposeResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ProposeResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Experiment != nil { + size, err := m.Experiment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AnalyzeRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AnalyzeRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *AnalyzeRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.ExpectedRevision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.ExpectedRevision)) + i-- + dAtA[i] = 0x10 + } + if len(m.ExperimentId) > 0 { + i -= len(m.ExperimentId) + copy(dAtA[i:], m.ExperimentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ExperimentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AnalyzeResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AnalyzeResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *AnalyzeResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Outcome != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Outcome)) + i-- + dAtA[i] = 0x10 + } + if m.Evidence != nil { + size, err := m.Evidence.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ReviewRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ReviewRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ReviewRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Evidence != nil { + size, err := m.Evidence.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + if len(m.RequestId) > 0 { + i -= len(m.RequestId) + copy(dAtA[i:], m.RequestId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.RequestId))) + i-- + dAtA[i] = 0x2a + } + if len(m.Reason) > 0 { + i -= len(m.Reason) + copy(dAtA[i:], m.Reason) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Reason))) + i-- + dAtA[i] = 0x22 + } + if m.Approve { + i-- + if m.Approve { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if m.ExpectedRevision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.ExpectedRevision)) + i-- + dAtA[i] = 0x10 + } + if len(m.ExperimentId) > 0 { + i -= len(m.ExperimentId) + copy(dAtA[i:], m.ExperimentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ExperimentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ReviewResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ReviewResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ReviewResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Experiment != nil { + size, err := m.Experiment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ControlRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ControlRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ControlRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.RequestId) > 0 { + i -= len(m.RequestId) + copy(dAtA[i:], m.RequestId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.RequestId))) + i-- + dAtA[i] = 0x3a + } + if len(m.Reason) > 0 { + i -= len(m.Reason) + copy(dAtA[i:], m.Reason) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Reason))) + i-- + dAtA[i] = 0x32 + } + if m.Action != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Action)) + i-- + dAtA[i] = 0x28 + } + if m.Fleet { + i-- + if m.Fleet { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if len(m.Location) > 0 { + i -= len(m.Location) + copy(dAtA[i:], m.Location) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Location))) + i-- + dAtA[i] = 0x1a + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0x12 + } + if len(m.ExperimentId) > 0 { + i -= len(m.ExperimentId) + copy(dAtA[i:], m.ExperimentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ExperimentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ControlResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ControlResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ControlResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.AffectedAgents != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.AffectedAgents)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *InspectRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *InspectRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *InspectRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0x12 + } + if len(m.ExperimentId) > 0 { + i -= len(m.ExperimentId) + copy(dAtA[i:], m.ExperimentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ExperimentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *InspectResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *InspectResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *InspectResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Observed) > 0 { + for iNdEx := len(m.Observed) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Observed[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Desired) > 0 { + for iNdEx := len(m.Desired) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Desired[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Experiments) > 0 { + for iNdEx := len(m.Experiments) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Experiments[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ProposeRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Experiment != nil { + l = m.Experiment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.RequestId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *ProposeResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Experiment != nil { + l = m.Experiment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *AnalyzeRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ExperimentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.ExpectedRevision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.ExpectedRevision)) + } + n += len(m.unknownFields) + return n +} + +func (m *AnalyzeResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Evidence != nil { + l = m.Evidence.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Outcome != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Outcome)) + } + n += len(m.unknownFields) + return n +} + +func (m *ReviewRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ExperimentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.ExpectedRevision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.ExpectedRevision)) + } + if m.Approve { + n += 2 + } + l = len(m.Reason) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.RequestId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Evidence != nil { + l = m.Evidence.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *ReviewResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Experiment != nil { + l = m.Experiment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *ControlRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ExperimentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Location) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Fleet { + n += 2 + } + if m.Action != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Action)) + } + l = len(m.Reason) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.RequestId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *ControlResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AffectedAgents != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.AffectedAgents)) + } + n += len(m.unknownFields) + return n +} + +func (m *InspectRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ExperimentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *InspectResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Experiments) > 0 { + for _, e := range m.Experiments { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if len(m.Desired) > 0 { + for _, e := range m.Desired { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if len(m.Observed) > 0 { + for _, e := range m.Observed { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *ProposeRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProposeRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProposeRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Experiment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Experiment == nil { + m.Experiment = &Experiment{} + } + if err := m.Experiment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RequestId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RequestId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ProposeResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ProposeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ProposeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Experiment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Experiment == nil { + m.Experiment = &Experiment{} + } + if err := m.Experiment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AnalyzeRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AnalyzeRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AnalyzeRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExperimentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExperimentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpectedRevision", wireType) + } + m.ExpectedRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ExpectedRevision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AnalyzeResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: AnalyzeResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AnalyzeResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Evidence == nil { + m.Evidence = &Evidence{} + } + if err := m.Evidence.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Outcome", wireType) + } + m.Outcome = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Outcome |= Outcome(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ReviewRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ReviewRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ReviewRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExperimentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExperimentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpectedRevision", wireType) + } + m.ExpectedRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ExpectedRevision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Approve", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Approve = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RequestId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RequestId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Evidence == nil { + m.Evidence = &Evidence{} + } + if err := m.Evidence.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ReviewResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ReviewResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ReviewResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Experiment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Experiment == nil { + m.Experiment = &Experiment{} + } + if err := m.Experiment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ControlRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ControlRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ControlRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExperimentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExperimentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Location", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Location = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Fleet", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Fleet = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Action", wireType) + } + m.Action = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Action |= ControlAction(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RequestId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RequestId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ControlResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ControlResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ControlResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AffectedAgents", wireType) + } + m.AffectedAgents = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.AffectedAgents |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *InspectRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: InspectRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: InspectRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExperimentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExperimentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *InspectResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: InspectResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: InspectResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Experiments", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Experiments = append(m.Experiments, &Experiment{}) + if err := m.Experiments[len(m.Experiments)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Desired", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Desired = append(m.Desired, &DesiredState{}) + if err := m.Desired[len(m.Desired)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Observed", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Observed = append(m.Observed, &CheckInRequest{}) + if err := m.Observed[len(m.Observed)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/gen/go/xtcp_treatment/treatment.pb.go b/gen/go/xtcp_treatment/treatment.pb.go new file mode 100644 index 000000000..8f82e4dd9 --- /dev/null +++ b/gen/go/xtcp_treatment/treatment.pb.go @@ -0,0 +1,1939 @@ +// +// xTCP - treatment +// +// Shared message types for the TCP route treatment control plane: what a +// treatment is, how it is assigned to an agent, what an agent reports back, +// and how an experiment over a cohort of agents is described and evidenced. +// +// Wire contract only. The controller and the agent work on Go domain types +// and convert at the gRPC boundary; nothing here is a storage schema. +// +// Validation: every client-controlled field carries a buf.validate rule that +// mirrors the bound in pkg/treatment/validate.go, so a malformed request is +// rejected before any handler runs. The Go validators remain authoritative +// for contextual rules that need more than one message (duplicate assignment +// IDs, overlapping destinations, cohort/baseline agreement). +// +// See docs/tcp-controller.md. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc (unknown) +// source: xtcp_treatment/v1/treatment.proto + +package xtcp_treatment + +import ( + _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + durationpb "google.golang.org/protobuf/types/known/durationpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Role is the certificate class an RPC requires. The server resolves the +// caller's SPIFFE identity once per call and compares it with this option; +// a method without a declaration is refused for everyone (fail closed). +type Role int32 + +const ( + Role_ROLE_UNSPECIFIED Role = 0 + // spiffe://xtcp/agent//; may only speak for its own agent_id. + Role_ROLE_AGENT Role = 1 + // spiffe://xtcp/operator/; recorded as the audit actor. + Role_ROLE_OPERATOR Role = 2 +) + +// Enum value maps for Role. +var ( + Role_name = map[int32]string{ + 0: "ROLE_UNSPECIFIED", + 1: "ROLE_AGENT", + 2: "ROLE_OPERATOR", + } + Role_value = map[string]int32{ + "ROLE_UNSPECIFIED": 0, + "ROLE_AGENT": 1, + "ROLE_OPERATOR": 2, + } +) + +func (x Role) Enum() *Role { + p := new(Role) + *p = x + return p +} + +func (x Role) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Role) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_v1_treatment_proto_enumTypes[0].Descriptor() +} + +func (Role) Type() protoreflect.EnumType { + return &file_xtcp_treatment_v1_treatment_proto_enumTypes[0] +} + +func (x Role) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Role.Descriptor instead. +func (Role) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{0} +} + +type AssignmentMode int32 + +const ( + AssignmentMode_ASSIGNMENT_MODE_UNSPECIFIED AssignmentMode = 0 + AssignmentMode_ASSIGNMENT_MODE_TRIAL AssignmentMode = 1 + AssignmentMode_ASSIGNMENT_MODE_STABLE AssignmentMode = 2 + AssignmentMode_ASSIGNMENT_MODE_SUSPENDED AssignmentMode = 3 + AssignmentMode_ASSIGNMENT_MODE_RETIRED AssignmentMode = 4 +) + +// Enum value maps for AssignmentMode. +var ( + AssignmentMode_name = map[int32]string{ + 0: "ASSIGNMENT_MODE_UNSPECIFIED", + 1: "ASSIGNMENT_MODE_TRIAL", + 2: "ASSIGNMENT_MODE_STABLE", + 3: "ASSIGNMENT_MODE_SUSPENDED", + 4: "ASSIGNMENT_MODE_RETIRED", + } + AssignmentMode_value = map[string]int32{ + "ASSIGNMENT_MODE_UNSPECIFIED": 0, + "ASSIGNMENT_MODE_TRIAL": 1, + "ASSIGNMENT_MODE_STABLE": 2, + "ASSIGNMENT_MODE_SUSPENDED": 3, + "ASSIGNMENT_MODE_RETIRED": 4, + } +) + +func (x AssignmentMode) Enum() *AssignmentMode { + p := new(AssignmentMode) + *p = x + return p +} + +func (x AssignmentMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AssignmentMode) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_v1_treatment_proto_enumTypes[1].Descriptor() +} + +func (AssignmentMode) Type() protoreflect.EnumType { + return &file_xtcp_treatment_v1_treatment_proto_enumTypes[1] +} + +func (x AssignmentMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AssignmentMode.Descriptor instead. +func (AssignmentMode) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{1} +} + +type ApplyStatus int32 + +const ( + ApplyStatus_APPLY_STATUS_UNSPECIFIED ApplyStatus = 0 + ApplyStatus_APPLY_STATUS_PENDING ApplyStatus = 1 + ApplyStatus_APPLY_STATUS_VERIFIED ApplyStatus = 2 + ApplyStatus_APPLY_STATUS_REMOVED ApplyStatus = 3 + ApplyStatus_APPLY_STATUS_EXPIRED ApplyStatus = 4 + ApplyStatus_APPLY_STATUS_FAILED ApplyStatus = 5 +) + +// Enum value maps for ApplyStatus. +var ( + ApplyStatus_name = map[int32]string{ + 0: "APPLY_STATUS_UNSPECIFIED", + 1: "APPLY_STATUS_PENDING", + 2: "APPLY_STATUS_VERIFIED", + 3: "APPLY_STATUS_REMOVED", + 4: "APPLY_STATUS_EXPIRED", + 5: "APPLY_STATUS_FAILED", + } + ApplyStatus_value = map[string]int32{ + "APPLY_STATUS_UNSPECIFIED": 0, + "APPLY_STATUS_PENDING": 1, + "APPLY_STATUS_VERIFIED": 2, + "APPLY_STATUS_REMOVED": 3, + "APPLY_STATUS_EXPIRED": 4, + "APPLY_STATUS_FAILED": 5, + } +) + +func (x ApplyStatus) Enum() *ApplyStatus { + p := new(ApplyStatus) + *p = x + return p +} + +func (x ApplyStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ApplyStatus) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_v1_treatment_proto_enumTypes[2].Descriptor() +} + +func (ApplyStatus) Type() protoreflect.EnumType { + return &file_xtcp_treatment_v1_treatment_proto_enumTypes[2] +} + +func (x ApplyStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ApplyStatus.Descriptor instead. +func (ApplyStatus) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{2} +} + +// Outcome is the result of evaluating one evidence window against a phase, +// or the standing of a completed treatment under drift monitoring. Only +// BENEFICIAL, SAFETY_ONLY and FINAL_SAFETY can advance a phase, and only +// after an operator review; HARMFUL and EXPIRED withdraw automatically. +type Outcome int32 + +const ( + Outcome_OUTCOME_UNSPECIFIED Outcome = 0 + // Analysis of a proposal that has no phase yet. + Outcome_OUTCOME_BASELINE Outcome = 1 + // Not every treated host has verified the assignment. + Outcome_OUTCOME_AWAITING_APPLICATION Outcome = 2 + // Treated hosts have not yet carried enough exposed sockets. + Outcome_OUTCOME_AWAITING_EXPOSURE Outcome = 3 + Outcome_OUTCOME_INSUFFICIENT_DURATION Outcome = 4 + Outcome_OUTCOME_INSUFFICIENT_DATA Outcome = 5 + Outcome_OUTCOME_INSUFFICIENT_CONTROLS Outcome = 6 + Outcome_OUTCOME_STALE Outcome = 7 + // No evidence source was available for this maintenance pass. + Outcome_OUTCOME_UNAVAILABLE Outcome = 8 + Outcome_OUTCOME_INCONCLUSIVE Outcome = 9 + // Cohort too small for a causal estimate; no regression observed. + Outcome_OUTCOME_SAFETY_ONLY Outcome = 10 + // Final 100% phase: no controls remain; no regression observed. + Outcome_OUTCOME_FINAL_SAFETY Outcome = 11 + Outcome_OUTCOME_BENEFICIAL Outcome = 12 + Outcome_OUTCOME_HARMFUL Outcome = 13 + Outcome_OUTCOME_EXPIRED Outcome = 14 + // Completed treatment under drift monitoring. + Outcome_OUTCOME_STABLE_OBSERVED Outcome = 15 + Outcome_OUTCOME_STABLE_EVIDENCE_INCOMPLETE Outcome = 16 + Outcome_OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED Outcome = 17 + // Every treated host has verified the assignment; the observation window + // is open and no evidence has been evaluated yet. + Outcome_OUTCOME_OBSERVING Outcome = 18 +) + +// Enum value maps for Outcome. +var ( + Outcome_name = map[int32]string{ + 0: "OUTCOME_UNSPECIFIED", + 1: "OUTCOME_BASELINE", + 2: "OUTCOME_AWAITING_APPLICATION", + 3: "OUTCOME_AWAITING_EXPOSURE", + 4: "OUTCOME_INSUFFICIENT_DURATION", + 5: "OUTCOME_INSUFFICIENT_DATA", + 6: "OUTCOME_INSUFFICIENT_CONTROLS", + 7: "OUTCOME_STALE", + 8: "OUTCOME_UNAVAILABLE", + 9: "OUTCOME_INCONCLUSIVE", + 10: "OUTCOME_SAFETY_ONLY", + 11: "OUTCOME_FINAL_SAFETY", + 12: "OUTCOME_BENEFICIAL", + 13: "OUTCOME_HARMFUL", + 14: "OUTCOME_EXPIRED", + 15: "OUTCOME_STABLE_OBSERVED", + 16: "OUTCOME_STABLE_EVIDENCE_INCOMPLETE", + 17: "OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED", + 18: "OUTCOME_OBSERVING", + } + Outcome_value = map[string]int32{ + "OUTCOME_UNSPECIFIED": 0, + "OUTCOME_BASELINE": 1, + "OUTCOME_AWAITING_APPLICATION": 2, + "OUTCOME_AWAITING_EXPOSURE": 3, + "OUTCOME_INSUFFICIENT_DURATION": 4, + "OUTCOME_INSUFFICIENT_DATA": 5, + "OUTCOME_INSUFFICIENT_CONTROLS": 6, + "OUTCOME_STALE": 7, + "OUTCOME_UNAVAILABLE": 8, + "OUTCOME_INCONCLUSIVE": 9, + "OUTCOME_SAFETY_ONLY": 10, + "OUTCOME_FINAL_SAFETY": 11, + "OUTCOME_BENEFICIAL": 12, + "OUTCOME_HARMFUL": 13, + "OUTCOME_EXPIRED": 14, + "OUTCOME_STABLE_OBSERVED": 15, + "OUTCOME_STABLE_EVIDENCE_INCOMPLETE": 16, + "OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED": 17, + "OUTCOME_OBSERVING": 18, + } +) + +func (x Outcome) Enum() *Outcome { + p := new(Outcome) + *p = x + return p +} + +func (x Outcome) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Outcome) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_v1_treatment_proto_enumTypes[3].Descriptor() +} + +func (Outcome) Type() protoreflect.EnumType { + return &file_xtcp_treatment_v1_treatment_proto_enumTypes[3] +} + +func (x Outcome) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Outcome.Descriptor instead. +func (Outcome) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{3} +} + +type ExperimentStatus int32 + +const ( + ExperimentStatus_EXPERIMENT_STATUS_UNSPECIFIED ExperimentStatus = 0 + ExperimentStatus_EXPERIMENT_STATUS_PROPOSED ExperimentStatus = 1 + ExperimentStatus_EXPERIMENT_STATUS_RUNNING ExperimentStatus = 2 + ExperimentStatus_EXPERIMENT_STATUS_PAUSED ExperimentStatus = 3 + ExperimentStatus_EXPERIMENT_STATUS_SUSPENDED ExperimentStatus = 4 + ExperimentStatus_EXPERIMENT_STATUS_COMPLETE ExperimentStatus = 5 + ExperimentStatus_EXPERIMENT_STATUS_RETIRED ExperimentStatus = 6 + ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK ExperimentStatus = 7 +) + +// Enum value maps for ExperimentStatus. +var ( + ExperimentStatus_name = map[int32]string{ + 0: "EXPERIMENT_STATUS_UNSPECIFIED", + 1: "EXPERIMENT_STATUS_PROPOSED", + 2: "EXPERIMENT_STATUS_RUNNING", + 3: "EXPERIMENT_STATUS_PAUSED", + 4: "EXPERIMENT_STATUS_SUSPENDED", + 5: "EXPERIMENT_STATUS_COMPLETE", + 6: "EXPERIMENT_STATUS_RETIRED", + 7: "EXPERIMENT_STATUS_ROLLED_BACK", + } + ExperimentStatus_value = map[string]int32{ + "EXPERIMENT_STATUS_UNSPECIFIED": 0, + "EXPERIMENT_STATUS_PROPOSED": 1, + "EXPERIMENT_STATUS_RUNNING": 2, + "EXPERIMENT_STATUS_PAUSED": 3, + "EXPERIMENT_STATUS_SUSPENDED": 4, + "EXPERIMENT_STATUS_COMPLETE": 5, + "EXPERIMENT_STATUS_RETIRED": 6, + "EXPERIMENT_STATUS_ROLLED_BACK": 7, + } +) + +func (x ExperimentStatus) Enum() *ExperimentStatus { + p := new(ExperimentStatus) + *p = x + return p +} + +func (x ExperimentStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ExperimentStatus) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_v1_treatment_proto_enumTypes[4].Descriptor() +} + +func (ExperimentStatus) Type() protoreflect.EnumType { + return &file_xtcp_treatment_v1_treatment_proto_enumTypes[4] +} + +func (x ExperimentStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ExperimentStatus.Descriptor instead. +func (ExperimentStatus) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{4} +} + +// TCPSettings are the per-route TCP parameters a treatment installs. Every +// field is optional; at least one must be present. +type TCPSettings struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Kernel algorithm name (TCP_CA_NAME_MAX is 16 including NUL). + CongestionControl *string `protobuf:"bytes,1,opt,name=congestion_control,json=congestionControl,proto3,oneof" json:"congestion_control,omitempty"` + CongestionLock bool `protobuf:"varint,2,opt,name=congestion_lock,json=congestionLock,proto3" json:"congestion_lock,omitempty"` + RtoMinMs *uint32 `protobuf:"varint,3,opt,name=rto_min_ms,json=rtoMinMs,proto3,oneof" json:"rto_min_ms,omitempty"` + InitialCongestionWindow *uint32 `protobuf:"varint,4,opt,name=initial_congestion_window,json=initialCongestionWindow,proto3,oneof" json:"initial_congestion_window,omitempty"` + InitialReceiveWindow *uint32 `protobuf:"varint,5,opt,name=initial_receive_window,json=initialReceiveWindow,proto3,oneof" json:"initial_receive_window,omitempty"` + QuickAck *bool `protobuf:"varint,6,opt,name=quick_ack,json=quickAck,proto3,oneof" json:"quick_ack,omitempty"` + Ecn *bool `protobuf:"varint,7,opt,name=ecn,proto3,oneof" json:"ecn,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TCPSettings) Reset() { + *x = TCPSettings{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TCPSettings) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TCPSettings) ProtoMessage() {} + +func (x *TCPSettings) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TCPSettings.ProtoReflect.Descriptor instead. +func (*TCPSettings) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{0} +} + +func (x *TCPSettings) GetCongestionControl() string { + if x != nil && x.CongestionControl != nil { + return *x.CongestionControl + } + return "" +} + +func (x *TCPSettings) GetCongestionLock() bool { + if x != nil { + return x.CongestionLock + } + return false +} + +func (x *TCPSettings) GetRtoMinMs() uint32 { + if x != nil && x.RtoMinMs != nil { + return *x.RtoMinMs + } + return 0 +} + +func (x *TCPSettings) GetInitialCongestionWindow() uint32 { + if x != nil && x.InitialCongestionWindow != nil { + return *x.InitialCongestionWindow + } + return 0 +} + +func (x *TCPSettings) GetInitialReceiveWindow() uint32 { + if x != nil && x.InitialReceiveWindow != nil { + return *x.InitialReceiveWindow + } + return 0 +} + +func (x *TCPSettings) GetQuickAck() bool { + if x != nil && x.QuickAck != nil { + return *x.QuickAck + } + return false +} + +func (x *TCPSettings) GetEcn() bool { + if x != nil && x.Ecn != nil { + return *x.Ecn + } + return false +} + +type Treatment struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Revision uint64 `protobuf:"varint,2,opt,name=revision,proto3" json:"revision,omitempty"` + // Canonical unicast host prefix (/32 or /128). Canonical form, unicast and + // not-loopback are checked by treatment.ValidateTreatment. + Destination string `protobuf:"bytes,3,opt,name=destination,proto3" json:"destination,omitempty"` + Settings *TCPSettings `protobuf:"bytes,4,opt,name=settings,proto3" json:"settings,omitempty"` + EcnFabricVerified bool `protobuf:"varint,5,opt,name=ecn_fabric_verified,json=ecnFabricVerified,proto3" json:"ecn_fabric_verified,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Treatment) Reset() { + *x = Treatment{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Treatment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Treatment) ProtoMessage() {} + +func (x *Treatment) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Treatment.ProtoReflect.Descriptor instead. +func (*Treatment) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{1} +} + +func (x *Treatment) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Treatment) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *Treatment) GetDestination() string { + if x != nil { + return x.Destination + } + return "" +} + +func (x *Treatment) GetSettings() *TCPSettings { + if x != nil { + return x.Settings + } + return nil +} + +func (x *Treatment) GetEcnFabricVerified() bool { + if x != nil { + return x.EcnFabricVerified + } + return false +} + +type Assignment struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExperimentId string `protobuf:"bytes,2,opt,name=experiment_id,json=experimentId,proto3" json:"experiment_id,omitempty"` + Treatment *Treatment `protobuf:"bytes,3,opt,name=treatment,proto3" json:"treatment,omitempty"` + Mode AssignmentMode `protobuf:"varint,4,opt,name=mode,proto3,enum=xtcp_treatment.v1.AssignmentMode" json:"mode,omitempty"` + LeaseExpiresAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=lease_expires_at,json=leaseExpiresAt,proto3" json:"lease_expires_at,omitempty"` + // Previous approved stable treatment, restored on trial expiry/rollback. + Predecessor *Treatment `protobuf:"bytes,6,opt,name=predecessor,proto3" json:"predecessor,omitempty"` + // Increment only on an explicitly approved reactivation, not lease renewal. + Generation uint64 `protobuf:"varint,7,opt,name=generation,proto3" json:"generation,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Assignment) Reset() { + *x = Assignment{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Assignment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Assignment) ProtoMessage() {} + +func (x *Assignment) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Assignment.ProtoReflect.Descriptor instead. +func (*Assignment) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{2} +} + +func (x *Assignment) GetExperimentId() string { + if x != nil { + return x.ExperimentId + } + return "" +} + +func (x *Assignment) GetTreatment() *Treatment { + if x != nil { + return x.Treatment + } + return nil +} + +func (x *Assignment) GetMode() AssignmentMode { + if x != nil { + return x.Mode + } + return AssignmentMode_ASSIGNMENT_MODE_UNSPECIFIED +} + +func (x *Assignment) GetLeaseExpiresAt() *timestamppb.Timestamp { + if x != nil { + return x.LeaseExpiresAt + } + return nil +} + +func (x *Assignment) GetPredecessor() *Treatment { + if x != nil { + return x.Predecessor + } + return nil +} + +func (x *Assignment) GetGeneration() uint64 { + if x != nil { + return x.Generation + } + return 0 +} + +// DesiredState is the complete revisioned snapshot an agent reconciles to. +// Duplicate assignment IDs and overlapping destinations are rejected by +// treatment.ValidateDesired. +type DesiredState struct { + state protoimpl.MessageState `protogen:"open.v1"` + AgentId string `protobuf:"bytes,1,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + Revision uint64 `protobuf:"varint,2,opt,name=revision,proto3" json:"revision,omitempty"` + Suspended bool `protobuf:"varint,3,opt,name=suspended,proto3" json:"suspended,omitempty"` + Assignments []*Assignment `protobuf:"bytes,4,rep,name=assignments,proto3" json:"assignments,omitempty"` + IssuedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=issued_at,json=issuedAt,proto3" json:"issued_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DesiredState) Reset() { + *x = DesiredState{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DesiredState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DesiredState) ProtoMessage() {} + +func (x *DesiredState) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DesiredState.ProtoReflect.Descriptor instead. +func (*DesiredState) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{3} +} + +func (x *DesiredState) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +func (x *DesiredState) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *DesiredState) GetSuspended() bool { + if x != nil { + return x.Suspended + } + return false +} + +func (x *DesiredState) GetAssignments() []*Assignment { + if x != nil { + return x.Assignments + } + return nil +} + +func (x *DesiredState) GetIssuedAt() *timestamppb.Timestamp { + if x != nil { + return x.IssuedAt + } + return nil +} + +type Capabilities struct { + state protoimpl.MessageState `protogen:"open.v1"` + BootId string `protobuf:"bytes,1,opt,name=boot_id,json=bootId,proto3" json:"boot_id,omitempty"` + KernelRelease string `protobuf:"bytes,2,opt,name=kernel_release,json=kernelRelease,proto3" json:"kernel_release,omitempty"` + CongestionAlgorithms []string `protobuf:"bytes,3,rep,name=congestion_algorithms,json=congestionAlgorithms,proto3" json:"congestion_algorithms,omitempty"` + SimpleHostRouting bool `protobuf:"varint,4,opt,name=simple_host_routing,json=simpleHostRouting,proto3" json:"simple_host_routing,omitempty"` + ActuatorEnabled bool `protobuf:"varint,5,opt,name=actuator_enabled,json=actuatorEnabled,proto3" json:"actuator_enabled,omitempty"` + // Per-process nonce the agent writes into its journal header and the + // daemon stamps into every record as collection_id. Evidence counts only + // records whose (agent_id, host_boot_id, collection_id) an agent reported. + CollectionId string `protobuf:"bytes,6,opt,name=collection_id,json=collectionId,proto3" json:"collection_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Capabilities) Reset() { + *x = Capabilities{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Capabilities) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Capabilities) ProtoMessage() {} + +func (x *Capabilities) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Capabilities.ProtoReflect.Descriptor instead. +func (*Capabilities) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{4} +} + +func (x *Capabilities) GetBootId() string { + if x != nil { + return x.BootId + } + return "" +} + +func (x *Capabilities) GetKernelRelease() string { + if x != nil { + return x.KernelRelease + } + return "" +} + +func (x *Capabilities) GetCongestionAlgorithms() []string { + if x != nil { + return x.CongestionAlgorithms + } + return nil +} + +func (x *Capabilities) GetSimpleHostRouting() bool { + if x != nil { + return x.SimpleHostRouting + } + return false +} + +func (x *Capabilities) GetActuatorEnabled() bool { + if x != nil { + return x.ActuatorEnabled + } + return false +} + +func (x *Capabilities) GetCollectionId() string { + if x != nil { + return x.CollectionId + } + return "" +} + +// ApplicationRecord is the agent's account of one assignment. Agents report +// these on check-in with installed_route and installed_boot_id cleared. +type ApplicationRecord struct { + state protoimpl.MessageState `protogen:"open.v1"` + Assignment *Assignment `protobuf:"bytes,1,opt,name=assignment,proto3" json:"assignment,omitempty"` + DesiredRevision uint64 `protobuf:"varint,2,opt,name=desired_revision,json=desiredRevision,proto3" json:"desired_revision,omitempty"` + Status ApplyStatus `protobuf:"varint,3,opt,name=status,proto3,enum=xtcp_treatment.v1.ApplyStatus" json:"status,omitempty"` + ReceivedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=received_at,json=receivedAt,proto3" json:"received_at,omitempty"` + AttemptedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=attempted_at,json=attemptedAt,proto3" json:"attempted_at,omitempty"` + AppliedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=applied_at,json=appliedAt,proto3" json:"applied_at,omitempty"` + VerifiedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=verified_at,json=verifiedAt,proto3" json:"verified_at,omitempty"` + RemovedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=removed_at,json=removedAt,proto3" json:"removed_at,omitempty"` + Error string `protobuf:"bytes,9,opt,name=error,proto3" json:"error,omitempty"` + // Locally generated canonical netlink route body, never accepted from RPC. + InstalledRoute []byte `protobuf:"bytes,10,opt,name=installed_route,json=installedRoute,proto3" json:"installed_route,omitempty"` + InstalledBootId string `protobuf:"bytes,11,opt,name=installed_boot_id,json=installedBootId,proto3" json:"installed_boot_id,omitempty"` + ExpiredLatched bool `protobuf:"varint,12,opt,name=expired_latched,json=expiredLatched,proto3" json:"expired_latched,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ApplicationRecord) Reset() { + *x = ApplicationRecord{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ApplicationRecord) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplicationRecord) ProtoMessage() {} + +func (x *ApplicationRecord) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ApplicationRecord.ProtoReflect.Descriptor instead. +func (*ApplicationRecord) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{5} +} + +func (x *ApplicationRecord) GetAssignment() *Assignment { + if x != nil { + return x.Assignment + } + return nil +} + +func (x *ApplicationRecord) GetDesiredRevision() uint64 { + if x != nil { + return x.DesiredRevision + } + return 0 +} + +func (x *ApplicationRecord) GetStatus() ApplyStatus { + if x != nil { + return x.Status + } + return ApplyStatus_APPLY_STATUS_UNSPECIFIED +} + +func (x *ApplicationRecord) GetReceivedAt() *timestamppb.Timestamp { + if x != nil { + return x.ReceivedAt + } + return nil +} + +func (x *ApplicationRecord) GetAttemptedAt() *timestamppb.Timestamp { + if x != nil { + return x.AttemptedAt + } + return nil +} + +func (x *ApplicationRecord) GetAppliedAt() *timestamppb.Timestamp { + if x != nil { + return x.AppliedAt + } + return nil +} + +func (x *ApplicationRecord) GetVerifiedAt() *timestamppb.Timestamp { + if x != nil { + return x.VerifiedAt + } + return nil +} + +func (x *ApplicationRecord) GetRemovedAt() *timestamppb.Timestamp { + if x != nil { + return x.RemovedAt + } + return nil +} + +func (x *ApplicationRecord) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *ApplicationRecord) GetInstalledRoute() []byte { + if x != nil { + return x.InstalledRoute + } + return nil +} + +func (x *ApplicationRecord) GetInstalledBootId() string { + if x != nil { + return x.InstalledBootId + } + return "" +} + +func (x *ApplicationRecord) GetExpiredLatched() bool { + if x != nil { + return x.ExpiredLatched + } + return false +} + +// LocalState is the agent's journal snapshot. It is a file format for the +// host-side journal and the local tooling, not an RPC payload. +type LocalState struct { + state protoimpl.MessageState `protogen:"open.v1"` + Desired *DesiredState `protobuf:"bytes,1,opt,name=desired,proto3" json:"desired,omitempty"` + LocallySuspended bool `protobuf:"varint,2,opt,name=locally_suspended,json=locallySuspended,proto3" json:"locally_suspended,omitempty"` + SuspensionReason string `protobuf:"bytes,3,opt,name=suspension_reason,json=suspensionReason,proto3" json:"suspension_reason,omitempty"` + Records []*ApplicationRecord `protobuf:"bytes,4,rep,name=records,proto3" json:"records,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LocalState) Reset() { + *x = LocalState{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LocalState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalState) ProtoMessage() {} + +func (x *LocalState) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocalState.ProtoReflect.Descriptor instead. +func (*LocalState) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{6} +} + +func (x *LocalState) GetDesired() *DesiredState { + if x != nil { + return x.Desired + } + return nil +} + +func (x *LocalState) GetLocallySuspended() bool { + if x != nil { + return x.LocallySuspended + } + return false +} + +func (x *LocalState) GetSuspensionReason() string { + if x != nil { + return x.SuspensionReason + } + return "" +} + +func (x *LocalState) GetRecords() []*ApplicationRecord { + if x != nil { + return x.Records + } + return nil +} + +func (x *LocalState) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +type HostEvidence struct { + state protoimpl.MessageState `protogen:"open.v1"` + AgentId string `protobuf:"bytes,1,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + Sockets uint64 `protobuf:"varint,2,opt,name=sockets,proto3" json:"sockets,omitempty"` + BytesAcked uint64 `protobuf:"varint,3,opt,name=bytes_acked,json=bytesAcked,proto3" json:"bytes_acked,omitempty"` + GoodputBps float64 `protobuf:"fixed64,4,opt,name=goodput_bps,json=goodputBps,proto3" json:"goodput_bps,omitempty"` + RetransmissionRatio float64 `protobuf:"fixed64,5,opt,name=retransmission_ratio,json=retransmissionRatio,proto3" json:"retransmission_ratio,omitempty"` + RttP95Ms float64 `protobuf:"fixed64,6,opt,name=rtt_p95_ms,json=rttP95Ms,proto3" json:"rtt_p95_ms,omitempty"` + ExposedSockets uint64 `protobuf:"varint,7,opt,name=exposed_sockets,json=exposedSockets,proto3" json:"exposed_sockets,omitempty"` + CollectionHealthy bool `protobuf:"varint,8,opt,name=collection_healthy,json=collectionHealthy,proto3" json:"collection_healthy,omitempty"` + // Sockets stamped with this agent_id whose boot and collection nonce + // match no session the agent reported. They are excluded from every other + // field and counted here so a reviewer can see them. + UnboundSockets uint64 `protobuf:"varint,9,opt,name=unbound_sockets,json=unboundSockets,proto3" json:"unbound_sockets,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HostEvidence) Reset() { + *x = HostEvidence{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HostEvidence) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostEvidence) ProtoMessage() {} + +func (x *HostEvidence) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HostEvidence.ProtoReflect.Descriptor instead. +func (*HostEvidence) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{7} +} + +func (x *HostEvidence) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +func (x *HostEvidence) GetSockets() uint64 { + if x != nil { + return x.Sockets + } + return 0 +} + +func (x *HostEvidence) GetBytesAcked() uint64 { + if x != nil { + return x.BytesAcked + } + return 0 +} + +func (x *HostEvidence) GetGoodputBps() float64 { + if x != nil { + return x.GoodputBps + } + return 0 +} + +func (x *HostEvidence) GetRetransmissionRatio() float64 { + if x != nil { + return x.RetransmissionRatio + } + return 0 +} + +func (x *HostEvidence) GetRttP95Ms() float64 { + if x != nil { + return x.RttP95Ms + } + return 0 +} + +func (x *HostEvidence) GetExposedSockets() uint64 { + if x != nil { + return x.ExposedSockets + } + return 0 +} + +func (x *HostEvidence) GetCollectionHealthy() bool { + if x != nil { + return x.CollectionHealthy + } + return false +} + +func (x *HostEvidence) GetUnboundSockets() uint64 { + if x != nil { + return x.UnboundSockets + } + return 0 +} + +type Evidence struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + AnalyzedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=analyzed_at,json=analyzedAt,proto3" json:"analyzed_at,omitempty"` + WindowStart *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=window_start,json=windowStart,proto3" json:"window_start,omitempty"` + WindowEnd *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=window_end,json=windowEnd,proto3" json:"window_end,omitempty"` + QueryVersion string `protobuf:"bytes,5,opt,name=query_version,json=queryVersion,proto3" json:"query_version,omitempty"` + EnrichmentVersion string `protobuf:"bytes,6,opt,name=enrichment_version,json=enrichmentVersion,proto3" json:"enrichment_version,omitempty"` + Hosts []*HostEvidence `protobuf:"bytes,7,rep,name=hosts,proto3" json:"hosts,omitempty"` + // SHA-256 of the raw warehouse response bytes, as received, that this + // summary was decoded from. The response itself is not archived: the + // digest lets two controllers (or a later audit) confirm they decoded the + // same bytes, and reproducing it means re-running query_version over + // [window_start, window_end) against the same table. Archiving responses + // to object storage is a possible follow-up, not a current guarantee. + ArtifactSha256 string `protobuf:"bytes,8,opt,name=artifact_sha256,json=artifactSha256,proto3" json:"artifact_sha256,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Evidence) Reset() { + *x = Evidence{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Evidence) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Evidence) ProtoMessage() {} + +func (x *Evidence) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Evidence.ProtoReflect.Descriptor instead. +func (*Evidence) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{8} +} + +func (x *Evidence) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Evidence) GetAnalyzedAt() *timestamppb.Timestamp { + if x != nil { + return x.AnalyzedAt + } + return nil +} + +func (x *Evidence) GetWindowStart() *timestamppb.Timestamp { + if x != nil { + return x.WindowStart + } + return nil +} + +func (x *Evidence) GetWindowEnd() *timestamppb.Timestamp { + if x != nil { + return x.WindowEnd + } + return nil +} + +func (x *Evidence) GetQueryVersion() string { + if x != nil { + return x.QueryVersion + } + return "" +} + +func (x *Evidence) GetEnrichmentVersion() string { + if x != nil { + return x.EnrichmentVersion + } + return "" +} + +func (x *Evidence) GetHosts() []*HostEvidence { + if x != nil { + return x.Hosts + } + return nil +} + +func (x *Evidence) GetArtifactSha256() string { + if x != nil { + return x.ArtifactSha256 + } + return "" +} + +type ExperimentPolicy struct { + state protoimpl.MessageState `protogen:"open.v1"` + MinimumObservation *durationpb.Duration `protobuf:"bytes,1,opt,name=minimum_observation,json=minimumObservation,proto3" json:"minimum_observation,omitempty"` + MaximumPhase *durationpb.Duration `protobuf:"bytes,2,opt,name=maximum_phase,json=maximumPhase,proto3" json:"maximum_phase,omitempty"` + MinimumSocketsPerHost uint64 `protobuf:"varint,3,opt,name=minimum_sockets_per_host,json=minimumSocketsPerHost,proto3" json:"minimum_sockets_per_host,omitempty"` + MinimumBytesPerHost uint64 `protobuf:"varint,4,opt,name=minimum_bytes_per_host,json=minimumBytesPerHost,proto3" json:"minimum_bytes_per_host,omitempty"` + MinimumTreatedHosts uint32 `protobuf:"varint,5,opt,name=minimum_treated_hosts,json=minimumTreatedHosts,proto3" json:"minimum_treated_hosts,omitempty"` + MinimumImprovement float64 `protobuf:"fixed64,6,opt,name=minimum_improvement,json=minimumImprovement,proto3" json:"minimum_improvement,omitempty"` + MaximumRetransmissionIncrease float64 `protobuf:"fixed64,7,opt,name=maximum_retransmission_increase,json=maximumRetransmissionIncrease,proto3" json:"maximum_retransmission_increase,omitempty"` + MaximumRttIncrease float64 `protobuf:"fixed64,8,opt,name=maximum_rtt_increase,json=maximumRttIncrease,proto3" json:"maximum_rtt_increase,omitempty"` + MaximumEvidenceAge *durationpb.Duration `protobuf:"bytes,9,opt,name=maximum_evidence_age,json=maximumEvidenceAge,proto3" json:"maximum_evidence_age,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExperimentPolicy) Reset() { + *x = ExperimentPolicy{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExperimentPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExperimentPolicy) ProtoMessage() {} + +func (x *ExperimentPolicy) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExperimentPolicy.ProtoReflect.Descriptor instead. +func (*ExperimentPolicy) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{9} +} + +func (x *ExperimentPolicy) GetMinimumObservation() *durationpb.Duration { + if x != nil { + return x.MinimumObservation + } + return nil +} + +func (x *ExperimentPolicy) GetMaximumPhase() *durationpb.Duration { + if x != nil { + return x.MaximumPhase + } + return nil +} + +func (x *ExperimentPolicy) GetMinimumSocketsPerHost() uint64 { + if x != nil { + return x.MinimumSocketsPerHost + } + return 0 +} + +func (x *ExperimentPolicy) GetMinimumBytesPerHost() uint64 { + if x != nil { + return x.MinimumBytesPerHost + } + return 0 +} + +func (x *ExperimentPolicy) GetMinimumTreatedHosts() uint32 { + if x != nil { + return x.MinimumTreatedHosts + } + return 0 +} + +func (x *ExperimentPolicy) GetMinimumImprovement() float64 { + if x != nil { + return x.MinimumImprovement + } + return 0 +} + +func (x *ExperimentPolicy) GetMaximumRetransmissionIncrease() float64 { + if x != nil { + return x.MaximumRetransmissionIncrease + } + return 0 +} + +func (x *ExperimentPolicy) GetMaximumRttIncrease() float64 { + if x != nil { + return x.MaximumRttIncrease + } + return 0 +} + +func (x *ExperimentPolicy) GetMaximumEvidenceAge() *durationpb.Duration { + if x != nil { + return x.MaximumEvidenceAge + } + return nil +} + +type Phase struct { + state protoimpl.MessageState `protogen:"open.v1"` + TargetHosts uint32 `protobuf:"varint,1,opt,name=target_hosts,json=targetHosts,proto3" json:"target_hosts,omitempty"` + IssuedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=issued_at,json=issuedAt,proto3" json:"issued_at,omitempty"` + ObservationStartedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=observation_started_at,json=observationStartedAt,proto3" json:"observation_started_at,omitempty"` + EvaluatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=evaluated_at,json=evaluatedAt,proto3" json:"evaluated_at,omitempty"` + Evidence *Evidence `protobuf:"bytes,5,opt,name=evidence,proto3" json:"evidence,omitempty"` + Outcome Outcome `protobuf:"varint,6,opt,name=outcome,proto3,enum=xtcp_treatment.v1.Outcome" json:"outcome,omitempty"` + Reviewer string `protobuf:"bytes,7,opt,name=reviewer,proto3" json:"reviewer,omitempty"` + Reason string `protobuf:"bytes,8,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Phase) Reset() { + *x = Phase{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Phase) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Phase) ProtoMessage() {} + +func (x *Phase) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Phase.ProtoReflect.Descriptor instead. +func (*Phase) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{10} +} + +func (x *Phase) GetTargetHosts() uint32 { + if x != nil { + return x.TargetHosts + } + return 0 +} + +func (x *Phase) GetIssuedAt() *timestamppb.Timestamp { + if x != nil { + return x.IssuedAt + } + return nil +} + +func (x *Phase) GetObservationStartedAt() *timestamppb.Timestamp { + if x != nil { + return x.ObservationStartedAt + } + return nil +} + +func (x *Phase) GetEvaluatedAt() *timestamppb.Timestamp { + if x != nil { + return x.EvaluatedAt + } + return nil +} + +func (x *Phase) GetEvidence() *Evidence { + if x != nil { + return x.Evidence + } + return nil +} + +func (x *Phase) GetOutcome() Outcome { + if x != nil { + return x.Outcome + } + return Outcome_OUTCOME_UNSPECIFIED +} + +func (x *Phase) GetReviewer() string { + if x != nil { + return x.Reviewer + } + return "" +} + +func (x *Phase) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type Experiment struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Location string `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` + Hypothesis string `protobuf:"bytes,3,opt,name=hypothesis,proto3" json:"hypothesis,omitempty"` + Treatment *Treatment `protobuf:"bytes,4,opt,name=treatment,proto3" json:"treatment,omitempty"` + Policy *ExperimentPolicy `protobuf:"bytes,5,opt,name=policy,proto3" json:"policy,omitempty"` + Baseline *Evidence `protobuf:"bytes,6,opt,name=baseline,proto3" json:"baseline,omitempty"` + // Randomised host order; phases treat a growing prefix of it. + CohortOrder []string `protobuf:"bytes,7,rep,name=cohort_order,json=cohortOrder,proto3" json:"cohort_order,omitempty"` + Phases []*Phase `protobuf:"bytes,8,rep,name=phases,proto3" json:"phases,omitempty"` + Status ExperimentStatus `protobuf:"varint,9,opt,name=status,proto3,enum=xtcp_treatment.v1.ExperimentStatus" json:"status,omitempty"` + Revision uint64 `protobuf:"varint,10,opt,name=revision,proto3" json:"revision,omitempty"` + ProposedAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=proposed_at,json=proposedAt,proto3" json:"proposed_at,omitempty"` + LatestEvidence *Evidence `protobuf:"bytes,12,opt,name=latest_evidence,json=latestEvidence,proto3" json:"latest_evidence,omitempty"` + LatestOutcome Outcome `protobuf:"varint,13,opt,name=latest_outcome,json=latestOutcome,proto3,enum=xtcp_treatment.v1.Outcome" json:"latest_outcome,omitempty"` + // When the controller last changed this experiment. Terminal experiments + // suppress rediscovery of their destination for a day after this instant. + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,14,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Experiment) Reset() { + *x = Experiment{} + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Experiment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Experiment) ProtoMessage() {} + +func (x *Experiment) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_v1_treatment_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Experiment.ProtoReflect.Descriptor instead. +func (*Experiment) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_v1_treatment_proto_rawDescGZIP(), []int{11} +} + +func (x *Experiment) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Experiment) GetLocation() string { + if x != nil { + return x.Location + } + return "" +} + +func (x *Experiment) GetHypothesis() string { + if x != nil { + return x.Hypothesis + } + return "" +} + +func (x *Experiment) GetTreatment() *Treatment { + if x != nil { + return x.Treatment + } + return nil +} + +func (x *Experiment) GetPolicy() *ExperimentPolicy { + if x != nil { + return x.Policy + } + return nil +} + +func (x *Experiment) GetBaseline() *Evidence { + if x != nil { + return x.Baseline + } + return nil +} + +func (x *Experiment) GetCohortOrder() []string { + if x != nil { + return x.CohortOrder + } + return nil +} + +func (x *Experiment) GetPhases() []*Phase { + if x != nil { + return x.Phases + } + return nil +} + +func (x *Experiment) GetStatus() ExperimentStatus { + if x != nil { + return x.Status + } + return ExperimentStatus_EXPERIMENT_STATUS_UNSPECIFIED +} + +func (x *Experiment) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *Experiment) GetProposedAt() *timestamppb.Timestamp { + if x != nil { + return x.ProposedAt + } + return nil +} + +func (x *Experiment) GetLatestEvidence() *Evidence { + if x != nil { + return x.LatestEvidence + } + return nil +} + +func (x *Experiment) GetLatestOutcome() Outcome { + if x != nil { + return x.LatestOutcome + } + return Outcome_OUTCOME_UNSPECIFIED +} + +func (x *Experiment) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +var file_xtcp_treatment_v1_treatment_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.MethodOptions)(nil), + ExtensionType: (*Role)(nil), + Field: 51002, + Name: "xtcp_treatment.v1.role", + Tag: "varint,51002,opt,name=role,enum=xtcp_treatment.v1.Role", + Filename: "xtcp_treatment/v1/treatment.proto", + }, +} + +// Extension fields to descriptorpb.MethodOptions. +var ( + // Field number from the 50000-99999 range reserved for internal use; + // 51001 is xtcp_auth.v1.access. + // + // optional xtcp_treatment.v1.Role role = 51002; + E_Role = &file_xtcp_treatment_v1_treatment_proto_extTypes[0] +) + +var File_xtcp_treatment_v1_treatment_proto protoreflect.FileDescriptor + +const file_xtcp_treatment_v1_treatment_proto_rawDesc = "" + + "\n" + + "!xtcp_treatment/v1/treatment.proto\x12\x11xtcp_treatment.v1\x1a\x1bbuf/validate/validate.proto\x1a google/protobuf/descriptor.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8d\a\n" + + "\vTCPSettings\x12Y\n" + + "\x12congestion_control\x18\x01 \x01(\tB%\xbaH\"r \x18\x0f2\x1c^[a-zA-Z0-9][a-zA-Z0-9_.-]*$H\x00R\x11congestionControl\x88\x01\x01\x12'\n" + + "\x0fcongestion_lock\x18\x02 \x01(\bR\x0econgestionLock\x12.\n" + + "\n" + + "rto_min_ms\x18\x03 \x01(\rB\v\xbaH\b*\x06\x18\xc0\xa9\a(\x01H\x01R\brtoMinMs\x88\x01\x01\x12K\n" + + "\x19initial_congestion_window\x18\x04 \x01(\rB\n" + + "\xbaH\a*\x05\x18\x80\b(\x01H\x02R\x17initialCongestionWindow\x88\x01\x01\x12E\n" + + "\x16initial_receive_window\x18\x05 \x01(\rB\n" + + "\xbaH\a*\x05\x18\x80\b(\x01H\x03R\x14initialReceiveWindow\x88\x01\x01\x12 \n" + + "\tquick_ack\x18\x06 \x01(\bH\x04R\bquickAck\x88\x01\x01\x12\x15\n" + + "\x03ecn\x18\a \x01(\bH\x05R\x03ecn\x88\x01\x01:\x87\x03\xbaH\x83\x03\x1a\xf3\x01\n" + + "\x16tcp_settings.non_empty\x12/a treatment must set at least one TCP parameter\x1a\xa7\x01has(this.congestion_control) || has(this.rto_min_ms) || has(this.initial_congestion_window) || has(this.initial_receive_window) || has(this.quick_ack) || has(this.ecn)\x1a\x8a\x01\n" + + "$tcp_settings.lock_requires_algorithm\x12+congestion_lock requires congestion_control\x1a5!this.congestion_lock || has(this.congestion_control)B\x15\n" + + "\x13_congestion_controlB\r\n" + + "\v_rto_min_msB\x1c\n" + + "\x1a_initial_congestion_windowB\x19\n" + + "\x17_initial_receive_windowB\f\n" + + "\n" + + "_quick_ackB\x06\n" + + "\x04_ecn\"\xd8\x03\n" + + "\tTreatment\x129\n" + + "\x02id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x02id\x12#\n" + + "\brevision\x18\x02 \x01(\x04B\a\xbaH\x042\x02 \x00R\brevision\x12,\n" + + "\vdestination\x18\x03 \x01(\tB\n" + + "\xbaH\ar\x05\x181\xe8\x01\x01R\vdestination\x12B\n" + + "\bsettings\x18\x04 \x01(\v2\x1e.xtcp_treatment.v1.TCPSettingsB\x06\xbaH\x03\xc8\x01\x01R\bsettings\x12.\n" + + "\x13ecn_fabric_verified\x18\x05 \x01(\bR\x11ecnFabricVerified:\xc8\x01\xbaH\xc4\x01\x1a\xc1\x01\n" + + "\x1ctreatment.dctcp_requires_ecn\x12ADCTCP requires independently verified ECN fabric and explicit ECN\x1a^this.settings.congestion_control != 'dctcp' || (this.ecn_fabric_verified && this.settings.ecn)\"\xcc\x05\n" + + "\n" + + "Assignment\x12N\n" + + "\rexperiment_id\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\fexperimentId\x12B\n" + + "\ttreatment\x18\x03 \x01(\v2\x1c.xtcp_treatment.v1.TreatmentB\x06\xbaH\x03\xc8\x01\x01R\ttreatment\x12A\n" + + "\x04mode\x18\x04 \x01(\x0e2!.xtcp_treatment.v1.AssignmentModeB\n" + + "\xbaH\a\x82\x01\x04\x10\x01 \x00R\x04mode\x12D\n" + + "\x10lease_expires_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\x0eleaseExpiresAt\x12>\n" + + "\vpredecessor\x18\x06 \x01(\v2\x1c.xtcp_treatment.v1.TreatmentR\vpredecessor\x12'\n" + + "\n" + + "generation\x18\a \x01(\x04B\a\xbaH\x042\x02 \x00R\n" + + "generation:\xad\x02\xbaH\xa9\x02\x1a}\n" + + "\x1fassignment.trial_requires_lease\x12,a trial assignment requires lease_expires_at\x1a,this.mode != 1 || has(this.lease_expires_at)\x1a\xa7\x01\n" + + "\"assignment.predecessor_destination\x12+predecessor must cover the same destination\x1aT!has(this.predecessor) || this.predecessor.destination == this.treatment.destinationJ\x04\b\x01\x10\x02R\x02id\"\xa4\x02\n" + + "\fDesiredState\x12D\n" + + "\bagent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\aagentId\x12#\n" + + "\brevision\x18\x02 \x01(\x04B\a\xbaH\x042\x02 \x00R\brevision\x12\x1c\n" + + "\tsuspended\x18\x03 \x01(\bR\tsuspended\x12J\n" + + "\vassignments\x18\x04 \x03(\v2\x1d.xtcp_treatment.v1.AssignmentB\t\xbaH\x06\x92\x01\x03\x10\x80 R\vassignments\x12?\n" + + "\tissued_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\bissuedAt\"\xdf\x02\n" + + "\fCapabilities\x12B\n" + + "\aboot_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x06bootId\x12/\n" + + "\x0ekernel_release\x18\x02 \x01(\tB\b\xbaH\x05r\x03\x18\x80\x02R\rkernelRelease\x12C\n" + + "\x15congestion_algorithms\x18\x03 \x03(\tB\x0e\xbaH\v\x92\x01\b\x10@\"\x04r\x02\x18\x0fR\x14congestionAlgorithms\x12.\n" + + "\x13simple_host_routing\x18\x04 \x01(\bR\x11simpleHostRouting\x12)\n" + + "\x10actuator_enabled\x18\x05 \x01(\bR\x0factuatorEnabled\x12:\n" + + "\rcollection_id\x18\x06 \x01(\tB\x15\xbaH\x12r\x102\x0e^[0-9a-f]{32}$R\fcollectionId\"\xa8\x05\n" + + "\x11ApplicationRecord\x12E\n" + + "\n" + + "assignment\x18\x01 \x01(\v2\x1d.xtcp_treatment.v1.AssignmentB\x06\xbaH\x03\xc8\x01\x01R\n" + + "assignment\x12)\n" + + "\x10desired_revision\x18\x02 \x01(\x04R\x0fdesiredRevision\x12@\n" + + "\x06status\x18\x03 \x01(\x0e2\x1e.xtcp_treatment.v1.ApplyStatusB\b\xbaH\x05\x82\x01\x02\x10\x01R\x06status\x12;\n" + + "\vreceived_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "receivedAt\x12=\n" + + "\fattempted_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\vattemptedAt\x129\n" + + "\n" + + "applied_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tappliedAt\x12;\n" + + "\vverified_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "verifiedAt\x129\n" + + "\n" + + "removed_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tremovedAt\x12\x1e\n" + + "\x05error\x18\t \x01(\tB\b\xbaH\x05r\x03\x18\x80 R\x05error\x121\n" + + "\x0finstalled_route\x18\n" + + " \x01(\fB\b\xbaH\x05z\x03\x18\x80 R\x0einstalledRoute\x124\n" + + "\x11installed_boot_id\x18\v \x01(\tB\b\xbaH\x05r\x03\x18\x80\x01R\x0finstalledBootId\x12'\n" + + "\x0fexpired_latched\x18\f \x01(\bR\x0eexpiredLatched\"\xb1\x02\n" + + "\n" + + "LocalState\x129\n" + + "\adesired\x18\x01 \x01(\v2\x1f.xtcp_treatment.v1.DesiredStateR\adesired\x12+\n" + + "\x11locally_suspended\x18\x02 \x01(\bR\x10locallySuspended\x125\n" + + "\x11suspension_reason\x18\x03 \x01(\tB\b\xbaH\x05r\x03\x18\x80\bR\x10suspensionReason\x12I\n" + + "\arecords\x18\x04 \x03(\v2$.xtcp_treatment.v1.ApplicationRecordB\t\xbaH\x06\x92\x01\x03\x10\x80@R\arecords\x129\n" + + "\n" + + "updated_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\"\xb2\x04\n" + + "\fHostEvidence\x12D\n" + + "\bagent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\aagentId\x12\x18\n" + + "\asockets\x18\x02 \x01(\x04R\asockets\x12\x1f\n" + + "\vbytes_acked\x18\x03 \x01(\x04R\n" + + "bytesAcked\x121\n" + + "\vgoodput_bps\x18\x04 \x01(\x01B\x10\xbaH\r\x12\v@\x01)\x00\x00\x00\x00\x00\x00\x00\x00R\n" + + "goodputBps\x12C\n" + + "\x14retransmission_ratio\x18\x05 \x01(\x01B\x10\xbaH\r\x12\v@\x01)\x00\x00\x00\x00\x00\x00\x00\x00R\x13retransmissionRatio\x12.\n" + + "\n" + + "rtt_p95_ms\x18\x06 \x01(\x01B\x10\xbaH\r\x12\v@\x01)\x00\x00\x00\x00\x00\x00\x00\x00R\brttP95Ms\x12'\n" + + "\x0fexposed_sockets\x18\a \x01(\x04R\x0eexposedSockets\x12-\n" + + "\x12collection_healthy\x18\b \x01(\bR\x11collectionHealthy\x12'\n" + + "\x0funbound_sockets\x18\t \x01(\x04R\x0eunboundSockets:x\xbaHu\x1as\n" + + "$host_evidence.exposed_within_sockets\x12%exposed_sockets cannot exceed sockets\x1a$this.exposed_sockets <= this.sockets\"\xbc\x05\n" + + "\bEvidence\x129\n" + + "\x02id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x02id\x12C\n" + + "\vanalyzed_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\n" + + "analyzedAt\x12E\n" + + "\fwindow_start\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\vwindowStart\x12A\n" + + "\n" + + "window_end\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\twindowEnd\x12/\n" + + "\rquery_version\x18\x05 \x01(\tB\n" + + "\xbaH\ar\x05\x10\x01\x18\x80\x02R\fqueryVersion\x127\n" + + "\x12enrichment_version\x18\x06 \x01(\tB\b\xbaH\x05r\x03\x18\x80\x02R\x11enrichmentVersion\x12B\n" + + "\x05hosts\x18\a \x03(\v2\x1f.xtcp_treatment.v1.HostEvidenceB\v\xbaH\b\x92\x01\x05\b\x01\x10\x90NR\x05hosts\x12>\n" + + "\x0fartifact_sha256\x18\b \x01(\tB\x15\xbaH\x12r\x102\x0e^[0-9a-f]{64}$R\x0eartifactSha256:\xb7\x01\xbaH\xb3\x01\x1a\xb0\x01\n" + + "\x11evidence.interval\x12Owindow_end must follow window_start and analyzed_at must not precede window_end\x1aJthis.window_end > this.window_start && this.analyzed_at >= this.window_end\"\xec\x06\n" + + "\x10ExperimentPolicy\x12]\n" + + "\x13minimum_observation\x18\x01 \x01(\v2\x19.google.protobuf.DurationB\x11\xbaH\x0e\xc8\x01\x01\xaa\x01\b\"\x04\b\x80\xf5$*\x00R\x12minimumObservation\x12Q\n" + + "\rmaximum_phase\x18\x02 \x01(\v2\x19.google.protobuf.DurationB\x11\xbaH\x0e\xc8\x01\x01\xaa\x01\b\"\x04\b\x80\xf5$*\x00R\fmaximumPhase\x12@\n" + + "\x18minimum_sockets_per_host\x18\x03 \x01(\x04B\a\xbaH\x042\x02 \x00R\x15minimumSocketsPerHost\x12<\n" + + "\x16minimum_bytes_per_host\x18\x04 \x01(\x04B\a\xbaH\x042\x02 \x00R\x13minimumBytesPerHost\x12>\n" + + "\x15minimum_treated_hosts\x18\x05 \x01(\rB\n" + + "\xbaH\a*\x05\x18\x90N(\x02R\x13minimumTreatedHosts\x12J\n" + + "\x13minimum_improvement\x18\x06 \x01(\x01B\x19\xbaH\x16\x12\x14@\x01\x19\x00\x00\x00\x00\x00\x00\xf0?)\x00\x00\x00\x00\x00\x00\x00\x00R\x12minimumImprovement\x12a\n" + + "\x1fmaximum_retransmission_increase\x18\a \x01(\x01B\x19\xbaH\x16\x12\x14@\x01\x19\x00\x00\x00\x00\x00\x00\xf0?)\x00\x00\x00\x00\x00\x00\x00\x00R\x1dmaximumRetransmissionIncrease\x12K\n" + + "\x14maximum_rtt_increase\x18\b \x01(\x01B\x19\xbaH\x16\x12\x14@\x01\x19\x00\x00\x00\x00\x00\x00\xf0?)\x00\x00\x00\x00\x00\x00\x00\x00R\x12maximumRttIncrease\x12^\n" + + "\x14maximum_evidence_age\x18\t \x01(\v2\x19.google.protobuf.DurationB\x11\xbaH\x0e\xc8\x01\x01\xaa\x01\b\"\x04\b\x80\xf5$*\x00R\x12maximumEvidenceAge:\x89\x01\xbaH\x85\x01\x1a\x82\x01\n" + + "\x1fpolicy.observation_within_phase\x12/minimum_observation cannot exceed maximum_phase\x1a.this.minimum_observation <= this.maximum_phase\"\xc1\x03\n" + + "\x05Phase\x12-\n" + + "\ftarget_hosts\x18\x01 \x01(\rB\n" + + "\xbaH\a*\x05\x18\x90N(\x01R\vtargetHosts\x127\n" + + "\tissued_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\bissuedAt\x12P\n" + + "\x16observation_started_at\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\x14observationStartedAt\x12=\n" + + "\fevaluated_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\vevaluatedAt\x127\n" + + "\bevidence\x18\x05 \x01(\v2\x1b.xtcp_treatment.v1.EvidenceR\bevidence\x12>\n" + + "\aoutcome\x18\x06 \x01(\x0e2\x1a.xtcp_treatment.v1.OutcomeB\b\xbaH\x05\x82\x01\x02\x10\x01R\aoutcome\x12$\n" + + "\breviewer\x18\a \x01(\tB\b\xbaH\x05r\x03\x18\x80\x01R\breviewer\x12 \n" + + "\x06reason\x18\b \x01(\tB\b\xbaH\x05r\x03\x18\x80 R\x06reason\"\x88\a\n" + + "\n" + + "Experiment\x129\n" + + "\x02id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x02id\x12E\n" + + "\blocation\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\blocation\x12*\n" + + "\n" + + "hypothesis\x18\x03 \x01(\tB\n" + + "\xbaH\ar\x05\x10\x01\x18\x80@R\n" + + "hypothesis\x12B\n" + + "\ttreatment\x18\x04 \x01(\v2\x1c.xtcp_treatment.v1.TreatmentB\x06\xbaH\x03\xc8\x01\x01R\ttreatment\x12C\n" + + "\x06policy\x18\x05 \x01(\v2#.xtcp_treatment.v1.ExperimentPolicyB\x06\xbaH\x03\xc8\x01\x01R\x06policy\x12?\n" + + "\bbaseline\x18\x06 \x01(\v2\x1b.xtcp_treatment.v1.EvidenceB\x06\xbaH\x03\xc8\x01\x01R\bbaseline\x12X\n" + + "\fcohort_order\x18\a \x03(\tB5\xbaH2\x92\x01/\b\x03\x10\x90N\x18\x01\"&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\vcohortOrder\x12:\n" + + "\x06phases\x18\b \x03(\v2\x18.xtcp_treatment.v1.PhaseB\b\xbaH\x05\x92\x01\x02\x10@R\x06phases\x12E\n" + + "\x06status\x18\t \x01(\x0e2#.xtcp_treatment.v1.ExperimentStatusB\b\xbaH\x05\x82\x01\x02\x10\x01R\x06status\x12\x1a\n" + + "\brevision\x18\n" + + " \x01(\x04R\brevision\x12;\n" + + "\vproposed_at\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "proposedAt\x12D\n" + + "\x0flatest_evidence\x18\f \x01(\v2\x1b.xtcp_treatment.v1.EvidenceR\x0elatestEvidence\x12K\n" + + "\x0elatest_outcome\x18\r \x01(\x0e2\x1a.xtcp_treatment.v1.OutcomeB\b\xbaH\x05\x82\x01\x02\x10\x01R\rlatestOutcome\x129\n" + + "\n" + + "updated_at\x18\x0e \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt*?\n" + + "\x04Role\x12\x14\n" + + "\x10ROLE_UNSPECIFIED\x10\x00\x12\x0e\n" + + "\n" + + "ROLE_AGENT\x10\x01\x12\x11\n" + + "\rROLE_OPERATOR\x10\x02*\xa4\x01\n" + + "\x0eAssignmentMode\x12\x1f\n" + + "\x1bASSIGNMENT_MODE_UNSPECIFIED\x10\x00\x12\x19\n" + + "\x15ASSIGNMENT_MODE_TRIAL\x10\x01\x12\x1a\n" + + "\x16ASSIGNMENT_MODE_STABLE\x10\x02\x12\x1d\n" + + "\x19ASSIGNMENT_MODE_SUSPENDED\x10\x03\x12\x1b\n" + + "\x17ASSIGNMENT_MODE_RETIRED\x10\x04*\xad\x01\n" + + "\vApplyStatus\x12\x1c\n" + + "\x18APPLY_STATUS_UNSPECIFIED\x10\x00\x12\x18\n" + + "\x14APPLY_STATUS_PENDING\x10\x01\x12\x19\n" + + "\x15APPLY_STATUS_VERIFIED\x10\x02\x12\x18\n" + + "\x14APPLY_STATUS_REMOVED\x10\x03\x12\x18\n" + + "\x14APPLY_STATUS_EXPIRED\x10\x04\x12\x17\n" + + "\x13APPLY_STATUS_FAILED\x10\x05*\xa4\x04\n" + + "\aOutcome\x12\x17\n" + + "\x13OUTCOME_UNSPECIFIED\x10\x00\x12\x14\n" + + "\x10OUTCOME_BASELINE\x10\x01\x12 \n" + + "\x1cOUTCOME_AWAITING_APPLICATION\x10\x02\x12\x1d\n" + + "\x19OUTCOME_AWAITING_EXPOSURE\x10\x03\x12!\n" + + "\x1dOUTCOME_INSUFFICIENT_DURATION\x10\x04\x12\x1d\n" + + "\x19OUTCOME_INSUFFICIENT_DATA\x10\x05\x12!\n" + + "\x1dOUTCOME_INSUFFICIENT_CONTROLS\x10\x06\x12\x11\n" + + "\rOUTCOME_STALE\x10\a\x12\x17\n" + + "\x13OUTCOME_UNAVAILABLE\x10\b\x12\x18\n" + + "\x14OUTCOME_INCONCLUSIVE\x10\t\x12\x17\n" + + "\x13OUTCOME_SAFETY_ONLY\x10\n" + + "\x12\x18\n" + + "\x14OUTCOME_FINAL_SAFETY\x10\v\x12\x16\n" + + "\x12OUTCOME_BENEFICIAL\x10\f\x12\x13\n" + + "\x0fOUTCOME_HARMFUL\x10\r\x12\x13\n" + + "\x0fOUTCOME_EXPIRED\x10\x0e\x12\x1b\n" + + "\x17OUTCOME_STABLE_OBSERVED\x10\x0f\x12&\n" + + "\"OUTCOME_STABLE_EVIDENCE_INCOMPLETE\x10\x10\x12-\n" + + ")OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED\x10\x11\x12\x15\n" + + "\x11OUTCOME_OBSERVING\x10\x12*\x95\x02\n" + + "\x10ExperimentStatus\x12!\n" + + "\x1dEXPERIMENT_STATUS_UNSPECIFIED\x10\x00\x12\x1e\n" + + "\x1aEXPERIMENT_STATUS_PROPOSED\x10\x01\x12\x1d\n" + + "\x19EXPERIMENT_STATUS_RUNNING\x10\x02\x12\x1c\n" + + "\x18EXPERIMENT_STATUS_PAUSED\x10\x03\x12\x1f\n" + + "\x1bEXPERIMENT_STATUS_SUSPENDED\x10\x04\x12\x1e\n" + + "\x1aEXPERIMENT_STATUS_COMPLETE\x10\x05\x12\x1d\n" + + "\x19EXPERIMENT_STATUS_RETIRED\x10\x06\x12!\n" + + "\x1dEXPERIMENT_STATUS_ROLLED_BACK\x10\a:M\n" + + "\x04role\x12\x1e.google.protobuf.MethodOptions\x18\xba\x8e\x03 \x01(\x0e2\x17.xtcp_treatment.v1.RoleR\x04roleB\xc0\x01\n" + + "\x15com.xtcp_treatment.v1B\x0eTreatmentProtoP\x01Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\xa2\x02\x03XXX\xaa\x02\x10XtcpTreatment.V1\xca\x02\x10XtcpTreatment\\V1\xe2\x02\x1cXtcpTreatment\\V1\\GPBMetadata\xea\x02\x11XtcpTreatment::V1b\x06proto3" + +var ( + file_xtcp_treatment_v1_treatment_proto_rawDescOnce sync.Once + file_xtcp_treatment_v1_treatment_proto_rawDescData []byte +) + +func file_xtcp_treatment_v1_treatment_proto_rawDescGZIP() []byte { + file_xtcp_treatment_v1_treatment_proto_rawDescOnce.Do(func() { + file_xtcp_treatment_v1_treatment_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_xtcp_treatment_v1_treatment_proto_rawDesc), len(file_xtcp_treatment_v1_treatment_proto_rawDesc))) + }) + return file_xtcp_treatment_v1_treatment_proto_rawDescData +} + +var file_xtcp_treatment_v1_treatment_proto_enumTypes = make([]protoimpl.EnumInfo, 5) +var file_xtcp_treatment_v1_treatment_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_xtcp_treatment_v1_treatment_proto_goTypes = []any{ + (Role)(0), // 0: xtcp_treatment.v1.Role + (AssignmentMode)(0), // 1: xtcp_treatment.v1.AssignmentMode + (ApplyStatus)(0), // 2: xtcp_treatment.v1.ApplyStatus + (Outcome)(0), // 3: xtcp_treatment.v1.Outcome + (ExperimentStatus)(0), // 4: xtcp_treatment.v1.ExperimentStatus + (*TCPSettings)(nil), // 5: xtcp_treatment.v1.TCPSettings + (*Treatment)(nil), // 6: xtcp_treatment.v1.Treatment + (*Assignment)(nil), // 7: xtcp_treatment.v1.Assignment + (*DesiredState)(nil), // 8: xtcp_treatment.v1.DesiredState + (*Capabilities)(nil), // 9: xtcp_treatment.v1.Capabilities + (*ApplicationRecord)(nil), // 10: xtcp_treatment.v1.ApplicationRecord + (*LocalState)(nil), // 11: xtcp_treatment.v1.LocalState + (*HostEvidence)(nil), // 12: xtcp_treatment.v1.HostEvidence + (*Evidence)(nil), // 13: xtcp_treatment.v1.Evidence + (*ExperimentPolicy)(nil), // 14: xtcp_treatment.v1.ExperimentPolicy + (*Phase)(nil), // 15: xtcp_treatment.v1.Phase + (*Experiment)(nil), // 16: xtcp_treatment.v1.Experiment + (*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 18: google.protobuf.Duration + (*descriptorpb.MethodOptions)(nil), // 19: google.protobuf.MethodOptions +} +var file_xtcp_treatment_v1_treatment_proto_depIdxs = []int32{ + 5, // 0: xtcp_treatment.v1.Treatment.settings:type_name -> xtcp_treatment.v1.TCPSettings + 6, // 1: xtcp_treatment.v1.Assignment.treatment:type_name -> xtcp_treatment.v1.Treatment + 1, // 2: xtcp_treatment.v1.Assignment.mode:type_name -> xtcp_treatment.v1.AssignmentMode + 17, // 3: xtcp_treatment.v1.Assignment.lease_expires_at:type_name -> google.protobuf.Timestamp + 6, // 4: xtcp_treatment.v1.Assignment.predecessor:type_name -> xtcp_treatment.v1.Treatment + 7, // 5: xtcp_treatment.v1.DesiredState.assignments:type_name -> xtcp_treatment.v1.Assignment + 17, // 6: xtcp_treatment.v1.DesiredState.issued_at:type_name -> google.protobuf.Timestamp + 7, // 7: xtcp_treatment.v1.ApplicationRecord.assignment:type_name -> xtcp_treatment.v1.Assignment + 2, // 8: xtcp_treatment.v1.ApplicationRecord.status:type_name -> xtcp_treatment.v1.ApplyStatus + 17, // 9: xtcp_treatment.v1.ApplicationRecord.received_at:type_name -> google.protobuf.Timestamp + 17, // 10: xtcp_treatment.v1.ApplicationRecord.attempted_at:type_name -> google.protobuf.Timestamp + 17, // 11: xtcp_treatment.v1.ApplicationRecord.applied_at:type_name -> google.protobuf.Timestamp + 17, // 12: xtcp_treatment.v1.ApplicationRecord.verified_at:type_name -> google.protobuf.Timestamp + 17, // 13: xtcp_treatment.v1.ApplicationRecord.removed_at:type_name -> google.protobuf.Timestamp + 8, // 14: xtcp_treatment.v1.LocalState.desired:type_name -> xtcp_treatment.v1.DesiredState + 10, // 15: xtcp_treatment.v1.LocalState.records:type_name -> xtcp_treatment.v1.ApplicationRecord + 17, // 16: xtcp_treatment.v1.LocalState.updated_at:type_name -> google.protobuf.Timestamp + 17, // 17: xtcp_treatment.v1.Evidence.analyzed_at:type_name -> google.protobuf.Timestamp + 17, // 18: xtcp_treatment.v1.Evidence.window_start:type_name -> google.protobuf.Timestamp + 17, // 19: xtcp_treatment.v1.Evidence.window_end:type_name -> google.protobuf.Timestamp + 12, // 20: xtcp_treatment.v1.Evidence.hosts:type_name -> xtcp_treatment.v1.HostEvidence + 18, // 21: xtcp_treatment.v1.ExperimentPolicy.minimum_observation:type_name -> google.protobuf.Duration + 18, // 22: xtcp_treatment.v1.ExperimentPolicy.maximum_phase:type_name -> google.protobuf.Duration + 18, // 23: xtcp_treatment.v1.ExperimentPolicy.maximum_evidence_age:type_name -> google.protobuf.Duration + 17, // 24: xtcp_treatment.v1.Phase.issued_at:type_name -> google.protobuf.Timestamp + 17, // 25: xtcp_treatment.v1.Phase.observation_started_at:type_name -> google.protobuf.Timestamp + 17, // 26: xtcp_treatment.v1.Phase.evaluated_at:type_name -> google.protobuf.Timestamp + 13, // 27: xtcp_treatment.v1.Phase.evidence:type_name -> xtcp_treatment.v1.Evidence + 3, // 28: xtcp_treatment.v1.Phase.outcome:type_name -> xtcp_treatment.v1.Outcome + 6, // 29: xtcp_treatment.v1.Experiment.treatment:type_name -> xtcp_treatment.v1.Treatment + 14, // 30: xtcp_treatment.v1.Experiment.policy:type_name -> xtcp_treatment.v1.ExperimentPolicy + 13, // 31: xtcp_treatment.v1.Experiment.baseline:type_name -> xtcp_treatment.v1.Evidence + 15, // 32: xtcp_treatment.v1.Experiment.phases:type_name -> xtcp_treatment.v1.Phase + 4, // 33: xtcp_treatment.v1.Experiment.status:type_name -> xtcp_treatment.v1.ExperimentStatus + 17, // 34: xtcp_treatment.v1.Experiment.proposed_at:type_name -> google.protobuf.Timestamp + 13, // 35: xtcp_treatment.v1.Experiment.latest_evidence:type_name -> xtcp_treatment.v1.Evidence + 3, // 36: xtcp_treatment.v1.Experiment.latest_outcome:type_name -> xtcp_treatment.v1.Outcome + 17, // 37: xtcp_treatment.v1.Experiment.updated_at:type_name -> google.protobuf.Timestamp + 19, // 38: xtcp_treatment.v1.role:extendee -> google.protobuf.MethodOptions + 0, // 39: xtcp_treatment.v1.role:type_name -> xtcp_treatment.v1.Role + 40, // [40:40] is the sub-list for method output_type + 40, // [40:40] is the sub-list for method input_type + 39, // [39:40] is the sub-list for extension type_name + 38, // [38:39] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name +} + +func init() { file_xtcp_treatment_v1_treatment_proto_init() } +func file_xtcp_treatment_v1_treatment_proto_init() { + if File_xtcp_treatment_v1_treatment_proto != nil { + return + } + file_xtcp_treatment_v1_treatment_proto_msgTypes[0].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_xtcp_treatment_v1_treatment_proto_rawDesc), len(file_xtcp_treatment_v1_treatment_proto_rawDesc)), + NumEnums: 5, + NumMessages: 12, + NumExtensions: 1, + NumServices: 0, + }, + GoTypes: file_xtcp_treatment_v1_treatment_proto_goTypes, + DependencyIndexes: file_xtcp_treatment_v1_treatment_proto_depIdxs, + EnumInfos: file_xtcp_treatment_v1_treatment_proto_enumTypes, + MessageInfos: file_xtcp_treatment_v1_treatment_proto_msgTypes, + ExtensionInfos: file_xtcp_treatment_v1_treatment_proto_extTypes, + }.Build() + File_xtcp_treatment_v1_treatment_proto = out.File + file_xtcp_treatment_v1_treatment_proto_goTypes = nil + file_xtcp_treatment_v1_treatment_proto_depIdxs = nil +} diff --git a/gen/go/xtcp_treatment/treatment_vtproto.pb.go b/gen/go/xtcp_treatment/treatment_vtproto.pb.go new file mode 100644 index 000000000..c36af2594 --- /dev/null +++ b/gen/go/xtcp_treatment/treatment_vtproto.pb.go @@ -0,0 +1,4877 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: (devel) +// source: xtcp_treatment/v1/treatment.proto + +package xtcp_treatment + +import ( + binary "encoding/binary" + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + durationpb "github.com/planetscale/vtprotobuf/types/known/durationpb" + timestamppb "github.com/planetscale/vtprotobuf/types/known/timestamppb" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + durationpb1 "google.golang.org/protobuf/types/known/durationpb" + timestamppb1 "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *TCPSettings) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TCPSettings) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *TCPSettings) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Ecn != nil { + i-- + if *m.Ecn { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x38 + } + if m.QuickAck != nil { + i-- + if *m.QuickAck { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + if m.InitialReceiveWindow != nil { + i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.InitialReceiveWindow)) + i-- + dAtA[i] = 0x28 + } + if m.InitialCongestionWindow != nil { + i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.InitialCongestionWindow)) + i-- + dAtA[i] = 0x20 + } + if m.RtoMinMs != nil { + i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.RtoMinMs)) + i-- + dAtA[i] = 0x18 + } + if m.CongestionLock { + i-- + if m.CongestionLock { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if m.CongestionControl != nil { + i -= len(*m.CongestionControl) + copy(dAtA[i:], *m.CongestionControl) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(*m.CongestionControl))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Treatment) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Treatment) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Treatment) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.EcnFabricVerified { + i-- + if m.EcnFabricVerified { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.Settings != nil { + size, err := m.Settings.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if len(m.Destination) > 0 { + i -= len(m.Destination) + copy(dAtA[i:], m.Destination) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Destination))) + i-- + dAtA[i] = 0x1a + } + if m.Revision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Revision)) + i-- + dAtA[i] = 0x10 + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Assignment) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Assignment) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Assignment) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Generation != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Generation)) + i-- + dAtA[i] = 0x38 + } + if m.Predecessor != nil { + size, err := m.Predecessor.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + if m.LeaseExpiresAt != nil { + size, err := (*timestamppb.Timestamp)(m.LeaseExpiresAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if m.Mode != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Mode)) + i-- + dAtA[i] = 0x20 + } + if m.Treatment != nil { + size, err := m.Treatment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + if len(m.ExperimentId) > 0 { + i -= len(m.ExperimentId) + copy(dAtA[i:], m.ExperimentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ExperimentId))) + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} + +func (m *DesiredState) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DesiredState) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *DesiredState) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.IssuedAt != nil { + size, err := (*timestamppb.Timestamp)(m.IssuedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if len(m.Assignments) > 0 { + for iNdEx := len(m.Assignments) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Assignments[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if m.Suspended { + i-- + if m.Suspended { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x18 + } + if m.Revision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Revision)) + i-- + dAtA[i] = 0x10 + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Capabilities) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Capabilities) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Capabilities) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.CollectionId) > 0 { + i -= len(m.CollectionId) + copy(dAtA[i:], m.CollectionId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.CollectionId))) + i-- + dAtA[i] = 0x32 + } + if m.ActuatorEnabled { + i-- + if m.ActuatorEnabled { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.SimpleHostRouting { + i-- + if m.SimpleHostRouting { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if len(m.CongestionAlgorithms) > 0 { + for iNdEx := len(m.CongestionAlgorithms) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.CongestionAlgorithms[iNdEx]) + copy(dAtA[i:], m.CongestionAlgorithms[iNdEx]) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.CongestionAlgorithms[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.KernelRelease) > 0 { + i -= len(m.KernelRelease) + copy(dAtA[i:], m.KernelRelease) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.KernelRelease))) + i-- + dAtA[i] = 0x12 + } + if len(m.BootId) > 0 { + i -= len(m.BootId) + copy(dAtA[i:], m.BootId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.BootId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ApplicationRecord) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ApplicationRecord) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ApplicationRecord) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.ExpiredLatched { + i-- + if m.ExpiredLatched { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x60 + } + if len(m.InstalledBootId) > 0 { + i -= len(m.InstalledBootId) + copy(dAtA[i:], m.InstalledBootId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.InstalledBootId))) + i-- + dAtA[i] = 0x5a + } + if len(m.InstalledRoute) > 0 { + i -= len(m.InstalledRoute) + copy(dAtA[i:], m.InstalledRoute) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.InstalledRoute))) + i-- + dAtA[i] = 0x52 + } + if len(m.Error) > 0 { + i -= len(m.Error) + copy(dAtA[i:], m.Error) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Error))) + i-- + dAtA[i] = 0x4a + } + if m.RemovedAt != nil { + size, err := (*timestamppb.Timestamp)(m.RemovedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x42 + } + if m.VerifiedAt != nil { + size, err := (*timestamppb.Timestamp)(m.VerifiedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x3a + } + if m.AppliedAt != nil { + size, err := (*timestamppb.Timestamp)(m.AppliedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + if m.AttemptedAt != nil { + size, err := (*timestamppb.Timestamp)(m.AttemptedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if m.ReceivedAt != nil { + size, err := (*timestamppb.Timestamp)(m.ReceivedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if m.Status != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x18 + } + if m.DesiredRevision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DesiredRevision)) + i-- + dAtA[i] = 0x10 + } + if m.Assignment != nil { + size, err := m.Assignment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *LocalState) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LocalState) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *LocalState) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.UpdatedAt != nil { + size, err := (*timestamppb.Timestamp)(m.UpdatedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if len(m.Records) > 0 { + for iNdEx := len(m.Records) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Records[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.SuspensionReason) > 0 { + i -= len(m.SuspensionReason) + copy(dAtA[i:], m.SuspensionReason) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SuspensionReason))) + i-- + dAtA[i] = 0x1a + } + if m.LocallySuspended { + i-- + if m.LocallySuspended { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if m.Desired != nil { + size, err := m.Desired.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *HostEvidence) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *HostEvidence) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *HostEvidence) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.UnboundSockets != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.UnboundSockets)) + i-- + dAtA[i] = 0x48 + } + if m.CollectionHealthy { + i-- + if m.CollectionHealthy { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x40 + } + if m.ExposedSockets != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.ExposedSockets)) + i-- + dAtA[i] = 0x38 + } + if m.RttP95Ms != 0 { + i -= 8 + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.RttP95Ms)))) + i-- + dAtA[i] = 0x31 + } + if m.RetransmissionRatio != 0 { + i -= 8 + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.RetransmissionRatio)))) + i-- + dAtA[i] = 0x29 + } + if m.GoodputBps != 0 { + i -= 8 + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.GoodputBps)))) + i-- + dAtA[i] = 0x21 + } + if m.BytesAcked != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.BytesAcked)) + i-- + dAtA[i] = 0x18 + } + if m.Sockets != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Sockets)) + i-- + dAtA[i] = 0x10 + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Evidence) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Evidence) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Evidence) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.ArtifactSha256) > 0 { + i -= len(m.ArtifactSha256) + copy(dAtA[i:], m.ArtifactSha256) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ArtifactSha256))) + i-- + dAtA[i] = 0x42 + } + if len(m.Hosts) > 0 { + for iNdEx := len(m.Hosts) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Hosts[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x3a + } + } + if len(m.EnrichmentVersion) > 0 { + i -= len(m.EnrichmentVersion) + copy(dAtA[i:], m.EnrichmentVersion) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.EnrichmentVersion))) + i-- + dAtA[i] = 0x32 + } + if len(m.QueryVersion) > 0 { + i -= len(m.QueryVersion) + copy(dAtA[i:], m.QueryVersion) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.QueryVersion))) + i-- + dAtA[i] = 0x2a + } + if m.WindowEnd != nil { + size, err := (*timestamppb.Timestamp)(m.WindowEnd).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if m.WindowStart != nil { + size, err := (*timestamppb.Timestamp)(m.WindowStart).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + if m.AnalyzedAt != nil { + size, err := (*timestamppb.Timestamp)(m.AnalyzedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ExperimentPolicy) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExperimentPolicy) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *ExperimentPolicy) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.MaximumEvidenceAge != nil { + size, err := (*durationpb.Duration)(m.MaximumEvidenceAge).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x4a + } + if m.MaximumRttIncrease != 0 { + i -= 8 + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.MaximumRttIncrease)))) + i-- + dAtA[i] = 0x41 + } + if m.MaximumRetransmissionIncrease != 0 { + i -= 8 + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.MaximumRetransmissionIncrease)))) + i-- + dAtA[i] = 0x39 + } + if m.MinimumImprovement != 0 { + i -= 8 + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.MinimumImprovement)))) + i-- + dAtA[i] = 0x31 + } + if m.MinimumTreatedHosts != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.MinimumTreatedHosts)) + i-- + dAtA[i] = 0x28 + } + if m.MinimumBytesPerHost != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.MinimumBytesPerHost)) + i-- + dAtA[i] = 0x20 + } + if m.MinimumSocketsPerHost != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.MinimumSocketsPerHost)) + i-- + dAtA[i] = 0x18 + } + if m.MaximumPhase != nil { + size, err := (*durationpb.Duration)(m.MaximumPhase).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if m.MinimumObservation != nil { + size, err := (*durationpb.Duration)(m.MinimumObservation).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Phase) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Phase) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Phase) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Reason) > 0 { + i -= len(m.Reason) + copy(dAtA[i:], m.Reason) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Reason))) + i-- + dAtA[i] = 0x42 + } + if len(m.Reviewer) > 0 { + i -= len(m.Reviewer) + copy(dAtA[i:], m.Reviewer) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Reviewer))) + i-- + dAtA[i] = 0x3a + } + if m.Outcome != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Outcome)) + i-- + dAtA[i] = 0x30 + } + if m.Evidence != nil { + size, err := m.Evidence.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if m.EvaluatedAt != nil { + size, err := (*timestamppb.Timestamp)(m.EvaluatedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if m.ObservationStartedAt != nil { + size, err := (*timestamppb.Timestamp)(m.ObservationStartedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + if m.IssuedAt != nil { + size, err := (*timestamppb.Timestamp)(m.IssuedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if m.TargetHosts != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.TargetHosts)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Experiment) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Experiment) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Experiment) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.UpdatedAt != nil { + size, err := (*timestamppb.Timestamp)(m.UpdatedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x72 + } + if m.LatestOutcome != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.LatestOutcome)) + i-- + dAtA[i] = 0x68 + } + if m.LatestEvidence != nil { + size, err := m.LatestEvidence.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x62 + } + if m.ProposedAt != nil { + size, err := (*timestamppb.Timestamp)(m.ProposedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x5a + } + if m.Revision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Revision)) + i-- + dAtA[i] = 0x50 + } + if m.Status != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x48 + } + if len(m.Phases) > 0 { + for iNdEx := len(m.Phases) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Phases[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x42 + } + } + if len(m.CohortOrder) > 0 { + for iNdEx := len(m.CohortOrder) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.CohortOrder[iNdEx]) + copy(dAtA[i:], m.CohortOrder[iNdEx]) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.CohortOrder[iNdEx]))) + i-- + dAtA[i] = 0x3a + } + } + if m.Baseline != nil { + size, err := m.Baseline.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + if m.Policy != nil { + size, err := m.Policy.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if m.Treatment != nil { + size, err := m.Treatment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if len(m.Hypothesis) > 0 { + i -= len(m.Hypothesis) + copy(dAtA[i:], m.Hypothesis) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Hypothesis))) + i-- + dAtA[i] = 0x1a + } + if len(m.Location) > 0 { + i -= len(m.Location) + copy(dAtA[i:], m.Location) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Location))) + i-- + dAtA[i] = 0x12 + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TCPSettings) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CongestionControl != nil { + l = len(*m.CongestionControl) + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.CongestionLock { + n += 2 + } + if m.RtoMinMs != nil { + n += 1 + protohelpers.SizeOfVarint(uint64(*m.RtoMinMs)) + } + if m.InitialCongestionWindow != nil { + n += 1 + protohelpers.SizeOfVarint(uint64(*m.InitialCongestionWindow)) + } + if m.InitialReceiveWindow != nil { + n += 1 + protohelpers.SizeOfVarint(uint64(*m.InitialReceiveWindow)) + } + if m.QuickAck != nil { + n += 2 + } + if m.Ecn != nil { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *Treatment) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Revision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Revision)) + } + l = len(m.Destination) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Settings != nil { + l = m.Settings.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.EcnFabricVerified { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *Assignment) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ExperimentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Treatment != nil { + l = m.Treatment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Mode != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Mode)) + } + if m.LeaseExpiresAt != nil { + l = (*timestamppb.Timestamp)(m.LeaseExpiresAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Predecessor != nil { + l = m.Predecessor.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Generation != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Generation)) + } + n += len(m.unknownFields) + return n +} + +func (m *DesiredState) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Revision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Revision)) + } + if m.Suspended { + n += 2 + } + if len(m.Assignments) > 0 { + for _, e := range m.Assignments { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if m.IssuedAt != nil { + l = (*timestamppb.Timestamp)(m.IssuedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Capabilities) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.BootId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.KernelRelease) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.CongestionAlgorithms) > 0 { + for _, s := range m.CongestionAlgorithms { + l = len(s) + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if m.SimpleHostRouting { + n += 2 + } + if m.ActuatorEnabled { + n += 2 + } + l = len(m.CollectionId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *ApplicationRecord) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Assignment != nil { + l = m.Assignment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.DesiredRevision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.DesiredRevision)) + } + if m.Status != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Status)) + } + if m.ReceivedAt != nil { + l = (*timestamppb.Timestamp)(m.ReceivedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.AttemptedAt != nil { + l = (*timestamppb.Timestamp)(m.AttemptedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.AppliedAt != nil { + l = (*timestamppb.Timestamp)(m.AppliedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.VerifiedAt != nil { + l = (*timestamppb.Timestamp)(m.VerifiedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.RemovedAt != nil { + l = (*timestamppb.Timestamp)(m.RemovedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Error) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.InstalledRoute) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.InstalledBootId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.ExpiredLatched { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *LocalState) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Desired != nil { + l = m.Desired.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.LocallySuspended { + n += 2 + } + l = len(m.SuspensionReason) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.Records) > 0 { + for _, e := range m.Records { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if m.UpdatedAt != nil { + l = (*timestamppb.Timestamp)(m.UpdatedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *HostEvidence) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Sockets != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Sockets)) + } + if m.BytesAcked != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.BytesAcked)) + } + if m.GoodputBps != 0 { + n += 9 + } + if m.RetransmissionRatio != 0 { + n += 9 + } + if m.RttP95Ms != 0 { + n += 9 + } + if m.ExposedSockets != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.ExposedSockets)) + } + if m.CollectionHealthy { + n += 2 + } + if m.UnboundSockets != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.UnboundSockets)) + } + n += len(m.unknownFields) + return n +} + +func (m *Evidence) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.AnalyzedAt != nil { + l = (*timestamppb.Timestamp)(m.AnalyzedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.WindowStart != nil { + l = (*timestamppb.Timestamp)(m.WindowStart).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.WindowEnd != nil { + l = (*timestamppb.Timestamp)(m.WindowEnd).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.QueryVersion) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.EnrichmentVersion) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.Hosts) > 0 { + for _, e := range m.Hosts { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + l = len(m.ArtifactSha256) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *ExperimentPolicy) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MinimumObservation != nil { + l = (*durationpb.Duration)(m.MinimumObservation).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.MaximumPhase != nil { + l = (*durationpb.Duration)(m.MaximumPhase).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.MinimumSocketsPerHost != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.MinimumSocketsPerHost)) + } + if m.MinimumBytesPerHost != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.MinimumBytesPerHost)) + } + if m.MinimumTreatedHosts != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.MinimumTreatedHosts)) + } + if m.MinimumImprovement != 0 { + n += 9 + } + if m.MaximumRetransmissionIncrease != 0 { + n += 9 + } + if m.MaximumRttIncrease != 0 { + n += 9 + } + if m.MaximumEvidenceAge != nil { + l = (*durationpb.Duration)(m.MaximumEvidenceAge).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Phase) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TargetHosts != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.TargetHosts)) + } + if m.IssuedAt != nil { + l = (*timestamppb.Timestamp)(m.IssuedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.ObservationStartedAt != nil { + l = (*timestamppb.Timestamp)(m.ObservationStartedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.EvaluatedAt != nil { + l = (*timestamppb.Timestamp)(m.EvaluatedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Evidence != nil { + l = m.Evidence.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Outcome != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Outcome)) + } + l = len(m.Reviewer) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Reason) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Experiment) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Location) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Hypothesis) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Treatment != nil { + l = m.Treatment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Policy != nil { + l = m.Policy.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Baseline != nil { + l = m.Baseline.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.CohortOrder) > 0 { + for _, s := range m.CohortOrder { + l = len(s) + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if len(m.Phases) > 0 { + for _, e := range m.Phases { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if m.Status != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Status)) + } + if m.Revision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Revision)) + } + if m.ProposedAt != nil { + l = (*timestamppb.Timestamp)(m.ProposedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.LatestEvidence != nil { + l = m.LatestEvidence.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.LatestOutcome != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.LatestOutcome)) + } + if m.UpdatedAt != nil { + l = (*timestamppb.Timestamp)(m.UpdatedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *TCPSettings) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TCPSettings: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TCPSettings: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CongestionControl", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.CongestionControl = &s + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CongestionLock", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CongestionLock = bool(v != 0) + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RtoMinMs", wireType) + } + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RtoMinMs = &v + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialCongestionWindow", wireType) + } + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.InitialCongestionWindow = &v + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialReceiveWindow", wireType) + } + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.InitialReceiveWindow = &v + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field QuickAck", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.QuickAck = &b + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Ecn", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Ecn = &b + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Treatment) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Treatment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Treatment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType) + } + m.Revision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Revision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Destination", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Destination = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Settings", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Settings == nil { + m.Settings = &TCPSettings{} + } + if err := m.Settings.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EcnFabricVerified", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.EcnFabricVerified = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Assignment) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Assignment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Assignment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExperimentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExperimentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Treatment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Treatment == nil { + m.Treatment = &Treatment{} + } + if err := m.Treatment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + m.Mode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Mode |= AssignmentMode(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseExpiresAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LeaseExpiresAt == nil { + m.LeaseExpiresAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.LeaseExpiresAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Predecessor", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Predecessor == nil { + m.Predecessor = &Treatment{} + } + if err := m.Predecessor.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Generation", wireType) + } + m.Generation = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Generation |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DesiredState) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DesiredState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DesiredState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType) + } + m.Revision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Revision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Suspended", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Suspended = bool(v != 0) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Assignments", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Assignments = append(m.Assignments, &Assignment{}) + if err := m.Assignments[len(m.Assignments)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IssuedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IssuedAt == nil { + m.IssuedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.IssuedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Capabilities) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Capabilities: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Capabilities: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BootId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BootId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field KernelRelease", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.KernelRelease = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CongestionAlgorithms", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CongestionAlgorithms = append(m.CongestionAlgorithms, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SimpleHostRouting", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SimpleHostRouting = bool(v != 0) + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ActuatorEnabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ActuatorEnabled = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CollectionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CollectionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ApplicationRecord) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ApplicationRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ApplicationRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Assignment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Assignment == nil { + m.Assignment = &Assignment{} + } + if err := m.Assignment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DesiredRevision", wireType) + } + m.DesiredRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DesiredRevision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= ApplyStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReceivedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ReceivedAt == nil { + m.ReceivedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.ReceivedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AttemptedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AttemptedAt == nil { + m.AttemptedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.AttemptedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppliedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AppliedAt == nil { + m.AppliedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.AppliedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VerifiedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.VerifiedAt == nil { + m.VerifiedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.VerifiedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RemovedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RemovedAt == nil { + m.RemovedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.RemovedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InstalledRoute", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InstalledRoute = append(m.InstalledRoute[:0], dAtA[iNdEx:postIndex]...) + if m.InstalledRoute == nil { + m.InstalledRoute = []byte{} + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InstalledBootId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InstalledBootId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpiredLatched", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ExpiredLatched = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LocalState) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: LocalState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LocalState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Desired", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Desired == nil { + m.Desired = &DesiredState{} + } + if err := m.Desired.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LocallySuspended", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.LocallySuspended = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SuspensionReason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SuspensionReason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Records = append(m.Records, &ApplicationRecord{}) + if err := m.Records[len(m.Records)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdatedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UpdatedAt == nil { + m.UpdatedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.UpdatedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *HostEvidence) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: HostEvidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: HostEvidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sockets", wireType) + } + m.Sockets = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Sockets |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BytesAcked", wireType) + } + m.BytesAcked = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BytesAcked |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field GoodputBps", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.GoodputBps = float64(math.Float64frombits(v)) + case 5: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field RetransmissionRatio", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.RetransmissionRatio = float64(math.Float64frombits(v)) + case 6: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field RttP95Ms", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.RttP95Ms = float64(math.Float64frombits(v)) + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExposedSockets", wireType) + } + m.ExposedSockets = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ExposedSockets |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CollectionHealthy", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CollectionHealthy = bool(v != 0) + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UnboundSockets", wireType) + } + m.UnboundSockets = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.UnboundSockets |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Evidence) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Evidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Evidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AnalyzedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AnalyzedAt == nil { + m.AnalyzedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.AnalyzedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WindowStart", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.WindowStart == nil { + m.WindowStart = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.WindowStart).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WindowEnd", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.WindowEnd == nil { + m.WindowEnd = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.WindowEnd).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QueryVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.QueryVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EnrichmentVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.EnrichmentVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hosts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hosts = append(m.Hosts, &HostEvidence{}) + if err := m.Hosts[len(m.Hosts)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ArtifactSha256", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ArtifactSha256 = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExperimentPolicy) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExperimentPolicy: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExperimentPolicy: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinimumObservation", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MinimumObservation == nil { + m.MinimumObservation = &durationpb1.Duration{} + } + if err := (*durationpb.Duration)(m.MinimumObservation).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaximumPhase", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MaximumPhase == nil { + m.MaximumPhase = &durationpb1.Duration{} + } + if err := (*durationpb.Duration)(m.MaximumPhase).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinimumSocketsPerHost", wireType) + } + m.MinimumSocketsPerHost = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MinimumSocketsPerHost |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinimumBytesPerHost", wireType) + } + m.MinimumBytesPerHost = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MinimumBytesPerHost |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MinimumTreatedHosts", wireType) + } + m.MinimumTreatedHosts = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MinimumTreatedHosts |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field MinimumImprovement", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.MinimumImprovement = float64(math.Float64frombits(v)) + case 7: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field MaximumRetransmissionIncrease", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.MaximumRetransmissionIncrease = float64(math.Float64frombits(v)) + case 8: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field MaximumRttIncrease", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.MaximumRttIncrease = float64(math.Float64frombits(v)) + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaximumEvidenceAge", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.MaximumEvidenceAge == nil { + m.MaximumEvidenceAge = &durationpb1.Duration{} + } + if err := (*durationpb.Duration)(m.MaximumEvidenceAge).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Phase) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Phase: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Phase: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TargetHosts", wireType) + } + m.TargetHosts = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TargetHosts |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IssuedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IssuedAt == nil { + m.IssuedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.IssuedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObservationStartedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ObservationStartedAt == nil { + m.ObservationStartedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.ObservationStartedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EvaluatedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.EvaluatedAt == nil { + m.EvaluatedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.EvaluatedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Evidence == nil { + m.Evidence = &Evidence{} + } + if err := m.Evidence.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Outcome", wireType) + } + m.Outcome = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Outcome |= Outcome(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reviewer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reviewer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Reason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Experiment) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Experiment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Experiment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Location", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Location = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hypothesis", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hypothesis = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Treatment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Treatment == nil { + m.Treatment = &Treatment{} + } + if err := m.Treatment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Policy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Policy == nil { + m.Policy = &ExperimentPolicy{} + } + if err := m.Policy.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Baseline", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Baseline == nil { + m.Baseline = &Evidence{} + } + if err := m.Baseline.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CohortOrder", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CohortOrder = append(m.CohortOrder, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Phases", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Phases = append(m.Phases, &Phase{}) + if err := m.Phases[len(m.Phases)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= ExperimentStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType) + } + m.Revision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Revision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ProposedAt == nil { + m.ProposedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.ProposedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LatestEvidence", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LatestEvidence == nil { + m.LatestEvidence = &Evidence{} + } + if err := m.LatestEvidence.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LatestOutcome", wireType) + } + m.LatestOutcome = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LatestOutcome |= Outcome(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdatedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UpdatedAt == nil { + m.UpdatedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.UpdatedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/gen/go/xtcp_treatment_journal/journal.pb.go b/gen/go/xtcp_treatment_journal/journal.pb.go new file mode 100644 index 000000000..2ef98a786 --- /dev/null +++ b/gen/go/xtcp_treatment_journal/journal.pb.go @@ -0,0 +1,897 @@ +// +// xTCP - treatment journal +// +// The host-side intent journal of the route treatment agent: the desired +// state last accepted from the controller, the local hold, and one record per +// assignment with the exact kernel route bytes that were installed. It is a +// FILE FORMAT, read and written only on the host by the agent, the watchdog +// and the local treatmentctl commands, and never an RPC payload. +// +// It is a separate proto package from xtcp_treatment.v1 on purpose: the host +// side (pkg/treatment/reconcile, the watchdog) must be able to read and write +// the journal without linking the gRPC service stubs that share a Go package +// with the RPC messages. The messages below therefore repeat the treatment +// shape rather than importing it; pkg/treatment/reconcile converts them to +// and from the domain types, and the domain validators run on every load. +// +// Values of the two enums mirror xtcp_treatment.v1 one-for-one and the domain +// enums in pkg/treatment; reconcile's tests pin the correspondence. +// +// See docs/tcp-controller.md, "Persistence, restart and withdrawal". + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc (unknown) +// source: xtcp_treatment_journal/v1/journal.proto + +package xtcp_treatment_journal + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type AssignmentMode int32 + +const ( + AssignmentMode_ASSIGNMENT_MODE_UNSPECIFIED AssignmentMode = 0 + AssignmentMode_ASSIGNMENT_MODE_TRIAL AssignmentMode = 1 + AssignmentMode_ASSIGNMENT_MODE_STABLE AssignmentMode = 2 + AssignmentMode_ASSIGNMENT_MODE_SUSPENDED AssignmentMode = 3 + AssignmentMode_ASSIGNMENT_MODE_RETIRED AssignmentMode = 4 +) + +// Enum value maps for AssignmentMode. +var ( + AssignmentMode_name = map[int32]string{ + 0: "ASSIGNMENT_MODE_UNSPECIFIED", + 1: "ASSIGNMENT_MODE_TRIAL", + 2: "ASSIGNMENT_MODE_STABLE", + 3: "ASSIGNMENT_MODE_SUSPENDED", + 4: "ASSIGNMENT_MODE_RETIRED", + } + AssignmentMode_value = map[string]int32{ + "ASSIGNMENT_MODE_UNSPECIFIED": 0, + "ASSIGNMENT_MODE_TRIAL": 1, + "ASSIGNMENT_MODE_STABLE": 2, + "ASSIGNMENT_MODE_SUSPENDED": 3, + "ASSIGNMENT_MODE_RETIRED": 4, + } +) + +func (x AssignmentMode) Enum() *AssignmentMode { + p := new(AssignmentMode) + *p = x + return p +} + +func (x AssignmentMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AssignmentMode) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_journal_v1_journal_proto_enumTypes[0].Descriptor() +} + +func (AssignmentMode) Type() protoreflect.EnumType { + return &file_xtcp_treatment_journal_v1_journal_proto_enumTypes[0] +} + +func (x AssignmentMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AssignmentMode.Descriptor instead. +func (AssignmentMode) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{0} +} + +type ApplyStatus int32 + +const ( + ApplyStatus_APPLY_STATUS_UNSPECIFIED ApplyStatus = 0 + ApplyStatus_APPLY_STATUS_PENDING ApplyStatus = 1 + ApplyStatus_APPLY_STATUS_VERIFIED ApplyStatus = 2 + ApplyStatus_APPLY_STATUS_REMOVED ApplyStatus = 3 + ApplyStatus_APPLY_STATUS_EXPIRED ApplyStatus = 4 + ApplyStatus_APPLY_STATUS_FAILED ApplyStatus = 5 +) + +// Enum value maps for ApplyStatus. +var ( + ApplyStatus_name = map[int32]string{ + 0: "APPLY_STATUS_UNSPECIFIED", + 1: "APPLY_STATUS_PENDING", + 2: "APPLY_STATUS_VERIFIED", + 3: "APPLY_STATUS_REMOVED", + 4: "APPLY_STATUS_EXPIRED", + 5: "APPLY_STATUS_FAILED", + } + ApplyStatus_value = map[string]int32{ + "APPLY_STATUS_UNSPECIFIED": 0, + "APPLY_STATUS_PENDING": 1, + "APPLY_STATUS_VERIFIED": 2, + "APPLY_STATUS_REMOVED": 3, + "APPLY_STATUS_EXPIRED": 4, + "APPLY_STATUS_FAILED": 5, + } +) + +func (x ApplyStatus) Enum() *ApplyStatus { + p := new(ApplyStatus) + *p = x + return p +} + +func (x ApplyStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ApplyStatus) Descriptor() protoreflect.EnumDescriptor { + return file_xtcp_treatment_journal_v1_journal_proto_enumTypes[1].Descriptor() +} + +func (ApplyStatus) Type() protoreflect.EnumType { + return &file_xtcp_treatment_journal_v1_journal_proto_enumTypes[1] +} + +func (x ApplyStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ApplyStatus.Descriptor instead. +func (ApplyStatus) EnumDescriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{1} +} + +// TCPSettings mirrors xtcp_treatment.v1.TCPSettings; presence is meaningful. +type TCPSettings struct { + state protoimpl.MessageState `protogen:"open.v1"` + CongestionControl *string `protobuf:"bytes,1,opt,name=congestion_control,json=congestionControl,proto3,oneof" json:"congestion_control,omitempty"` + CongestionLock bool `protobuf:"varint,2,opt,name=congestion_lock,json=congestionLock,proto3" json:"congestion_lock,omitempty"` + RtoMinMs *uint32 `protobuf:"varint,3,opt,name=rto_min_ms,json=rtoMinMs,proto3,oneof" json:"rto_min_ms,omitempty"` + InitialCongestionWindow *uint32 `protobuf:"varint,4,opt,name=initial_congestion_window,json=initialCongestionWindow,proto3,oneof" json:"initial_congestion_window,omitempty"` + InitialReceiveWindow *uint32 `protobuf:"varint,5,opt,name=initial_receive_window,json=initialReceiveWindow,proto3,oneof" json:"initial_receive_window,omitempty"` + QuickAck *bool `protobuf:"varint,6,opt,name=quick_ack,json=quickAck,proto3,oneof" json:"quick_ack,omitempty"` + Ecn *bool `protobuf:"varint,7,opt,name=ecn,proto3,oneof" json:"ecn,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TCPSettings) Reset() { + *x = TCPSettings{} + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TCPSettings) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TCPSettings) ProtoMessage() {} + +func (x *TCPSettings) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TCPSettings.ProtoReflect.Descriptor instead. +func (*TCPSettings) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{0} +} + +func (x *TCPSettings) GetCongestionControl() string { + if x != nil && x.CongestionControl != nil { + return *x.CongestionControl + } + return "" +} + +func (x *TCPSettings) GetCongestionLock() bool { + if x != nil { + return x.CongestionLock + } + return false +} + +func (x *TCPSettings) GetRtoMinMs() uint32 { + if x != nil && x.RtoMinMs != nil { + return *x.RtoMinMs + } + return 0 +} + +func (x *TCPSettings) GetInitialCongestionWindow() uint32 { + if x != nil && x.InitialCongestionWindow != nil { + return *x.InitialCongestionWindow + } + return 0 +} + +func (x *TCPSettings) GetInitialReceiveWindow() uint32 { + if x != nil && x.InitialReceiveWindow != nil { + return *x.InitialReceiveWindow + } + return 0 +} + +func (x *TCPSettings) GetQuickAck() bool { + if x != nil && x.QuickAck != nil { + return *x.QuickAck + } + return false +} + +func (x *TCPSettings) GetEcn() bool { + if x != nil && x.Ecn != nil { + return *x.Ecn + } + return false +} + +type Treatment struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Revision uint64 `protobuf:"varint,2,opt,name=revision,proto3" json:"revision,omitempty"` + // Canonical /32 or /128 host prefix. + Destination string `protobuf:"bytes,3,opt,name=destination,proto3" json:"destination,omitempty"` + Settings *TCPSettings `protobuf:"bytes,4,opt,name=settings,proto3" json:"settings,omitempty"` + EcnFabricVerified bool `protobuf:"varint,5,opt,name=ecn_fabric_verified,json=ecnFabricVerified,proto3" json:"ecn_fabric_verified,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Treatment) Reset() { + *x = Treatment{} + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Treatment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Treatment) ProtoMessage() {} + +func (x *Treatment) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Treatment.ProtoReflect.Descriptor instead. +func (*Treatment) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{1} +} + +func (x *Treatment) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Treatment) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *Treatment) GetDestination() string { + if x != nil { + return x.Destination + } + return "" +} + +func (x *Treatment) GetSettings() *TCPSettings { + if x != nil { + return x.Settings + } + return nil +} + +func (x *Treatment) GetEcnFabricVerified() bool { + if x != nil { + return x.EcnFabricVerified + } + return false +} + +type Assignment struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExperimentId string `protobuf:"bytes,1,opt,name=experiment_id,json=experimentId,proto3" json:"experiment_id,omitempty"` + Treatment *Treatment `protobuf:"bytes,2,opt,name=treatment,proto3" json:"treatment,omitempty"` + Mode AssignmentMode `protobuf:"varint,3,opt,name=mode,proto3,enum=xtcp_treatment_journal.v1.AssignmentMode" json:"mode,omitempty"` + LeaseExpiresAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=lease_expires_at,json=leaseExpiresAt,proto3" json:"lease_expires_at,omitempty"` + Predecessor *Treatment `protobuf:"bytes,5,opt,name=predecessor,proto3" json:"predecessor,omitempty"` + Generation uint64 `protobuf:"varint,6,opt,name=generation,proto3" json:"generation,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Assignment) Reset() { + *x = Assignment{} + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Assignment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Assignment) ProtoMessage() {} + +func (x *Assignment) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Assignment.ProtoReflect.Descriptor instead. +func (*Assignment) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{2} +} + +func (x *Assignment) GetExperimentId() string { + if x != nil { + return x.ExperimentId + } + return "" +} + +func (x *Assignment) GetTreatment() *Treatment { + if x != nil { + return x.Treatment + } + return nil +} + +func (x *Assignment) GetMode() AssignmentMode { + if x != nil { + return x.Mode + } + return AssignmentMode_ASSIGNMENT_MODE_UNSPECIFIED +} + +func (x *Assignment) GetLeaseExpiresAt() *timestamppb.Timestamp { + if x != nil { + return x.LeaseExpiresAt + } + return nil +} + +func (x *Assignment) GetPredecessor() *Treatment { + if x != nil { + return x.Predecessor + } + return nil +} + +func (x *Assignment) GetGeneration() uint64 { + if x != nil { + return x.Generation + } + return 0 +} + +// Desired is the controller's last accepted snapshot for this agent. The +// agent identity lives on the Journal header. +type Desired struct { + state protoimpl.MessageState `protogen:"open.v1"` + Revision uint64 `protobuf:"varint,1,opt,name=revision,proto3" json:"revision,omitempty"` + Suspended bool `protobuf:"varint,2,opt,name=suspended,proto3" json:"suspended,omitempty"` + IssuedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=issued_at,json=issuedAt,proto3" json:"issued_at,omitempty"` + Assignments []*Assignment `protobuf:"bytes,4,rep,name=assignments,proto3" json:"assignments,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Desired) Reset() { + *x = Desired{} + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Desired) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Desired) ProtoMessage() {} + +func (x *Desired) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Desired.ProtoReflect.Descriptor instead. +func (*Desired) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{3} +} + +func (x *Desired) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *Desired) GetSuspended() bool { + if x != nil { + return x.Suspended + } + return false +} + +func (x *Desired) GetIssuedAt() *timestamppb.Timestamp { + if x != nil { + return x.IssuedAt + } + return nil +} + +func (x *Desired) GetAssignments() []*Assignment { + if x != nil { + return x.Assignments + } + return nil +} + +// Record is the agent's account of one assignment plus the kernel-local +// facts (installed route bytes, installing boot) that never leave the host. +type Record struct { + state protoimpl.MessageState `protogen:"open.v1"` + Assignment *Assignment `protobuf:"bytes,1,opt,name=assignment,proto3" json:"assignment,omitempty"` + DesiredRevision uint64 `protobuf:"varint,2,opt,name=desired_revision,json=desiredRevision,proto3" json:"desired_revision,omitempty"` + Status ApplyStatus `protobuf:"varint,3,opt,name=status,proto3,enum=xtcp_treatment_journal.v1.ApplyStatus" json:"status,omitempty"` + ReceivedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=received_at,json=receivedAt,proto3" json:"received_at,omitempty"` + AttemptedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=attempted_at,json=attemptedAt,proto3" json:"attempted_at,omitempty"` + AppliedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=applied_at,json=appliedAt,proto3" json:"applied_at,omitempty"` + VerifiedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=verified_at,json=verifiedAt,proto3" json:"verified_at,omitempty"` + RemovedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=removed_at,json=removedAt,proto3" json:"removed_at,omitempty"` + Error string `protobuf:"bytes,9,opt,name=error,proto3" json:"error,omitempty"` + // Locally planned canonical netlink route body, the only thing Remove will + // ever be asked to withdraw. + InstalledRoute []byte `protobuf:"bytes,10,opt,name=installed_route,json=installedRoute,proto3" json:"installed_route,omitempty"` + InstalledBootId string `protobuf:"bytes,11,opt,name=installed_boot_id,json=installedBootId,proto3" json:"installed_boot_id,omitempty"` + ExpiredLatched bool `protobuf:"varint,12,opt,name=expired_latched,json=expiredLatched,proto3" json:"expired_latched,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Record) Reset() { + *x = Record{} + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Record) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Record) ProtoMessage() {} + +func (x *Record) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Record.ProtoReflect.Descriptor instead. +func (*Record) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{4} +} + +func (x *Record) GetAssignment() *Assignment { + if x != nil { + return x.Assignment + } + return nil +} + +func (x *Record) GetDesiredRevision() uint64 { + if x != nil { + return x.DesiredRevision + } + return 0 +} + +func (x *Record) GetStatus() ApplyStatus { + if x != nil { + return x.Status + } + return ApplyStatus_APPLY_STATUS_UNSPECIFIED +} + +func (x *Record) GetReceivedAt() *timestamppb.Timestamp { + if x != nil { + return x.ReceivedAt + } + return nil +} + +func (x *Record) GetAttemptedAt() *timestamppb.Timestamp { + if x != nil { + return x.AttemptedAt + } + return nil +} + +func (x *Record) GetAppliedAt() *timestamppb.Timestamp { + if x != nil { + return x.AppliedAt + } + return nil +} + +func (x *Record) GetVerifiedAt() *timestamppb.Timestamp { + if x != nil { + return x.VerifiedAt + } + return nil +} + +func (x *Record) GetRemovedAt() *timestamppb.Timestamp { + if x != nil { + return x.RemovedAt + } + return nil +} + +func (x *Record) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *Record) GetInstalledRoute() []byte { + if x != nil { + return x.InstalledRoute + } + return nil +} + +func (x *Record) GetInstalledBootId() string { + if x != nil { + return x.InstalledBootId + } + return "" +} + +func (x *Record) GetExpiredLatched() bool { + if x != nil { + return x.ExpiredLatched + } + return false +} + +// Journal is the atomic snapshot in /state.textproto. The header +// identifies the writer so a journal can never be reconciled for another +// agent and so a telemetry-only daemon can attribute records from it. +type Journal struct { + state protoimpl.MessageState `protogen:"open.v1"` + AgentId string `protobuf:"bytes,1,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` + Location string `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` + // Boot that last wrote the journal; per-record installed_boot_id says + // which boot installed each route. + BootId string `protobuf:"bytes,3,opt,name=boot_id,json=bootId,proto3" json:"boot_id,omitempty"` + Desired *Desired `protobuf:"bytes,4,opt,name=desired,proto3" json:"desired,omitempty"` + LocallySuspended bool `protobuf:"varint,5,opt,name=locally_suspended,json=locallySuspended,proto3" json:"locally_suspended,omitempty"` + SuspensionReason string `protobuf:"bytes,6,opt,name=suspension_reason,json=suspensionReason,proto3" json:"suspension_reason,omitempty"` + Records []*Record `protobuf:"bytes,7,rep,name=records,proto3" json:"records,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + // Per-process nonce of the agent that owns the journal. The agent writes + // it; the watchdog preserves it; a telemetry-only daemon stamps it into + // records as collection_id. + CollectionId string `protobuf:"bytes,9,opt,name=collection_id,json=collectionId,proto3" json:"collection_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Journal) Reset() { + *x = Journal{} + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Journal) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Journal) ProtoMessage() {} + +func (x *Journal) ProtoReflect() protoreflect.Message { + mi := &file_xtcp_treatment_journal_v1_journal_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Journal.ProtoReflect.Descriptor instead. +func (*Journal) Descriptor() ([]byte, []int) { + return file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP(), []int{5} +} + +func (x *Journal) GetAgentId() string { + if x != nil { + return x.AgentId + } + return "" +} + +func (x *Journal) GetLocation() string { + if x != nil { + return x.Location + } + return "" +} + +func (x *Journal) GetBootId() string { + if x != nil { + return x.BootId + } + return "" +} + +func (x *Journal) GetDesired() *Desired { + if x != nil { + return x.Desired + } + return nil +} + +func (x *Journal) GetLocallySuspended() bool { + if x != nil { + return x.LocallySuspended + } + return false +} + +func (x *Journal) GetSuspensionReason() string { + if x != nil { + return x.SuspensionReason + } + return "" +} + +func (x *Journal) GetRecords() []*Record { + if x != nil { + return x.Records + } + return nil +} + +func (x *Journal) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +func (x *Journal) GetCollectionId() string { + if x != nil { + return x.CollectionId + } + return "" +} + +var File_xtcp_treatment_journal_v1_journal_proto protoreflect.FileDescriptor + +const file_xtcp_treatment_journal_v1_journal_proto_rawDesc = "" + + "\n" + + "'xtcp_treatment_journal/v1/journal.proto\x12\x19xtcp_treatment_journal.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb7\x03\n" + + "\vTCPSettings\x122\n" + + "\x12congestion_control\x18\x01 \x01(\tH\x00R\x11congestionControl\x88\x01\x01\x12'\n" + + "\x0fcongestion_lock\x18\x02 \x01(\bR\x0econgestionLock\x12!\n" + + "\n" + + "rto_min_ms\x18\x03 \x01(\rH\x01R\brtoMinMs\x88\x01\x01\x12?\n" + + "\x19initial_congestion_window\x18\x04 \x01(\rH\x02R\x17initialCongestionWindow\x88\x01\x01\x129\n" + + "\x16initial_receive_window\x18\x05 \x01(\rH\x03R\x14initialReceiveWindow\x88\x01\x01\x12 \n" + + "\tquick_ack\x18\x06 \x01(\bH\x04R\bquickAck\x88\x01\x01\x12\x15\n" + + "\x03ecn\x18\a \x01(\bH\x05R\x03ecn\x88\x01\x01B\x15\n" + + "\x13_congestion_controlB\r\n" + + "\v_rto_min_msB\x1c\n" + + "\x1a_initial_congestion_windowB\x19\n" + + "\x17_initial_receive_windowB\f\n" + + "\n" + + "_quick_ackB\x06\n" + + "\x04_ecn\"\xcd\x01\n" + + "\tTreatment\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1a\n" + + "\brevision\x18\x02 \x01(\x04R\brevision\x12 \n" + + "\vdestination\x18\x03 \x01(\tR\vdestination\x12B\n" + + "\bsettings\x18\x04 \x01(\v2&.xtcp_treatment_journal.v1.TCPSettingsR\bsettings\x12.\n" + + "\x13ecn_fabric_verified\x18\x05 \x01(\bR\x11ecnFabricVerified\"\xe2\x02\n" + + "\n" + + "Assignment\x12#\n" + + "\rexperiment_id\x18\x01 \x01(\tR\fexperimentId\x12B\n" + + "\ttreatment\x18\x02 \x01(\v2$.xtcp_treatment_journal.v1.TreatmentR\ttreatment\x12=\n" + + "\x04mode\x18\x03 \x01(\x0e2).xtcp_treatment_journal.v1.AssignmentModeR\x04mode\x12D\n" + + "\x10lease_expires_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\x0eleaseExpiresAt\x12F\n" + + "\vpredecessor\x18\x05 \x01(\v2$.xtcp_treatment_journal.v1.TreatmentR\vpredecessor\x12\x1e\n" + + "\n" + + "generation\x18\x06 \x01(\x04R\n" + + "generation\"\xc5\x01\n" + + "\aDesired\x12\x1a\n" + + "\brevision\x18\x01 \x01(\x04R\brevision\x12\x1c\n" + + "\tsuspended\x18\x02 \x01(\bR\tsuspended\x127\n" + + "\tissued_at\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\bissuedAt\x12G\n" + + "\vassignments\x18\x04 \x03(\v2%.xtcp_treatment_journal.v1.AssignmentR\vassignments\"\xfd\x04\n" + + "\x06Record\x12E\n" + + "\n" + + "assignment\x18\x01 \x01(\v2%.xtcp_treatment_journal.v1.AssignmentR\n" + + "assignment\x12)\n" + + "\x10desired_revision\x18\x02 \x01(\x04R\x0fdesiredRevision\x12>\n" + + "\x06status\x18\x03 \x01(\x0e2&.xtcp_treatment_journal.v1.ApplyStatusR\x06status\x12;\n" + + "\vreceived_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "receivedAt\x12=\n" + + "\fattempted_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\vattemptedAt\x129\n" + + "\n" + + "applied_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tappliedAt\x12;\n" + + "\vverified_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "verifiedAt\x129\n" + + "\n" + + "removed_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tremovedAt\x12\x14\n" + + "\x05error\x18\t \x01(\tR\x05error\x12'\n" + + "\x0finstalled_route\x18\n" + + " \x01(\fR\x0einstalledRoute\x12*\n" + + "\x11installed_boot_id\x18\v \x01(\tR\x0finstalledBootId\x12'\n" + + "\x0fexpired_latched\x18\f \x01(\bR\x0eexpiredLatched\"\x8e\x03\n" + + "\aJournal\x12\x19\n" + + "\bagent_id\x18\x01 \x01(\tR\aagentId\x12\x1a\n" + + "\blocation\x18\x02 \x01(\tR\blocation\x12\x17\n" + + "\aboot_id\x18\x03 \x01(\tR\x06bootId\x12<\n" + + "\adesired\x18\x04 \x01(\v2\".xtcp_treatment_journal.v1.DesiredR\adesired\x12+\n" + + "\x11locally_suspended\x18\x05 \x01(\bR\x10locallySuspended\x12+\n" + + "\x11suspension_reason\x18\x06 \x01(\tR\x10suspensionReason\x12;\n" + + "\arecords\x18\a \x03(\v2!.xtcp_treatment_journal.v1.RecordR\arecords\x129\n" + + "\n" + + "updated_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12#\n" + + "\rcollection_id\x18\t \x01(\tR\fcollectionId*\xa4\x01\n" + + "\x0eAssignmentMode\x12\x1f\n" + + "\x1bASSIGNMENT_MODE_UNSPECIFIED\x10\x00\x12\x19\n" + + "\x15ASSIGNMENT_MODE_TRIAL\x10\x01\x12\x1a\n" + + "\x16ASSIGNMENT_MODE_STABLE\x10\x02\x12\x1d\n" + + "\x19ASSIGNMENT_MODE_SUSPENDED\x10\x03\x12\x1b\n" + + "\x17ASSIGNMENT_MODE_RETIRED\x10\x04*\xad\x01\n" + + "\vApplyStatus\x12\x1c\n" + + "\x18APPLY_STATUS_UNSPECIFIED\x10\x00\x12\x18\n" + + "\x14APPLY_STATUS_PENDING\x10\x01\x12\x19\n" + + "\x15APPLY_STATUS_VERIFIED\x10\x02\x12\x18\n" + + "\x14APPLY_STATUS_REMOVED\x10\x03\x12\x18\n" + + "\x14APPLY_STATUS_EXPIRED\x10\x04\x12\x17\n" + + "\x13APPLY_STATUS_FAILED\x10\x05B\xea\x01\n" + + "\x1dcom.xtcp_treatment_journal.v1B\fJournalProtoP\x01Z>github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment_journal\xa2\x02\x03XXX\xaa\x02\x17XtcpTreatmentJournal.V1\xca\x02\x17XtcpTreatmentJournal\\V1\xe2\x02#XtcpTreatmentJournal\\V1\\GPBMetadata\xea\x02\x18XtcpTreatmentJournal::V1b\x06proto3" + +var ( + file_xtcp_treatment_journal_v1_journal_proto_rawDescOnce sync.Once + file_xtcp_treatment_journal_v1_journal_proto_rawDescData []byte +) + +func file_xtcp_treatment_journal_v1_journal_proto_rawDescGZIP() []byte { + file_xtcp_treatment_journal_v1_journal_proto_rawDescOnce.Do(func() { + file_xtcp_treatment_journal_v1_journal_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_xtcp_treatment_journal_v1_journal_proto_rawDesc), len(file_xtcp_treatment_journal_v1_journal_proto_rawDesc))) + }) + return file_xtcp_treatment_journal_v1_journal_proto_rawDescData +} + +var file_xtcp_treatment_journal_v1_journal_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_xtcp_treatment_journal_v1_journal_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_xtcp_treatment_journal_v1_journal_proto_goTypes = []any{ + (AssignmentMode)(0), // 0: xtcp_treatment_journal.v1.AssignmentMode + (ApplyStatus)(0), // 1: xtcp_treatment_journal.v1.ApplyStatus + (*TCPSettings)(nil), // 2: xtcp_treatment_journal.v1.TCPSettings + (*Treatment)(nil), // 3: xtcp_treatment_journal.v1.Treatment + (*Assignment)(nil), // 4: xtcp_treatment_journal.v1.Assignment + (*Desired)(nil), // 5: xtcp_treatment_journal.v1.Desired + (*Record)(nil), // 6: xtcp_treatment_journal.v1.Record + (*Journal)(nil), // 7: xtcp_treatment_journal.v1.Journal + (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp +} +var file_xtcp_treatment_journal_v1_journal_proto_depIdxs = []int32{ + 2, // 0: xtcp_treatment_journal.v1.Treatment.settings:type_name -> xtcp_treatment_journal.v1.TCPSettings + 3, // 1: xtcp_treatment_journal.v1.Assignment.treatment:type_name -> xtcp_treatment_journal.v1.Treatment + 0, // 2: xtcp_treatment_journal.v1.Assignment.mode:type_name -> xtcp_treatment_journal.v1.AssignmentMode + 8, // 3: xtcp_treatment_journal.v1.Assignment.lease_expires_at:type_name -> google.protobuf.Timestamp + 3, // 4: xtcp_treatment_journal.v1.Assignment.predecessor:type_name -> xtcp_treatment_journal.v1.Treatment + 8, // 5: xtcp_treatment_journal.v1.Desired.issued_at:type_name -> google.protobuf.Timestamp + 4, // 6: xtcp_treatment_journal.v1.Desired.assignments:type_name -> xtcp_treatment_journal.v1.Assignment + 4, // 7: xtcp_treatment_journal.v1.Record.assignment:type_name -> xtcp_treatment_journal.v1.Assignment + 1, // 8: xtcp_treatment_journal.v1.Record.status:type_name -> xtcp_treatment_journal.v1.ApplyStatus + 8, // 9: xtcp_treatment_journal.v1.Record.received_at:type_name -> google.protobuf.Timestamp + 8, // 10: xtcp_treatment_journal.v1.Record.attempted_at:type_name -> google.protobuf.Timestamp + 8, // 11: xtcp_treatment_journal.v1.Record.applied_at:type_name -> google.protobuf.Timestamp + 8, // 12: xtcp_treatment_journal.v1.Record.verified_at:type_name -> google.protobuf.Timestamp + 8, // 13: xtcp_treatment_journal.v1.Record.removed_at:type_name -> google.protobuf.Timestamp + 5, // 14: xtcp_treatment_journal.v1.Journal.desired:type_name -> xtcp_treatment_journal.v1.Desired + 6, // 15: xtcp_treatment_journal.v1.Journal.records:type_name -> xtcp_treatment_journal.v1.Record + 8, // 16: xtcp_treatment_journal.v1.Journal.updated_at:type_name -> google.protobuf.Timestamp + 17, // [17:17] is the sub-list for method output_type + 17, // [17:17] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name +} + +func init() { file_xtcp_treatment_journal_v1_journal_proto_init() } +func file_xtcp_treatment_journal_v1_journal_proto_init() { + if File_xtcp_treatment_journal_v1_journal_proto != nil { + return + } + file_xtcp_treatment_journal_v1_journal_proto_msgTypes[0].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_xtcp_treatment_journal_v1_journal_proto_rawDesc), len(file_xtcp_treatment_journal_v1_journal_proto_rawDesc)), + NumEnums: 2, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_xtcp_treatment_journal_v1_journal_proto_goTypes, + DependencyIndexes: file_xtcp_treatment_journal_v1_journal_proto_depIdxs, + EnumInfos: file_xtcp_treatment_journal_v1_journal_proto_enumTypes, + MessageInfos: file_xtcp_treatment_journal_v1_journal_proto_msgTypes, + }.Build() + File_xtcp_treatment_journal_v1_journal_proto = out.File + file_xtcp_treatment_journal_v1_journal_proto_goTypes = nil + file_xtcp_treatment_journal_v1_journal_proto_depIdxs = nil +} diff --git a/gen/go/xtcp_treatment_journal/journal_vtproto.pb.go b/gen/go/xtcp_treatment_journal/journal_vtproto.pb.go new file mode 100644 index 000000000..3eeb5acf7 --- /dev/null +++ b/gen/go/xtcp_treatment_journal/journal_vtproto.pb.go @@ -0,0 +1,2338 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: (devel) +// source: xtcp_treatment_journal/v1/journal.proto + +package xtcp_treatment_journal + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + timestamppb "github.com/planetscale/vtprotobuf/types/known/timestamppb" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb1 "google.golang.org/protobuf/types/known/timestamppb" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *TCPSettings) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TCPSettings) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *TCPSettings) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Ecn != nil { + i-- + if *m.Ecn { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x38 + } + if m.QuickAck != nil { + i-- + if *m.QuickAck { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + if m.InitialReceiveWindow != nil { + i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.InitialReceiveWindow)) + i-- + dAtA[i] = 0x28 + } + if m.InitialCongestionWindow != nil { + i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.InitialCongestionWindow)) + i-- + dAtA[i] = 0x20 + } + if m.RtoMinMs != nil { + i = protohelpers.EncodeVarint(dAtA, i, uint64(*m.RtoMinMs)) + i-- + dAtA[i] = 0x18 + } + if m.CongestionLock { + i-- + if m.CongestionLock { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if m.CongestionControl != nil { + i -= len(*m.CongestionControl) + copy(dAtA[i:], *m.CongestionControl) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(*m.CongestionControl))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Treatment) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Treatment) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Treatment) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.EcnFabricVerified { + i-- + if m.EcnFabricVerified { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.Settings != nil { + size, err := m.Settings.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if len(m.Destination) > 0 { + i -= len(m.Destination) + copy(dAtA[i:], m.Destination) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Destination))) + i-- + dAtA[i] = 0x1a + } + if m.Revision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Revision)) + i-- + dAtA[i] = 0x10 + } + if len(m.Id) > 0 { + i -= len(m.Id) + copy(dAtA[i:], m.Id) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Id))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Assignment) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Assignment) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Assignment) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Generation != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Generation)) + i-- + dAtA[i] = 0x30 + } + if m.Predecessor != nil { + size, err := m.Predecessor.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if m.LeaseExpiresAt != nil { + size, err := (*timestamppb.Timestamp)(m.LeaseExpiresAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if m.Mode != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Mode)) + i-- + dAtA[i] = 0x18 + } + if m.Treatment != nil { + size, err := m.Treatment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 + } + if len(m.ExperimentId) > 0 { + i -= len(m.ExperimentId) + copy(dAtA[i:], m.ExperimentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.ExperimentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Desired) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Desired) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Desired) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Assignments) > 0 { + for iNdEx := len(m.Assignments) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Assignments[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if m.IssuedAt != nil { + size, err := (*timestamppb.Timestamp)(m.IssuedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + if m.Suspended { + i-- + if m.Suspended { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if m.Revision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Revision)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Record) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Record) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Record) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.ExpiredLatched { + i-- + if m.ExpiredLatched { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x60 + } + if len(m.InstalledBootId) > 0 { + i -= len(m.InstalledBootId) + copy(dAtA[i:], m.InstalledBootId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.InstalledBootId))) + i-- + dAtA[i] = 0x5a + } + if len(m.InstalledRoute) > 0 { + i -= len(m.InstalledRoute) + copy(dAtA[i:], m.InstalledRoute) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.InstalledRoute))) + i-- + dAtA[i] = 0x52 + } + if len(m.Error) > 0 { + i -= len(m.Error) + copy(dAtA[i:], m.Error) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Error))) + i-- + dAtA[i] = 0x4a + } + if m.RemovedAt != nil { + size, err := (*timestamppb.Timestamp)(m.RemovedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x42 + } + if m.VerifiedAt != nil { + size, err := (*timestamppb.Timestamp)(m.VerifiedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x3a + } + if m.AppliedAt != nil { + size, err := (*timestamppb.Timestamp)(m.AppliedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x32 + } + if m.AttemptedAt != nil { + size, err := (*timestamppb.Timestamp)(m.AttemptedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + if m.ReceivedAt != nil { + size, err := (*timestamppb.Timestamp)(m.ReceivedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if m.Status != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x18 + } + if m.DesiredRevision != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.DesiredRevision)) + i-- + dAtA[i] = 0x10 + } + if m.Assignment != nil { + size, err := m.Assignment.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Journal) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Journal) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *Journal) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.CollectionId) > 0 { + i -= len(m.CollectionId) + copy(dAtA[i:], m.CollectionId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.CollectionId))) + i-- + dAtA[i] = 0x4a + } + if m.UpdatedAt != nil { + size, err := (*timestamppb.Timestamp)(m.UpdatedAt).MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x42 + } + if len(m.Records) > 0 { + for iNdEx := len(m.Records) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Records[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x3a + } + } + if len(m.SuspensionReason) > 0 { + i -= len(m.SuspensionReason) + copy(dAtA[i:], m.SuspensionReason) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SuspensionReason))) + i-- + dAtA[i] = 0x32 + } + if m.LocallySuspended { + i-- + if m.LocallySuspended { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } + if m.Desired != nil { + size, err := m.Desired.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if len(m.BootId) > 0 { + i -= len(m.BootId) + copy(dAtA[i:], m.BootId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.BootId))) + i-- + dAtA[i] = 0x1a + } + if len(m.Location) > 0 { + i -= len(m.Location) + copy(dAtA[i:], m.Location) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Location))) + i-- + dAtA[i] = 0x12 + } + if len(m.AgentId) > 0 { + i -= len(m.AgentId) + copy(dAtA[i:], m.AgentId) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.AgentId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TCPSettings) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.CongestionControl != nil { + l = len(*m.CongestionControl) + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.CongestionLock { + n += 2 + } + if m.RtoMinMs != nil { + n += 1 + protohelpers.SizeOfVarint(uint64(*m.RtoMinMs)) + } + if m.InitialCongestionWindow != nil { + n += 1 + protohelpers.SizeOfVarint(uint64(*m.InitialCongestionWindow)) + } + if m.InitialReceiveWindow != nil { + n += 1 + protohelpers.SizeOfVarint(uint64(*m.InitialReceiveWindow)) + } + if m.QuickAck != nil { + n += 2 + } + if m.Ecn != nil { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *Treatment) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Id) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Revision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Revision)) + } + l = len(m.Destination) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Settings != nil { + l = m.Settings.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.EcnFabricVerified { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *Assignment) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ExperimentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Treatment != nil { + l = m.Treatment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Mode != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Mode)) + } + if m.LeaseExpiresAt != nil { + l = (*timestamppb.Timestamp)(m.LeaseExpiresAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Predecessor != nil { + l = m.Predecessor.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Generation != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Generation)) + } + n += len(m.unknownFields) + return n +} + +func (m *Desired) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Revision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Revision)) + } + if m.Suspended { + n += 2 + } + if m.IssuedAt != nil { + l = (*timestamppb.Timestamp)(m.IssuedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.Assignments) > 0 { + for _, e := range m.Assignments { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *Record) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Assignment != nil { + l = m.Assignment.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.DesiredRevision != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.DesiredRevision)) + } + if m.Status != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Status)) + } + if m.ReceivedAt != nil { + l = (*timestamppb.Timestamp)(m.ReceivedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.AttemptedAt != nil { + l = (*timestamppb.Timestamp)(m.AttemptedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.AppliedAt != nil { + l = (*timestamppb.Timestamp)(m.AppliedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.VerifiedAt != nil { + l = (*timestamppb.Timestamp)(m.VerifiedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.RemovedAt != nil { + l = (*timestamppb.Timestamp)(m.RemovedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Error) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.InstalledRoute) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.InstalledBootId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.ExpiredLatched { + n += 2 + } + n += len(m.unknownFields) + return n +} + +func (m *Journal) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AgentId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Location) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.BootId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Desired != nil { + l = m.Desired.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.LocallySuspended { + n += 2 + } + l = len(m.SuspensionReason) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.Records) > 0 { + for _, e := range m.Records { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + if m.UpdatedAt != nil { + l = (*timestamppb.Timestamp)(m.UpdatedAt).SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.CollectionId) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *TCPSettings) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TCPSettings: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TCPSettings: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CongestionControl", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := string(dAtA[iNdEx:postIndex]) + m.CongestionControl = &s + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CongestionLock", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.CongestionLock = bool(v != 0) + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field RtoMinMs", wireType) + } + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.RtoMinMs = &v + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialCongestionWindow", wireType) + } + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.InitialCongestionWindow = &v + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field InitialReceiveWindow", wireType) + } + var v uint32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.InitialReceiveWindow = &v + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field QuickAck", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.QuickAck = &b + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Ecn", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.Ecn = &b + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Treatment) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Treatment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Treatment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Id = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType) + } + m.Revision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Revision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Destination", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Destination = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Settings", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Settings == nil { + m.Settings = &TCPSettings{} + } + if err := m.Settings.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EcnFabricVerified", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.EcnFabricVerified = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Assignment) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Assignment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Assignment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExperimentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExperimentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Treatment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Treatment == nil { + m.Treatment = &Treatment{} + } + if err := m.Treatment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + m.Mode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Mode |= AssignmentMode(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeaseExpiresAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.LeaseExpiresAt == nil { + m.LeaseExpiresAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.LeaseExpiresAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Predecessor", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Predecessor == nil { + m.Predecessor = &Treatment{} + } + if err := m.Predecessor.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Generation", wireType) + } + m.Generation = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Generation |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Desired) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Desired: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Desired: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType) + } + m.Revision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Revision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Suspended", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Suspended = bool(v != 0) + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IssuedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.IssuedAt == nil { + m.IssuedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.IssuedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Assignments", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Assignments = append(m.Assignments, &Assignment{}) + if err := m.Assignments[len(m.Assignments)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Record) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Record: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Record: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Assignment", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Assignment == nil { + m.Assignment = &Assignment{} + } + if err := m.Assignment.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DesiredRevision", wireType) + } + m.DesiredRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DesiredRevision |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= ApplyStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ReceivedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ReceivedAt == nil { + m.ReceivedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.ReceivedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AttemptedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AttemptedAt == nil { + m.AttemptedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.AttemptedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppliedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.AppliedAt == nil { + m.AppliedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.AppliedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VerifiedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.VerifiedAt == nil { + m.VerifiedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.VerifiedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RemovedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RemovedAt == nil { + m.RemovedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.RemovedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InstalledRoute", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InstalledRoute = append(m.InstalledRoute[:0], dAtA[iNdEx:postIndex]...) + if m.InstalledRoute == nil { + m.InstalledRoute = []byte{} + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InstalledBootId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.InstalledBootId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExpiredLatched", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ExpiredLatched = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Journal) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Journal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Journal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AgentId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AgentId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Location", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Location = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BootId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BootId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Desired", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Desired == nil { + m.Desired = &Desired{} + } + if err := m.Desired.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LocallySuspended", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.LocallySuspended = bool(v != 0) + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SuspensionReason", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SuspensionReason = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Records = append(m.Records, &Record{}) + if err := m.Records[len(m.Records)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpdatedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UpdatedAt == nil { + m.UpdatedAt = ×tamppb1.Timestamp{} + } + if err := (*timestamppb.Timestamp)(m.UpdatedAt).UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CollectionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CollectionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/gen/openapi/xtcp_treatment/v1/agent.swagger.json b/gen/openapi/xtcp_treatment/v1/agent.swagger.json new file mode 100644 index 000000000..3cfab79d6 --- /dev/null +++ b/gen/openapi/xtcp_treatment/v1/agent.swagger.json @@ -0,0 +1,49 @@ +{ + "swagger": "2.0", + "info": { + "title": "xtcp_treatment/v1/agent.proto", + "version": "version not set" + }, + "tags": [ + { + "name": "AgentControlService" + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": true + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/gen/openapi/xtcp_treatment/v1/operator.swagger.json b/gen/openapi/xtcp_treatment/v1/operator.swagger.json new file mode 100644 index 000000000..eada7abea --- /dev/null +++ b/gen/openapi/xtcp_treatment/v1/operator.swagger.json @@ -0,0 +1,49 @@ +{ + "swagger": "2.0", + "info": { + "title": "xtcp_treatment/v1/operator.proto", + "version": "version not set" + }, + "tags": [ + { + "name": "OperatorService" + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": true + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/gen/openapi/xtcp_treatment/v1/treatment.swagger.json b/gen/openapi/xtcp_treatment/v1/treatment.swagger.json new file mode 100644 index 000000000..f50b3cdd6 --- /dev/null +++ b/gen/openapi/xtcp_treatment/v1/treatment.swagger.json @@ -0,0 +1,44 @@ +{ + "swagger": "2.0", + "info": { + "title": "xtcp_treatment/v1/treatment.proto", + "version": "version not set" + }, + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": true + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/gen/openapi/xtcp_treatment_journal/v1/journal.swagger.json b/gen/openapi/xtcp_treatment_journal/v1/journal.swagger.json new file mode 100644 index 000000000..20340a399 --- /dev/null +++ b/gen/openapi/xtcp_treatment_journal/v1/journal.swagger.json @@ -0,0 +1,44 @@ +{ + "swagger": "2.0", + "info": { + "title": "xtcp_treatment_journal/v1/journal.proto", + "version": "version not set" + }, + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": {}, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": true + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + } + } +} diff --git a/gen/python/xtcp_treatment/v1/agent_pb2.py b/gen/python/xtcp_treatment/v1/agent_pb2.py new file mode 100644 index 000000000..b9f238e2c --- /dev/null +++ b/gen/python/xtcp_treatment/v1/agent_pb2.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: xtcp_treatment/v1/agent.proto +# Protobuf Python Version: 7.36.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 36, + 2, + '', + 'xtcp_treatment/v1/agent.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from buf.validate import validate_pb2 as buf_dot_validate_dot_validate__pb2 +from xtcp_treatment.v1 import treatment_pb2 as xtcp__treatment_dot_v1_dot_treatment__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1dxtcp_treatment/v1/agent.proto\x12\x11xtcp_treatment.v1\x1a\x1b\x62uf/validate/validate.proto\x1a!xtcp_treatment/v1/treatment.proto\"\x8d\x03\n\x0e\x43heckInRequest\x12\x44\n\x08\x61gent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x07\x61gentId\x12\x45\n\x08location\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x08location\x12K\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32\x1f.xtcp_treatment.v1.CapabilitiesB\x06\xbaH\x03\xc8\x01\x01R\x0c\x63\x61pabilities\x12)\n\x10\x64\x65sired_revision\x18\x04 \x01(\x04R\x0f\x64\x65siredRevision\x12I\n\x07records\x18\x05 \x03(\x0b\x32$.xtcp_treatment.v1.ApplicationRecordB\t\xbaH\x06\x92\x01\x03\x10\x80@R\x07records\x12+\n\x11locally_suspended\x18\x06 \x01(\x08R\x10locallySuspended\"L\n\x0f\x43heckInResponse\x12\x39\n\x07\x64\x65sired\x18\x01 \x01(\x0b\x32\x1f.xtcp_treatment.v1.DesiredStateR\x07\x64\x65sired\"^\n\x16GetDesiredStateRequest\x12\x44\n\x08\x61gent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x07\x61gentId\"T\n\x17GetDesiredStateResponse\x12\x39\n\x07\x64\x65sired\x18\x01 \x01(\x0b\x32\x1f.xtcp_treatment.v1.DesiredStateR\x07\x64\x65sired\"\x87\x01\n\x18WatchDesiredStateRequest\x12\x44\n\x08\x61gent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x07\x61gentId\x12%\n\x0e\x61\x66ter_revision\x18\x02 \x01(\x04R\rafterRevision\"7\n\x19WatchDesiredStateResponse\x12\x1a\n\x08revision\x18\x01 \x01(\x04R\x08revision2\xd5\x02\n\x13\x41gentControlService\x12V\n\x07\x43heckIn\x12!.xtcp_treatment.v1.CheckInRequest\x1a\".xtcp_treatment.v1.CheckInResponse\"\x04\xd0\xf3\x18\x01\x12n\n\x0fGetDesiredState\x12).xtcp_treatment.v1.GetDesiredStateRequest\x1a*.xtcp_treatment.v1.GetDesiredStateResponse\"\x04\xd0\xf3\x18\x01\x12v\n\x11WatchDesiredState\x12+.xtcp_treatment.v1.WatchDesiredStateRequest\x1a,.xtcp_treatment.v1.WatchDesiredStateResponse\"\x04\xd0\xf3\x18\x01\x30\x01\x42\xbc\x01\n\x15\x63om.xtcp_treatment.v1B\nAgentProtoP\x01Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\xa2\x02\x03XXX\xaa\x02\x10XtcpTreatment.V1\xca\x02\x10XtcpTreatment\\V1\xe2\x02\x1cXtcpTreatment\\V1\\GPBMetadata\xea\x02\x11XtcpTreatment::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'xtcp_treatment.v1.agent_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\025com.xtcp_treatment.v1B\nAgentProtoP\001Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\242\002\003XXX\252\002\020XtcpTreatment.V1\312\002\020XtcpTreatment\\V1\342\002\034XtcpTreatment\\V1\\GPBMetadata\352\002\021XtcpTreatment::V1' + _globals['_CHECKINREQUEST'].fields_by_name['agent_id']._loaded_options = None + _globals['_CHECKINREQUEST'].fields_by_name['agent_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_CHECKINREQUEST'].fields_by_name['location']._loaded_options = None + _globals['_CHECKINREQUEST'].fields_by_name['location']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_CHECKINREQUEST'].fields_by_name['capabilities']._loaded_options = None + _globals['_CHECKINREQUEST'].fields_by_name['capabilities']._serialized_options = b'\272H\003\310\001\001' + _globals['_CHECKINREQUEST'].fields_by_name['records']._loaded_options = None + _globals['_CHECKINREQUEST'].fields_by_name['records']._serialized_options = b'\272H\006\222\001\003\020\200@' + _globals['_GETDESIREDSTATEREQUEST'].fields_by_name['agent_id']._loaded_options = None + _globals['_GETDESIREDSTATEREQUEST'].fields_by_name['agent_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_WATCHDESIREDSTATEREQUEST'].fields_by_name['agent_id']._loaded_options = None + _globals['_WATCHDESIREDSTATEREQUEST'].fields_by_name['agent_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_AGENTCONTROLSERVICE'].methods_by_name['CheckIn']._loaded_options = None + _globals['_AGENTCONTROLSERVICE'].methods_by_name['CheckIn']._serialized_options = b'\320\363\030\001' + _globals['_AGENTCONTROLSERVICE'].methods_by_name['GetDesiredState']._loaded_options = None + _globals['_AGENTCONTROLSERVICE'].methods_by_name['GetDesiredState']._serialized_options = b'\320\363\030\001' + _globals['_AGENTCONTROLSERVICE'].methods_by_name['WatchDesiredState']._loaded_options = None + _globals['_AGENTCONTROLSERVICE'].methods_by_name['WatchDesiredState']._serialized_options = b'\320\363\030\001' + _globals['_CHECKINREQUEST']._serialized_start=117 + _globals['_CHECKINREQUEST']._serialized_end=514 + _globals['_CHECKINRESPONSE']._serialized_start=516 + _globals['_CHECKINRESPONSE']._serialized_end=592 + _globals['_GETDESIREDSTATEREQUEST']._serialized_start=594 + _globals['_GETDESIREDSTATEREQUEST']._serialized_end=688 + _globals['_GETDESIREDSTATERESPONSE']._serialized_start=690 + _globals['_GETDESIREDSTATERESPONSE']._serialized_end=774 + _globals['_WATCHDESIREDSTATEREQUEST']._serialized_start=777 + _globals['_WATCHDESIREDSTATEREQUEST']._serialized_end=912 + _globals['_WATCHDESIREDSTATERESPONSE']._serialized_start=914 + _globals['_WATCHDESIREDSTATERESPONSE']._serialized_end=969 + _globals['_AGENTCONTROLSERVICE']._serialized_start=972 + _globals['_AGENTCONTROLSERVICE']._serialized_end=1313 +# @@protoc_insertion_point(module_scope) diff --git a/gen/python/xtcp_treatment/v1/agent_pb2.pyi b/gen/python/xtcp_treatment/v1/agent_pb2.pyi new file mode 100644 index 000000000..1d1a91240 --- /dev/null +++ b/gen/python/xtcp_treatment/v1/agent_pb2.pyi @@ -0,0 +1,57 @@ +from buf.validate import validate_pb2 as _validate_pb2 +from xtcp_treatment.v1 import treatment_pb2 as _treatment_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class CheckInRequest(_message.Message): + __slots__ = ("agent_id", "location", "capabilities", "desired_revision", "records", "locally_suspended") + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + LOCATION_FIELD_NUMBER: _ClassVar[int] + CAPABILITIES_FIELD_NUMBER: _ClassVar[int] + DESIRED_REVISION_FIELD_NUMBER: _ClassVar[int] + RECORDS_FIELD_NUMBER: _ClassVar[int] + LOCALLY_SUSPENDED_FIELD_NUMBER: _ClassVar[int] + agent_id: str + location: str + capabilities: _treatment_pb2.Capabilities + desired_revision: int + records: _containers.RepeatedCompositeFieldContainer[_treatment_pb2.ApplicationRecord] + locally_suspended: bool + def __init__(self, agent_id: _Optional[str] = ..., location: _Optional[str] = ..., capabilities: _Optional[_Union[_treatment_pb2.Capabilities, _Mapping]] = ..., desired_revision: _Optional[int] = ..., records: _Optional[_Iterable[_Union[_treatment_pb2.ApplicationRecord, _Mapping]]] = ..., locally_suspended: _Optional[bool] = ...) -> None: ... + +class CheckInResponse(_message.Message): + __slots__ = ("desired",) + DESIRED_FIELD_NUMBER: _ClassVar[int] + desired: _treatment_pb2.DesiredState + def __init__(self, desired: _Optional[_Union[_treatment_pb2.DesiredState, _Mapping]] = ...) -> None: ... + +class GetDesiredStateRequest(_message.Message): + __slots__ = ("agent_id",) + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + agent_id: str + def __init__(self, agent_id: _Optional[str] = ...) -> None: ... + +class GetDesiredStateResponse(_message.Message): + __slots__ = ("desired",) + DESIRED_FIELD_NUMBER: _ClassVar[int] + desired: _treatment_pb2.DesiredState + def __init__(self, desired: _Optional[_Union[_treatment_pb2.DesiredState, _Mapping]] = ...) -> None: ... + +class WatchDesiredStateRequest(_message.Message): + __slots__ = ("agent_id", "after_revision") + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + AFTER_REVISION_FIELD_NUMBER: _ClassVar[int] + agent_id: str + after_revision: int + def __init__(self, agent_id: _Optional[str] = ..., after_revision: _Optional[int] = ...) -> None: ... + +class WatchDesiredStateResponse(_message.Message): + __slots__ = ("revision",) + REVISION_FIELD_NUMBER: _ClassVar[int] + revision: int + def __init__(self, revision: _Optional[int] = ...) -> None: ... diff --git a/gen/python/xtcp_treatment/v1/agent_pb2_grpc.py b/gen/python/xtcp_treatment/v1/agent_pb2_grpc.py new file mode 100644 index 000000000..31fd206cb --- /dev/null +++ b/gen/python/xtcp_treatment/v1/agent_pb2_grpc.py @@ -0,0 +1,163 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +from xtcp_treatment.v1 import agent_pb2 as xtcp__treatment_dot_v1_dot_agent__pb2 + + +class AgentControlServiceStub: + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.CheckIn = channel.unary_unary( + '/xtcp_treatment.v1.AgentControlService/CheckIn', + request_serializer=xtcp__treatment_dot_v1_dot_agent__pb2.CheckInRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_agent__pb2.CheckInResponse.FromString, + _registered_method=True) + self.GetDesiredState = channel.unary_unary( + '/xtcp_treatment.v1.AgentControlService/GetDesiredState', + request_serializer=xtcp__treatment_dot_v1_dot_agent__pb2.GetDesiredStateRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_agent__pb2.GetDesiredStateResponse.FromString, + _registered_method=True) + self.WatchDesiredState = channel.unary_stream( + '/xtcp_treatment.v1.AgentControlService/WatchDesiredState', + request_serializer=xtcp__treatment_dot_v1_dot_agent__pb2.WatchDesiredStateRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_agent__pb2.WatchDesiredStateResponse.FromString, + _registered_method=True) + + +class AgentControlServiceServicer: + """Missing associated documentation comment in .proto file.""" + + def CheckIn(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetDesiredState(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def WatchDesiredState(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_AgentControlServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'CheckIn': grpc.unary_unary_rpc_method_handler( + servicer.CheckIn, + request_deserializer=xtcp__treatment_dot_v1_dot_agent__pb2.CheckInRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_agent__pb2.CheckInResponse.SerializeToString, + ), + 'GetDesiredState': grpc.unary_unary_rpc_method_handler( + servicer.GetDesiredState, + request_deserializer=xtcp__treatment_dot_v1_dot_agent__pb2.GetDesiredStateRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_agent__pb2.GetDesiredStateResponse.SerializeToString, + ), + 'WatchDesiredState': grpc.unary_stream_rpc_method_handler( + servicer.WatchDesiredState, + request_deserializer=xtcp__treatment_dot_v1_dot_agent__pb2.WatchDesiredStateRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_agent__pb2.WatchDesiredStateResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'xtcp_treatment.v1.AgentControlService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('xtcp_treatment.v1.AgentControlService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class AgentControlService: + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def CheckIn(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/xtcp_treatment.v1.AgentControlService/CheckIn', + xtcp__treatment_dot_v1_dot_agent__pb2.CheckInRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_agent__pb2.CheckInResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def GetDesiredState(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/xtcp_treatment.v1.AgentControlService/GetDesiredState', + xtcp__treatment_dot_v1_dot_agent__pb2.GetDesiredStateRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_agent__pb2.GetDesiredStateResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def WatchDesiredState(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_stream( + request, + target, + '/xtcp_treatment.v1.AgentControlService/WatchDesiredState', + xtcp__treatment_dot_v1_dot_agent__pb2.WatchDesiredStateRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_agent__pb2.WatchDesiredStateResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/gen/python/xtcp_treatment/v1/operator_pb2.py b/gen/python/xtcp_treatment/v1/operator_pb2.py new file mode 100644 index 000000000..0f2e0d22f --- /dev/null +++ b/gen/python/xtcp_treatment/v1/operator_pb2.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: xtcp_treatment/v1/operator.proto +# Protobuf Python Version: 7.36.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 36, + 2, + '', + 'xtcp_treatment/v1/operator.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from buf.validate import validate_pb2 as buf_dot_validate_dot_validate__pb2 +from xtcp_treatment.v1 import agent_pb2 as xtcp__treatment_dot_v1_dot_agent__pb2 +from xtcp_treatment.v1 import treatment_pb2 as xtcp__treatment_dot_v1_dot_treatment__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n xtcp_treatment/v1/operator.proto\x12\x11xtcp_treatment.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x1dxtcp_treatment/v1/agent.proto\x1a!xtcp_treatment/v1/treatment.proto\"\xbb\x02\n\x0eProposeRequest\x12\x45\n\nexperiment\x18\x01 \x01(\x0b\x32\x1d.xtcp_treatment.v1.ExperimentB\x06\xbaH\x03\xc8\x01\x01R\nexperiment\x12H\n\nrequest_id\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\trequestId:\x97\x01\xbaH\x93\x01\x1a\x90\x01\n\x19propose.request_id_suffix\x12Mrequest_id must not end with .result (reserved for the paired response event)\x1a$!this.request_id.endsWith(\'.result\')\"P\n\x0fProposeResponse\x12=\n\nexperiment\x18\x01 \x01(\x0b\x32\x1d.xtcp_treatment.v1.ExperimentR\nexperiment\"\x8d\x01\n\x0e\x41nalyzeRequest\x12N\n\rexperiment_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x0c\x65xperimentId\x12+\n\x11\x65xpected_revision\x18\x02 \x01(\x04R\x10\x65xpectedRevision\"\x80\x01\n\x0f\x41nalyzeResponse\x12\x37\n\x08\x65vidence\x18\x01 \x01(\x0b\x32\x1b.xtcp_treatment.v1.EvidenceR\x08\x65vidence\x12\x34\n\x07outcome\x18\x02 \x01(\x0e\x32\x1a.xtcp_treatment.v1.OutcomeR\x07outcome\"\xe6\x03\n\rReviewRequest\x12N\n\rexperiment_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x0c\x65xperimentId\x12+\n\x11\x65xpected_revision\x18\x02 \x01(\x04R\x10\x65xpectedRevision\x12\x18\n\x07\x61pprove\x18\x03 \x01(\x08R\x07\x61pprove\x12\"\n\x06reason\x18\x04 \x01(\tB\n\xbaH\x07r\x05\x10\x01\x18\x80 R\x06reason\x12H\n\nrequest_id\x18\x05 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\trequestId\x12\x37\n\x08\x65vidence\x18\x06 \x01(\x0b\x32\x1b.xtcp_treatment.v1.EvidenceR\x08\x65vidence:\x96\x01\xbaH\x92\x01\x1a\x8f\x01\n\x18review.request_id_suffix\x12Mrequest_id must not end with .result (reserved for the paired response event)\x1a$!this.request_id.endsWith(\'.result\')\"O\n\x0eReviewResponse\x12=\n\nexperiment\x18\x01 \x01(\x0b\x32\x1d.xtcp_treatment.v1.ExperimentR\nexperiment\"\xba\x06\n\x0e\x43ontrolRequest\x12Q\n\rexperiment_id\x18\x01 \x01(\tB,\xbaH)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\xd8\x01\x01R\x0c\x65xperimentId\x12G\n\x08\x61gent_id\x18\x02 \x01(\tB,\xbaH)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\xd8\x01\x01R\x07\x61gentId\x12H\n\x08location\x18\x03 \x01(\tB,\xbaH)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\xd8\x01\x01R\x08location\x12\x14\n\x05\x66leet\x18\x04 \x01(\x08R\x05\x66leet\x12\x44\n\x06\x61\x63tion\x18\x05 \x01(\x0e\x32 .xtcp_treatment.v1.ControlActionB\n\xbaH\x07\x82\x01\x04\x10\x01 \x00R\x06\x61\x63tion\x12\"\n\x06reason\x18\x06 \x01(\tB\n\xbaH\x07r\x05\x10\x01\x18\x80 R\x06reason\x12H\n\nrequest_id\x18\x07 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\trequestId:\xf7\x02\xbaH\xf3\x02\x1a\x90\x01\n\x19\x63ontrol.request_id_suffix\x12Mrequest_id must not end with .result (reserved for the paired response event)\x1a$!this.request_id.endsWith(\'.result\')\x1a\xdd\x01\n\x14\x63ontrol.one_selector\x12\x45\x65xactly one of experiment_id, agent_id, location or fleet is required\x1a~(this.fleet ? 1 : 0) + (this.experiment_id != \'\' ? 1 : 0) + (this.agent_id != \'\' ? 1 : 0) + (this.location != \'\' ? 1 : 0) == 1\":\n\x0f\x43ontrolResponse\x12\'\n\x0f\x61\x66\x66\x65\x63ted_agents\x18\x01 \x01(\rR\x0e\x61\x66\x66\x65\x63tedAgents\"\xac\x01\n\x0eInspectRequest\x12Q\n\rexperiment_id\x18\x01 \x01(\tB,\xbaH)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\xd8\x01\x01R\x0c\x65xperimentId\x12G\n\x08\x61gent_id\x18\x02 \x01(\tB,\xbaH)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\xd8\x01\x01R\x07\x61gentId\"\xcc\x01\n\x0fInspectResponse\x12?\n\x0b\x65xperiments\x18\x01 \x03(\x0b\x32\x1d.xtcp_treatment.v1.ExperimentR\x0b\x65xperiments\x12\x39\n\x07\x64\x65sired\x18\x02 \x03(\x0b\x32\x1f.xtcp_treatment.v1.DesiredStateR\x07\x64\x65sired\x12=\n\x08observed\x18\x03 \x03(\x0b\x32!.xtcp_treatment.v1.CheckInRequestR\x08observed*\xb8\x01\n\rControlAction\x12\x1e\n\x1a\x43ONTROL_ACTION_UNSPECIFIED\x10\x00\x12\x18\n\x14\x43ONTROL_ACTION_PAUSE\x10\x01\x12\x1a\n\x16\x43ONTROL_ACTION_SUSPEND\x10\x02\x12\x19\n\x15\x43ONTROL_ACTION_RESUME\x10\x03\x12\x1b\n\x17\x43ONTROL_ACTION_ROLLBACK\x10\x04\x12\x19\n\x15\x43ONTROL_ACTION_RETIRE\x10\x05\x32\xc6\x03\n\x0fOperatorService\x12V\n\x07Propose\x12!.xtcp_treatment.v1.ProposeRequest\x1a\".xtcp_treatment.v1.ProposeResponse\"\x04\xd0\xf3\x18\x02\x12V\n\x07\x41nalyze\x12!.xtcp_treatment.v1.AnalyzeRequest\x1a\".xtcp_treatment.v1.AnalyzeResponse\"\x04\xd0\xf3\x18\x02\x12S\n\x06Review\x12 .xtcp_treatment.v1.ReviewRequest\x1a!.xtcp_treatment.v1.ReviewResponse\"\x04\xd0\xf3\x18\x02\x12V\n\x07\x43ontrol\x12!.xtcp_treatment.v1.ControlRequest\x1a\".xtcp_treatment.v1.ControlResponse\"\x04\xd0\xf3\x18\x02\x12V\n\x07Inspect\x12!.xtcp_treatment.v1.InspectRequest\x1a\".xtcp_treatment.v1.InspectResponse\"\x04\xd0\xf3\x18\x02\x42\xbf\x01\n\x15\x63om.xtcp_treatment.v1B\rOperatorProtoP\x01Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\xa2\x02\x03XXX\xaa\x02\x10XtcpTreatment.V1\xca\x02\x10XtcpTreatment\\V1\xe2\x02\x1cXtcpTreatment\\V1\\GPBMetadata\xea\x02\x11XtcpTreatment::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'xtcp_treatment.v1.operator_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\025com.xtcp_treatment.v1B\rOperatorProtoP\001Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\242\002\003XXX\252\002\020XtcpTreatment.V1\312\002\020XtcpTreatment\\V1\342\002\034XtcpTreatment\\V1\\GPBMetadata\352\002\021XtcpTreatment::V1' + _globals['_PROPOSEREQUEST'].fields_by_name['experiment']._loaded_options = None + _globals['_PROPOSEREQUEST'].fields_by_name['experiment']._serialized_options = b'\272H\003\310\001\001' + _globals['_PROPOSEREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_PROPOSEREQUEST'].fields_by_name['request_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_PROPOSEREQUEST']._loaded_options = None + _globals['_PROPOSEREQUEST']._serialized_options = b'\272H\223\001\032\220\001\n\031propose.request_id_suffix\022Mrequest_id must not end with .result (reserved for the paired response event)\032$!this.request_id.endsWith(\'.result\')' + _globals['_ANALYZEREQUEST'].fields_by_name['experiment_id']._loaded_options = None + _globals['_ANALYZEREQUEST'].fields_by_name['experiment_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_REVIEWREQUEST'].fields_by_name['experiment_id']._loaded_options = None + _globals['_REVIEWREQUEST'].fields_by_name['experiment_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_REVIEWREQUEST'].fields_by_name['reason']._loaded_options = None + _globals['_REVIEWREQUEST'].fields_by_name['reason']._serialized_options = b'\272H\007r\005\020\001\030\200 ' + _globals['_REVIEWREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_REVIEWREQUEST'].fields_by_name['request_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_REVIEWREQUEST']._loaded_options = None + _globals['_REVIEWREQUEST']._serialized_options = b'\272H\222\001\032\217\001\n\030review.request_id_suffix\022Mrequest_id must not end with .result (reserved for the paired response event)\032$!this.request_id.endsWith(\'.result\')' + _globals['_CONTROLREQUEST'].fields_by_name['experiment_id']._loaded_options = None + _globals['_CONTROLREQUEST'].fields_by_name['experiment_id']._serialized_options = b'\272H)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001\001' + _globals['_CONTROLREQUEST'].fields_by_name['agent_id']._loaded_options = None + _globals['_CONTROLREQUEST'].fields_by_name['agent_id']._serialized_options = b'\272H)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001\001' + _globals['_CONTROLREQUEST'].fields_by_name['location']._loaded_options = None + _globals['_CONTROLREQUEST'].fields_by_name['location']._serialized_options = b'\272H)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001\001' + _globals['_CONTROLREQUEST'].fields_by_name['action']._loaded_options = None + _globals['_CONTROLREQUEST'].fields_by_name['action']._serialized_options = b'\272H\007\202\001\004\020\001 \000' + _globals['_CONTROLREQUEST'].fields_by_name['reason']._loaded_options = None + _globals['_CONTROLREQUEST'].fields_by_name['reason']._serialized_options = b'\272H\007r\005\020\001\030\200 ' + _globals['_CONTROLREQUEST'].fields_by_name['request_id']._loaded_options = None + _globals['_CONTROLREQUEST'].fields_by_name['request_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_CONTROLREQUEST']._loaded_options = None + _globals['_CONTROLREQUEST']._serialized_options = b'\272H\363\002\032\220\001\n\031control.request_id_suffix\022Mrequest_id must not end with .result (reserved for the paired response event)\032$!this.request_id.endsWith(\'.result\')\032\335\001\n\024control.one_selector\022Eexactly one of experiment_id, agent_id, location or fleet is required\032~(this.fleet ? 1 : 0) + (this.experiment_id != \'\' ? 1 : 0) + (this.agent_id != \'\' ? 1 : 0) + (this.location != \'\' ? 1 : 0) == 1' + _globals['_INSPECTREQUEST'].fields_by_name['experiment_id']._loaded_options = None + _globals['_INSPECTREQUEST'].fields_by_name['experiment_id']._serialized_options = b'\272H)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001\001' + _globals['_INSPECTREQUEST'].fields_by_name['agent_id']._loaded_options = None + _globals['_INSPECTREQUEST'].fields_by_name['agent_id']._serialized_options = b'\272H)r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$\330\001\001' + _globals['_OPERATORSERVICE'].methods_by_name['Propose']._loaded_options = None + _globals['_OPERATORSERVICE'].methods_by_name['Propose']._serialized_options = b'\320\363\030\002' + _globals['_OPERATORSERVICE'].methods_by_name['Analyze']._loaded_options = None + _globals['_OPERATORSERVICE'].methods_by_name['Analyze']._serialized_options = b'\320\363\030\002' + _globals['_OPERATORSERVICE'].methods_by_name['Review']._loaded_options = None + _globals['_OPERATORSERVICE'].methods_by_name['Review']._serialized_options = b'\320\363\030\002' + _globals['_OPERATORSERVICE'].methods_by_name['Control']._loaded_options = None + _globals['_OPERATORSERVICE'].methods_by_name['Control']._serialized_options = b'\320\363\030\002' + _globals['_OPERATORSERVICE'].methods_by_name['Inspect']._loaded_options = None + _globals['_OPERATORSERVICE'].methods_by_name['Inspect']._serialized_options = b'\320\363\030\002' + _globals['_CONTROLACTION']._serialized_start=2667 + _globals['_CONTROLACTION']._serialized_end=2851 + _globals['_PROPOSEREQUEST']._serialized_start=151 + _globals['_PROPOSEREQUEST']._serialized_end=466 + _globals['_PROPOSERESPONSE']._serialized_start=468 + _globals['_PROPOSERESPONSE']._serialized_end=548 + _globals['_ANALYZEREQUEST']._serialized_start=551 + _globals['_ANALYZEREQUEST']._serialized_end=692 + _globals['_ANALYZERESPONSE']._serialized_start=695 + _globals['_ANALYZERESPONSE']._serialized_end=823 + _globals['_REVIEWREQUEST']._serialized_start=826 + _globals['_REVIEWREQUEST']._serialized_end=1312 + _globals['_REVIEWRESPONSE']._serialized_start=1314 + _globals['_REVIEWRESPONSE']._serialized_end=1393 + _globals['_CONTROLREQUEST']._serialized_start=1396 + _globals['_CONTROLREQUEST']._serialized_end=2222 + _globals['_CONTROLRESPONSE']._serialized_start=2224 + _globals['_CONTROLRESPONSE']._serialized_end=2282 + _globals['_INSPECTREQUEST']._serialized_start=2285 + _globals['_INSPECTREQUEST']._serialized_end=2457 + _globals['_INSPECTRESPONSE']._serialized_start=2460 + _globals['_INSPECTRESPONSE']._serialized_end=2664 + _globals['_OPERATORSERVICE']._serialized_start=2854 + _globals['_OPERATORSERVICE']._serialized_end=3308 +# @@protoc_insertion_point(module_scope) diff --git a/gen/python/xtcp_treatment/v1/operator_pb2.pyi b/gen/python/xtcp_treatment/v1/operator_pb2.pyi new file mode 100644 index 000000000..08dbfc580 --- /dev/null +++ b/gen/python/xtcp_treatment/v1/operator_pb2.pyi @@ -0,0 +1,120 @@ +from buf.validate import validate_pb2 as _validate_pb2 +from xtcp_treatment.v1 import agent_pb2 as _agent_pb2 +from xtcp_treatment.v1 import treatment_pb2 as _treatment_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ControlAction(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + CONTROL_ACTION_UNSPECIFIED: _ClassVar[ControlAction] + CONTROL_ACTION_PAUSE: _ClassVar[ControlAction] + CONTROL_ACTION_SUSPEND: _ClassVar[ControlAction] + CONTROL_ACTION_RESUME: _ClassVar[ControlAction] + CONTROL_ACTION_ROLLBACK: _ClassVar[ControlAction] + CONTROL_ACTION_RETIRE: _ClassVar[ControlAction] +CONTROL_ACTION_UNSPECIFIED: ControlAction +CONTROL_ACTION_PAUSE: ControlAction +CONTROL_ACTION_SUSPEND: ControlAction +CONTROL_ACTION_RESUME: ControlAction +CONTROL_ACTION_ROLLBACK: ControlAction +CONTROL_ACTION_RETIRE: ControlAction + +class ProposeRequest(_message.Message): + __slots__ = ("experiment", "request_id") + EXPERIMENT_FIELD_NUMBER: _ClassVar[int] + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + experiment: _treatment_pb2.Experiment + request_id: str + def __init__(self, experiment: _Optional[_Union[_treatment_pb2.Experiment, _Mapping]] = ..., request_id: _Optional[str] = ...) -> None: ... + +class ProposeResponse(_message.Message): + __slots__ = ("experiment",) + EXPERIMENT_FIELD_NUMBER: _ClassVar[int] + experiment: _treatment_pb2.Experiment + def __init__(self, experiment: _Optional[_Union[_treatment_pb2.Experiment, _Mapping]] = ...) -> None: ... + +class AnalyzeRequest(_message.Message): + __slots__ = ("experiment_id", "expected_revision") + EXPERIMENT_ID_FIELD_NUMBER: _ClassVar[int] + EXPECTED_REVISION_FIELD_NUMBER: _ClassVar[int] + experiment_id: str + expected_revision: int + def __init__(self, experiment_id: _Optional[str] = ..., expected_revision: _Optional[int] = ...) -> None: ... + +class AnalyzeResponse(_message.Message): + __slots__ = ("evidence", "outcome") + EVIDENCE_FIELD_NUMBER: _ClassVar[int] + OUTCOME_FIELD_NUMBER: _ClassVar[int] + evidence: _treatment_pb2.Evidence + outcome: _treatment_pb2.Outcome + def __init__(self, evidence: _Optional[_Union[_treatment_pb2.Evidence, _Mapping]] = ..., outcome: _Optional[_Union[_treatment_pb2.Outcome, str]] = ...) -> None: ... + +class ReviewRequest(_message.Message): + __slots__ = ("experiment_id", "expected_revision", "approve", "reason", "request_id", "evidence") + EXPERIMENT_ID_FIELD_NUMBER: _ClassVar[int] + EXPECTED_REVISION_FIELD_NUMBER: _ClassVar[int] + APPROVE_FIELD_NUMBER: _ClassVar[int] + REASON_FIELD_NUMBER: _ClassVar[int] + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + EVIDENCE_FIELD_NUMBER: _ClassVar[int] + experiment_id: str + expected_revision: int + approve: bool + reason: str + request_id: str + evidence: _treatment_pb2.Evidence + def __init__(self, experiment_id: _Optional[str] = ..., expected_revision: _Optional[int] = ..., approve: _Optional[bool] = ..., reason: _Optional[str] = ..., request_id: _Optional[str] = ..., evidence: _Optional[_Union[_treatment_pb2.Evidence, _Mapping]] = ...) -> None: ... + +class ReviewResponse(_message.Message): + __slots__ = ("experiment",) + EXPERIMENT_FIELD_NUMBER: _ClassVar[int] + experiment: _treatment_pb2.Experiment + def __init__(self, experiment: _Optional[_Union[_treatment_pb2.Experiment, _Mapping]] = ...) -> None: ... + +class ControlRequest(_message.Message): + __slots__ = ("experiment_id", "agent_id", "location", "fleet", "action", "reason", "request_id") + EXPERIMENT_ID_FIELD_NUMBER: _ClassVar[int] + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + LOCATION_FIELD_NUMBER: _ClassVar[int] + FLEET_FIELD_NUMBER: _ClassVar[int] + ACTION_FIELD_NUMBER: _ClassVar[int] + REASON_FIELD_NUMBER: _ClassVar[int] + REQUEST_ID_FIELD_NUMBER: _ClassVar[int] + experiment_id: str + agent_id: str + location: str + fleet: bool + action: ControlAction + reason: str + request_id: str + def __init__(self, experiment_id: _Optional[str] = ..., agent_id: _Optional[str] = ..., location: _Optional[str] = ..., fleet: _Optional[bool] = ..., action: _Optional[_Union[ControlAction, str]] = ..., reason: _Optional[str] = ..., request_id: _Optional[str] = ...) -> None: ... + +class ControlResponse(_message.Message): + __slots__ = ("affected_agents",) + AFFECTED_AGENTS_FIELD_NUMBER: _ClassVar[int] + affected_agents: int + def __init__(self, affected_agents: _Optional[int] = ...) -> None: ... + +class InspectRequest(_message.Message): + __slots__ = ("experiment_id", "agent_id") + EXPERIMENT_ID_FIELD_NUMBER: _ClassVar[int] + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + experiment_id: str + agent_id: str + def __init__(self, experiment_id: _Optional[str] = ..., agent_id: _Optional[str] = ...) -> None: ... + +class InspectResponse(_message.Message): + __slots__ = ("experiments", "desired", "observed") + EXPERIMENTS_FIELD_NUMBER: _ClassVar[int] + DESIRED_FIELD_NUMBER: _ClassVar[int] + OBSERVED_FIELD_NUMBER: _ClassVar[int] + experiments: _containers.RepeatedCompositeFieldContainer[_treatment_pb2.Experiment] + desired: _containers.RepeatedCompositeFieldContainer[_treatment_pb2.DesiredState] + observed: _containers.RepeatedCompositeFieldContainer[_agent_pb2.CheckInRequest] + def __init__(self, experiments: _Optional[_Iterable[_Union[_treatment_pb2.Experiment, _Mapping]]] = ..., desired: _Optional[_Iterable[_Union[_treatment_pb2.DesiredState, _Mapping]]] = ..., observed: _Optional[_Iterable[_Union[_agent_pb2.CheckInRequest, _Mapping]]] = ...) -> None: ... diff --git a/gen/python/xtcp_treatment/v1/operator_pb2_grpc.py b/gen/python/xtcp_treatment/v1/operator_pb2_grpc.py new file mode 100644 index 000000000..4a8259dc3 --- /dev/null +++ b/gen/python/xtcp_treatment/v1/operator_pb2_grpc.py @@ -0,0 +1,249 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +from xtcp_treatment.v1 import operator_pb2 as xtcp__treatment_dot_v1_dot_operator__pb2 + + +class OperatorServiceStub: + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Propose = channel.unary_unary( + '/xtcp_treatment.v1.OperatorService/Propose', + request_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.ProposeRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.ProposeResponse.FromString, + _registered_method=True) + self.Analyze = channel.unary_unary( + '/xtcp_treatment.v1.OperatorService/Analyze', + request_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.AnalyzeRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.AnalyzeResponse.FromString, + _registered_method=True) + self.Review = channel.unary_unary( + '/xtcp_treatment.v1.OperatorService/Review', + request_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.ReviewRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.ReviewResponse.FromString, + _registered_method=True) + self.Control = channel.unary_unary( + '/xtcp_treatment.v1.OperatorService/Control', + request_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.ControlRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.ControlResponse.FromString, + _registered_method=True) + self.Inspect = channel.unary_unary( + '/xtcp_treatment.v1.OperatorService/Inspect', + request_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.InspectRequest.SerializeToString, + response_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.InspectResponse.FromString, + _registered_method=True) + + +class OperatorServiceServicer: + """Missing associated documentation comment in .proto file.""" + + def Propose(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Analyze(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Review(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Control(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Inspect(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_OperatorServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Propose': grpc.unary_unary_rpc_method_handler( + servicer.Propose, + request_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.ProposeRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.ProposeResponse.SerializeToString, + ), + 'Analyze': grpc.unary_unary_rpc_method_handler( + servicer.Analyze, + request_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.AnalyzeRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.AnalyzeResponse.SerializeToString, + ), + 'Review': grpc.unary_unary_rpc_method_handler( + servicer.Review, + request_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.ReviewRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.ReviewResponse.SerializeToString, + ), + 'Control': grpc.unary_unary_rpc_method_handler( + servicer.Control, + request_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.ControlRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.ControlResponse.SerializeToString, + ), + 'Inspect': grpc.unary_unary_rpc_method_handler( + servicer.Inspect, + request_deserializer=xtcp__treatment_dot_v1_dot_operator__pb2.InspectRequest.FromString, + response_serializer=xtcp__treatment_dot_v1_dot_operator__pb2.InspectResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'xtcp_treatment.v1.OperatorService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + server.add_registered_method_handlers('xtcp_treatment.v1.OperatorService', rpc_method_handlers) + + + # This class is part of an EXPERIMENTAL API. +class OperatorService: + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def Propose(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/xtcp_treatment.v1.OperatorService/Propose', + xtcp__treatment_dot_v1_dot_operator__pb2.ProposeRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_operator__pb2.ProposeResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Analyze(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/xtcp_treatment.v1.OperatorService/Analyze', + xtcp__treatment_dot_v1_dot_operator__pb2.AnalyzeRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_operator__pb2.AnalyzeResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Review(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/xtcp_treatment.v1.OperatorService/Review', + xtcp__treatment_dot_v1_dot_operator__pb2.ReviewRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_operator__pb2.ReviewResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Control(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/xtcp_treatment.v1.OperatorService/Control', + xtcp__treatment_dot_v1_dot_operator__pb2.ControlRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_operator__pb2.ControlResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def Inspect(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/xtcp_treatment.v1.OperatorService/Inspect', + xtcp__treatment_dot_v1_dot_operator__pb2.InspectRequest.SerializeToString, + xtcp__treatment_dot_v1_dot_operator__pb2.InspectResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) diff --git a/gen/python/xtcp_treatment/v1/treatment_pb2.py b/gen/python/xtcp_treatment/v1/treatment_pb2.py new file mode 100644 index 000000000..9b4fa2a95 --- /dev/null +++ b/gen/python/xtcp_treatment/v1/treatment_pb2.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: xtcp_treatment/v1/treatment.proto +# Protobuf Python Version: 7.36.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 36, + 2, + '', + 'xtcp_treatment/v1/treatment.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from buf.validate import validate_pb2 as buf_dot_validate_dot_validate__pb2 +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!xtcp_treatment/v1/treatment.proto\x12\x11xtcp_treatment.v1\x1a\x1b\x62uf/validate/validate.proto\x1a google/protobuf/descriptor.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8d\x07\n\x0bTCPSettings\x12Y\n\x12\x63ongestion_control\x18\x01 \x01(\tB%\xbaH\"r \x18\x0f\x32\x1c^[a-zA-Z0-9][a-zA-Z0-9_.-]*$H\x00R\x11\x63ongestionControl\x88\x01\x01\x12\'\n\x0f\x63ongestion_lock\x18\x02 \x01(\x08R\x0e\x63ongestionLock\x12.\n\nrto_min_ms\x18\x03 \x01(\rB\x0b\xbaH\x08*\x06\x18\xc0\xa9\x07(\x01H\x01R\x08rtoMinMs\x88\x01\x01\x12K\n\x19initial_congestion_window\x18\x04 \x01(\rB\n\xbaH\x07*\x05\x18\x80\x08(\x01H\x02R\x17initialCongestionWindow\x88\x01\x01\x12\x45\n\x16initial_receive_window\x18\x05 \x01(\rB\n\xbaH\x07*\x05\x18\x80\x08(\x01H\x03R\x14initialReceiveWindow\x88\x01\x01\x12 \n\tquick_ack\x18\x06 \x01(\x08H\x04R\x08quickAck\x88\x01\x01\x12\x15\n\x03\x65\x63n\x18\x07 \x01(\x08H\x05R\x03\x65\x63n\x88\x01\x01:\x87\x03\xbaH\x83\x03\x1a\xf3\x01\n\x16tcp_settings.non_empty\x12/a treatment must set at least one TCP parameter\x1a\xa7\x01has(this.congestion_control) || has(this.rto_min_ms) || has(this.initial_congestion_window) || has(this.initial_receive_window) || has(this.quick_ack) || has(this.ecn)\x1a\x8a\x01\n$tcp_settings.lock_requires_algorithm\x12+congestion_lock requires congestion_control\x1a\x35!this.congestion_lock || has(this.congestion_control)B\x15\n\x13_congestion_controlB\r\n\x0b_rto_min_msB\x1c\n\x1a_initial_congestion_windowB\x19\n\x17_initial_receive_windowB\x0c\n\n_quick_ackB\x06\n\x04_ecn\"\xd8\x03\n\tTreatment\x12\x39\n\x02id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x02id\x12#\n\x08revision\x18\x02 \x01(\x04\x42\x07\xbaH\x04\x32\x02 \x00R\x08revision\x12,\n\x0b\x64\x65stination\x18\x03 \x01(\tB\n\xbaH\x07r\x05\x18\x31\xe8\x01\x01R\x0b\x64\x65stination\x12\x42\n\x08settings\x18\x04 \x01(\x0b\x32\x1e.xtcp_treatment.v1.TCPSettingsB\x06\xbaH\x03\xc8\x01\x01R\x08settings\x12.\n\x13\x65\x63n_fabric_verified\x18\x05 \x01(\x08R\x11\x65\x63nFabricVerified:\xc8\x01\xbaH\xc4\x01\x1a\xc1\x01\n\x1ctreatment.dctcp_requires_ecn\x12\x41\x44\x43TCP requires independently verified ECN fabric and explicit ECN\x1a^this.settings.congestion_control != \'dctcp\' || (this.ecn_fabric_verified && this.settings.ecn)\"\xcc\x05\n\nAssignment\x12N\n\rexperiment_id\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x0c\x65xperimentId\x12\x42\n\ttreatment\x18\x03 \x01(\x0b\x32\x1c.xtcp_treatment.v1.TreatmentB\x06\xbaH\x03\xc8\x01\x01R\ttreatment\x12\x41\n\x04mode\x18\x04 \x01(\x0e\x32!.xtcp_treatment.v1.AssignmentModeB\n\xbaH\x07\x82\x01\x04\x10\x01 \x00R\x04mode\x12\x44\n\x10lease_expires_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0eleaseExpiresAt\x12>\n\x0bpredecessor\x18\x06 \x01(\x0b\x32\x1c.xtcp_treatment.v1.TreatmentR\x0bpredecessor\x12\'\n\ngeneration\x18\x07 \x01(\x04\x42\x07\xbaH\x04\x32\x02 \x00R\ngeneration:\xad\x02\xbaH\xa9\x02\x1a}\n\x1f\x61ssignment.trial_requires_lease\x12,a trial assignment requires lease_expires_at\x1a,this.mode != 1 || has(this.lease_expires_at)\x1a\xa7\x01\n\"assignment.predecessor_destination\x12+predecessor must cover the same destination\x1aT!has(this.predecessor) || this.predecessor.destination == this.treatment.destinationJ\x04\x08\x01\x10\x02R\x02id\"\xa4\x02\n\x0c\x44\x65siredState\x12\x44\n\x08\x61gent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x07\x61gentId\x12#\n\x08revision\x18\x02 \x01(\x04\x42\x07\xbaH\x04\x32\x02 \x00R\x08revision\x12\x1c\n\tsuspended\x18\x03 \x01(\x08R\tsuspended\x12J\n\x0b\x61ssignments\x18\x04 \x03(\x0b\x32\x1d.xtcp_treatment.v1.AssignmentB\t\xbaH\x06\x92\x01\x03\x10\x80 R\x0b\x61ssignments\x12?\n\tissued_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\x08issuedAt\"\xdf\x02\n\x0c\x43\x61pabilities\x12\x42\n\x07\x62oot_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x06\x62ootId\x12/\n\x0ekernel_release\x18\x02 \x01(\tB\x08\xbaH\x05r\x03\x18\x80\x02R\rkernelRelease\x12\x43\n\x15\x63ongestion_algorithms\x18\x03 \x03(\tB\x0e\xbaH\x0b\x92\x01\x08\x10@\"\x04r\x02\x18\x0fR\x14\x63ongestionAlgorithms\x12.\n\x13simple_host_routing\x18\x04 \x01(\x08R\x11simpleHostRouting\x12)\n\x10\x61\x63tuator_enabled\x18\x05 \x01(\x08R\x0f\x61\x63tuatorEnabled\x12:\n\rcollection_id\x18\x06 \x01(\tB\x15\xbaH\x12r\x10\x32\x0e^[0-9a-f]{32}$R\x0c\x63ollectionId\"\xa8\x05\n\x11\x41pplicationRecord\x12\x45\n\nassignment\x18\x01 \x01(\x0b\x32\x1d.xtcp_treatment.v1.AssignmentB\x06\xbaH\x03\xc8\x01\x01R\nassignment\x12)\n\x10\x64\x65sired_revision\x18\x02 \x01(\x04R\x0f\x64\x65siredRevision\x12@\n\x06status\x18\x03 \x01(\x0e\x32\x1e.xtcp_treatment.v1.ApplyStatusB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x06status\x12;\n\x0breceived_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nreceivedAt\x12=\n\x0c\x61ttempted_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0b\x61ttemptedAt\x12\x39\n\napplied_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tappliedAt\x12;\n\x0bverified_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nverifiedAt\x12\x39\n\nremoved_at\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tremovedAt\x12\x1e\n\x05\x65rror\x18\t \x01(\tB\x08\xbaH\x05r\x03\x18\x80 R\x05\x65rror\x12\x31\n\x0finstalled_route\x18\n \x01(\x0c\x42\x08\xbaH\x05z\x03\x18\x80 R\x0einstalledRoute\x12\x34\n\x11installed_boot_id\x18\x0b \x01(\tB\x08\xbaH\x05r\x03\x18\x80\x01R\x0finstalledBootId\x12\'\n\x0f\x65xpired_latched\x18\x0c \x01(\x08R\x0e\x65xpiredLatched\"\xb1\x02\n\nLocalState\x12\x39\n\x07\x64\x65sired\x18\x01 \x01(\x0b\x32\x1f.xtcp_treatment.v1.DesiredStateR\x07\x64\x65sired\x12+\n\x11locally_suspended\x18\x02 \x01(\x08R\x10locallySuspended\x12\x35\n\x11suspension_reason\x18\x03 \x01(\tB\x08\xbaH\x05r\x03\x18\x80\x08R\x10suspensionReason\x12I\n\x07records\x18\x04 \x03(\x0b\x32$.xtcp_treatment.v1.ApplicationRecordB\t\xbaH\x06\x92\x01\x03\x10\x80@R\x07records\x12\x39\n\nupdated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\"\xb2\x04\n\x0cHostEvidence\x12\x44\n\x08\x61gent_id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x07\x61gentId\x12\x18\n\x07sockets\x18\x02 \x01(\x04R\x07sockets\x12\x1f\n\x0b\x62ytes_acked\x18\x03 \x01(\x04R\nbytesAcked\x12\x31\n\x0bgoodput_bps\x18\x04 \x01(\x01\x42\x10\xbaH\r\x12\x0b)\x00\x00\x00\x00\x00\x00\x00\x00@\x01R\ngoodputBps\x12\x43\n\x14retransmission_ratio\x18\x05 \x01(\x01\x42\x10\xbaH\r\x12\x0b)\x00\x00\x00\x00\x00\x00\x00\x00@\x01R\x13retransmissionRatio\x12.\n\nrtt_p95_ms\x18\x06 \x01(\x01\x42\x10\xbaH\r\x12\x0b)\x00\x00\x00\x00\x00\x00\x00\x00@\x01R\x08rttP95Ms\x12\'\n\x0f\x65xposed_sockets\x18\x07 \x01(\x04R\x0e\x65xposedSockets\x12-\n\x12\x63ollection_healthy\x18\x08 \x01(\x08R\x11\x63ollectionHealthy\x12\'\n\x0funbound_sockets\x18\t \x01(\x04R\x0eunboundSockets:x\xbaHu\x1as\n$host_evidence.exposed_within_sockets\x12%exposed_sockets cannot exceed sockets\x1a$this.exposed_sockets <= this.sockets\"\xbc\x05\n\x08\x45vidence\x12\x39\n\x02id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x02id\x12\x43\n\x0b\x61nalyzed_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\nanalyzedAt\x12\x45\n\x0cwindow_start\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\x0bwindowStart\x12\x41\n\nwindow_end\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x06\xbaH\x03\xc8\x01\x01R\twindowEnd\x12/\n\rquery_version\x18\x05 \x01(\tB\n\xbaH\x07r\x05\x10\x01\x18\x80\x02R\x0cqueryVersion\x12\x37\n\x12\x65nrichment_version\x18\x06 \x01(\tB\x08\xbaH\x05r\x03\x18\x80\x02R\x11\x65nrichmentVersion\x12\x42\n\x05hosts\x18\x07 \x03(\x0b\x32\x1f.xtcp_treatment.v1.HostEvidenceB\x0b\xbaH\x08\x92\x01\x05\x08\x01\x10\x90NR\x05hosts\x12>\n\x0f\x61rtifact_sha256\x18\x08 \x01(\tB\x15\xbaH\x12r\x10\x32\x0e^[0-9a-f]{64}$R\x0e\x61rtifactSha256:\xb7\x01\xbaH\xb3\x01\x1a\xb0\x01\n\x11\x65vidence.interval\x12Owindow_end must follow window_start and analyzed_at must not precede window_end\x1aJthis.window_end > this.window_start && this.analyzed_at >= this.window_end\"\xec\x06\n\x10\x45xperimentPolicy\x12]\n\x13minimum_observation\x18\x01 \x01(\x0b\x32\x19.google.protobuf.DurationB\x11\xbaH\x0e\xaa\x01\x08\"\x04\x08\x80\xf5$*\x00\xc8\x01\x01R\x12minimumObservation\x12Q\n\rmaximum_phase\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationB\x11\xbaH\x0e\xaa\x01\x08\"\x04\x08\x80\xf5$*\x00\xc8\x01\x01R\x0cmaximumPhase\x12@\n\x18minimum_sockets_per_host\x18\x03 \x01(\x04\x42\x07\xbaH\x04\x32\x02 \x00R\x15minimumSocketsPerHost\x12<\n\x16minimum_bytes_per_host\x18\x04 \x01(\x04\x42\x07\xbaH\x04\x32\x02 \x00R\x13minimumBytesPerHost\x12>\n\x15minimum_treated_hosts\x18\x05 \x01(\rB\n\xbaH\x07*\x05\x18\x90N(\x02R\x13minimumTreatedHosts\x12J\n\x13minimum_improvement\x18\x06 \x01(\x01\x42\x19\xbaH\x16\x12\x14\x19\x00\x00\x00\x00\x00\x00\xf0?)\x00\x00\x00\x00\x00\x00\x00\x00@\x01R\x12minimumImprovement\x12\x61\n\x1fmaximum_retransmission_increase\x18\x07 \x01(\x01\x42\x19\xbaH\x16\x12\x14\x19\x00\x00\x00\x00\x00\x00\xf0?)\x00\x00\x00\x00\x00\x00\x00\x00@\x01R\x1dmaximumRetransmissionIncrease\x12K\n\x14maximum_rtt_increase\x18\x08 \x01(\x01\x42\x19\xbaH\x16\x12\x14\x19\x00\x00\x00\x00\x00\x00\xf0?)\x00\x00\x00\x00\x00\x00\x00\x00@\x01R\x12maximumRttIncrease\x12^\n\x14maximum_evidence_age\x18\t \x01(\x0b\x32\x19.google.protobuf.DurationB\x11\xbaH\x0e\xaa\x01\x08\"\x04\x08\x80\xf5$*\x00\xc8\x01\x01R\x12maximumEvidenceAge:\x89\x01\xbaH\x85\x01\x1a\x82\x01\n\x1fpolicy.observation_within_phase\x12/minimum_observation cannot exceed maximum_phase\x1a.this.minimum_observation <= this.maximum_phase\"\xc1\x03\n\x05Phase\x12-\n\x0ctarget_hosts\x18\x01 \x01(\rB\n\xbaH\x07*\x05\x18\x90N(\x01R\x0btargetHosts\x12\x37\n\tissued_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x08issuedAt\x12P\n\x16observation_started_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x14observationStartedAt\x12=\n\x0c\x65valuated_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0b\x65valuatedAt\x12\x37\n\x08\x65vidence\x18\x05 \x01(\x0b\x32\x1b.xtcp_treatment.v1.EvidenceR\x08\x65vidence\x12>\n\x07outcome\x18\x06 \x01(\x0e\x32\x1a.xtcp_treatment.v1.OutcomeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x07outcome\x12$\n\x08reviewer\x18\x07 \x01(\tB\x08\xbaH\x05r\x03\x18\x80\x01R\x08reviewer\x12 \n\x06reason\x18\x08 \x01(\tB\x08\xbaH\x05r\x03\x18\x80 R\x06reason\"\x88\x07\n\nExperiment\x12\x39\n\x02id\x18\x01 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x02id\x12\x45\n\x08location\x18\x02 \x01(\tB)\xbaH&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x08location\x12*\n\nhypothesis\x18\x03 \x01(\tB\n\xbaH\x07r\x05\x10\x01\x18\x80@R\nhypothesis\x12\x42\n\ttreatment\x18\x04 \x01(\x0b\x32\x1c.xtcp_treatment.v1.TreatmentB\x06\xbaH\x03\xc8\x01\x01R\ttreatment\x12\x43\n\x06policy\x18\x05 \x01(\x0b\x32#.xtcp_treatment.v1.ExperimentPolicyB\x06\xbaH\x03\xc8\x01\x01R\x06policy\x12?\n\x08\x62\x61seline\x18\x06 \x01(\x0b\x32\x1b.xtcp_treatment.v1.EvidenceB\x06\xbaH\x03\xc8\x01\x01R\x08\x62\x61seline\x12X\n\x0c\x63ohort_order\x18\x07 \x03(\tB5\xbaH2\x92\x01/\x08\x03\x10\x90N\x18\x01\"&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$R\x0b\x63ohortOrder\x12:\n\x06phases\x18\x08 \x03(\x0b\x32\x18.xtcp_treatment.v1.PhaseB\x08\xbaH\x05\x92\x01\x02\x10@R\x06phases\x12\x45\n\x06status\x18\t \x01(\x0e\x32#.xtcp_treatment.v1.ExperimentStatusB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x06status\x12\x1a\n\x08revision\x18\n \x01(\x04R\x08revision\x12;\n\x0bproposed_at\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nproposedAt\x12\x44\n\x0flatest_evidence\x18\x0c \x01(\x0b\x32\x1b.xtcp_treatment.v1.EvidenceR\x0elatestEvidence\x12K\n\x0elatest_outcome\x18\r \x01(\x0e\x32\x1a.xtcp_treatment.v1.OutcomeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\rlatestOutcome\x12\x39\n\nupdated_at\x18\x0e \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt*?\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0e\n\nROLE_AGENT\x10\x01\x12\x11\n\rROLE_OPERATOR\x10\x02*\xa4\x01\n\x0e\x41ssignmentMode\x12\x1f\n\x1b\x41SSIGNMENT_MODE_UNSPECIFIED\x10\x00\x12\x19\n\x15\x41SSIGNMENT_MODE_TRIAL\x10\x01\x12\x1a\n\x16\x41SSIGNMENT_MODE_STABLE\x10\x02\x12\x1d\n\x19\x41SSIGNMENT_MODE_SUSPENDED\x10\x03\x12\x1b\n\x17\x41SSIGNMENT_MODE_RETIRED\x10\x04*\xad\x01\n\x0b\x41pplyStatus\x12\x1c\n\x18\x41PPLY_STATUS_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41PPLY_STATUS_PENDING\x10\x01\x12\x19\n\x15\x41PPLY_STATUS_VERIFIED\x10\x02\x12\x18\n\x14\x41PPLY_STATUS_REMOVED\x10\x03\x12\x18\n\x14\x41PPLY_STATUS_EXPIRED\x10\x04\x12\x17\n\x13\x41PPLY_STATUS_FAILED\x10\x05*\xa4\x04\n\x07Outcome\x12\x17\n\x13OUTCOME_UNSPECIFIED\x10\x00\x12\x14\n\x10OUTCOME_BASELINE\x10\x01\x12 \n\x1cOUTCOME_AWAITING_APPLICATION\x10\x02\x12\x1d\n\x19OUTCOME_AWAITING_EXPOSURE\x10\x03\x12!\n\x1dOUTCOME_INSUFFICIENT_DURATION\x10\x04\x12\x1d\n\x19OUTCOME_INSUFFICIENT_DATA\x10\x05\x12!\n\x1dOUTCOME_INSUFFICIENT_CONTROLS\x10\x06\x12\x11\n\rOUTCOME_STALE\x10\x07\x12\x17\n\x13OUTCOME_UNAVAILABLE\x10\x08\x12\x18\n\x14OUTCOME_INCONCLUSIVE\x10\t\x12\x17\n\x13OUTCOME_SAFETY_ONLY\x10\n\x12\x18\n\x14OUTCOME_FINAL_SAFETY\x10\x0b\x12\x16\n\x12OUTCOME_BENEFICIAL\x10\x0c\x12\x13\n\x0fOUTCOME_HARMFUL\x10\r\x12\x13\n\x0fOUTCOME_EXPIRED\x10\x0e\x12\x1b\n\x17OUTCOME_STABLE_OBSERVED\x10\x0f\x12&\n\"OUTCOME_STABLE_EVIDENCE_INCOMPLETE\x10\x10\x12-\n)OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED\x10\x11\x12\x15\n\x11OUTCOME_OBSERVING\x10\x12*\x95\x02\n\x10\x45xperimentStatus\x12!\n\x1d\x45XPERIMENT_STATUS_UNSPECIFIED\x10\x00\x12\x1e\n\x1a\x45XPERIMENT_STATUS_PROPOSED\x10\x01\x12\x1d\n\x19\x45XPERIMENT_STATUS_RUNNING\x10\x02\x12\x1c\n\x18\x45XPERIMENT_STATUS_PAUSED\x10\x03\x12\x1f\n\x1b\x45XPERIMENT_STATUS_SUSPENDED\x10\x04\x12\x1e\n\x1a\x45XPERIMENT_STATUS_COMPLETE\x10\x05\x12\x1d\n\x19\x45XPERIMENT_STATUS_RETIRED\x10\x06\x12!\n\x1d\x45XPERIMENT_STATUS_ROLLED_BACK\x10\x07:M\n\x04role\x12\x1e.google.protobuf.MethodOptions\x18\xba\x8e\x03 \x01(\x0e\x32\x17.xtcp_treatment.v1.RoleR\x04roleB\xc0\x01\n\x15\x63om.xtcp_treatment.v1B\x0eTreatmentProtoP\x01Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\xa2\x02\x03XXX\xaa\x02\x10XtcpTreatment.V1\xca\x02\x10XtcpTreatment\\V1\xe2\x02\x1cXtcpTreatment\\V1\\GPBMetadata\xea\x02\x11XtcpTreatment::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'xtcp_treatment.v1.treatment_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\025com.xtcp_treatment.v1B\016TreatmentProtoP\001Z6github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment\242\002\003XXX\252\002\020XtcpTreatment.V1\312\002\020XtcpTreatment\\V1\342\002\034XtcpTreatment\\V1\\GPBMetadata\352\002\021XtcpTreatment::V1' + _globals['_TCPSETTINGS'].fields_by_name['congestion_control']._loaded_options = None + _globals['_TCPSETTINGS'].fields_by_name['congestion_control']._serialized_options = b'\272H\"r \030\0172\034^[a-zA-Z0-9][a-zA-Z0-9_.-]*$' + _globals['_TCPSETTINGS'].fields_by_name['rto_min_ms']._loaded_options = None + _globals['_TCPSETTINGS'].fields_by_name['rto_min_ms']._serialized_options = b'\272H\010*\006\030\300\251\007(\001' + _globals['_TCPSETTINGS'].fields_by_name['initial_congestion_window']._loaded_options = None + _globals['_TCPSETTINGS'].fields_by_name['initial_congestion_window']._serialized_options = b'\272H\007*\005\030\200\010(\001' + _globals['_TCPSETTINGS'].fields_by_name['initial_receive_window']._loaded_options = None + _globals['_TCPSETTINGS'].fields_by_name['initial_receive_window']._serialized_options = b'\272H\007*\005\030\200\010(\001' + _globals['_TCPSETTINGS']._loaded_options = None + _globals['_TCPSETTINGS']._serialized_options = b'\272H\203\003\032\363\001\n\026tcp_settings.non_empty\022/a treatment must set at least one TCP parameter\032\247\001has(this.congestion_control) || has(this.rto_min_ms) || has(this.initial_congestion_window) || has(this.initial_receive_window) || has(this.quick_ack) || has(this.ecn)\032\212\001\n$tcp_settings.lock_requires_algorithm\022+congestion_lock requires congestion_control\0325!this.congestion_lock || has(this.congestion_control)' + _globals['_TREATMENT'].fields_by_name['id']._loaded_options = None + _globals['_TREATMENT'].fields_by_name['id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_TREATMENT'].fields_by_name['revision']._loaded_options = None + _globals['_TREATMENT'].fields_by_name['revision']._serialized_options = b'\272H\0042\002 \000' + _globals['_TREATMENT'].fields_by_name['destination']._loaded_options = None + _globals['_TREATMENT'].fields_by_name['destination']._serialized_options = b'\272H\007r\005\0301\350\001\001' + _globals['_TREATMENT'].fields_by_name['settings']._loaded_options = None + _globals['_TREATMENT'].fields_by_name['settings']._serialized_options = b'\272H\003\310\001\001' + _globals['_TREATMENT']._loaded_options = None + _globals['_TREATMENT']._serialized_options = b'\272H\304\001\032\301\001\n\034treatment.dctcp_requires_ecn\022ADCTCP requires independently verified ECN fabric and explicit ECN\032^this.settings.congestion_control != \'dctcp\' || (this.ecn_fabric_verified && this.settings.ecn)' + _globals['_ASSIGNMENT'].fields_by_name['experiment_id']._loaded_options = None + _globals['_ASSIGNMENT'].fields_by_name['experiment_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_ASSIGNMENT'].fields_by_name['treatment']._loaded_options = None + _globals['_ASSIGNMENT'].fields_by_name['treatment']._serialized_options = b'\272H\003\310\001\001' + _globals['_ASSIGNMENT'].fields_by_name['mode']._loaded_options = None + _globals['_ASSIGNMENT'].fields_by_name['mode']._serialized_options = b'\272H\007\202\001\004\020\001 \000' + _globals['_ASSIGNMENT'].fields_by_name['generation']._loaded_options = None + _globals['_ASSIGNMENT'].fields_by_name['generation']._serialized_options = b'\272H\0042\002 \000' + _globals['_ASSIGNMENT']._loaded_options = None + _globals['_ASSIGNMENT']._serialized_options = b'\272H\251\002\032}\n\037assignment.trial_requires_lease\022,a trial assignment requires lease_expires_at\032,this.mode != 1 || has(this.lease_expires_at)\032\247\001\n\"assignment.predecessor_destination\022+predecessor must cover the same destination\032T!has(this.predecessor) || this.predecessor.destination == this.treatment.destination' + _globals['_DESIREDSTATE'].fields_by_name['agent_id']._loaded_options = None + _globals['_DESIREDSTATE'].fields_by_name['agent_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_DESIREDSTATE'].fields_by_name['revision']._loaded_options = None + _globals['_DESIREDSTATE'].fields_by_name['revision']._serialized_options = b'\272H\0042\002 \000' + _globals['_DESIREDSTATE'].fields_by_name['assignments']._loaded_options = None + _globals['_DESIREDSTATE'].fields_by_name['assignments']._serialized_options = b'\272H\006\222\001\003\020\200 ' + _globals['_DESIREDSTATE'].fields_by_name['issued_at']._loaded_options = None + _globals['_DESIREDSTATE'].fields_by_name['issued_at']._serialized_options = b'\272H\003\310\001\001' + _globals['_CAPABILITIES'].fields_by_name['boot_id']._loaded_options = None + _globals['_CAPABILITIES'].fields_by_name['boot_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_CAPABILITIES'].fields_by_name['kernel_release']._loaded_options = None + _globals['_CAPABILITIES'].fields_by_name['kernel_release']._serialized_options = b'\272H\005r\003\030\200\002' + _globals['_CAPABILITIES'].fields_by_name['congestion_algorithms']._loaded_options = None + _globals['_CAPABILITIES'].fields_by_name['congestion_algorithms']._serialized_options = b'\272H\013\222\001\010\020@\"\004r\002\030\017' + _globals['_CAPABILITIES'].fields_by_name['collection_id']._loaded_options = None + _globals['_CAPABILITIES'].fields_by_name['collection_id']._serialized_options = b'\272H\022r\0202\016^[0-9a-f]{32}$' + _globals['_APPLICATIONRECORD'].fields_by_name['assignment']._loaded_options = None + _globals['_APPLICATIONRECORD'].fields_by_name['assignment']._serialized_options = b'\272H\003\310\001\001' + _globals['_APPLICATIONRECORD'].fields_by_name['status']._loaded_options = None + _globals['_APPLICATIONRECORD'].fields_by_name['status']._serialized_options = b'\272H\005\202\001\002\020\001' + _globals['_APPLICATIONRECORD'].fields_by_name['error']._loaded_options = None + _globals['_APPLICATIONRECORD'].fields_by_name['error']._serialized_options = b'\272H\005r\003\030\200 ' + _globals['_APPLICATIONRECORD'].fields_by_name['installed_route']._loaded_options = None + _globals['_APPLICATIONRECORD'].fields_by_name['installed_route']._serialized_options = b'\272H\005z\003\030\200 ' + _globals['_APPLICATIONRECORD'].fields_by_name['installed_boot_id']._loaded_options = None + _globals['_APPLICATIONRECORD'].fields_by_name['installed_boot_id']._serialized_options = b'\272H\005r\003\030\200\001' + _globals['_LOCALSTATE'].fields_by_name['suspension_reason']._loaded_options = None + _globals['_LOCALSTATE'].fields_by_name['suspension_reason']._serialized_options = b'\272H\005r\003\030\200\010' + _globals['_LOCALSTATE'].fields_by_name['records']._loaded_options = None + _globals['_LOCALSTATE'].fields_by_name['records']._serialized_options = b'\272H\006\222\001\003\020\200@' + _globals['_HOSTEVIDENCE'].fields_by_name['agent_id']._loaded_options = None + _globals['_HOSTEVIDENCE'].fields_by_name['agent_id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_HOSTEVIDENCE'].fields_by_name['goodput_bps']._loaded_options = None + _globals['_HOSTEVIDENCE'].fields_by_name['goodput_bps']._serialized_options = b'\272H\r\022\013)\000\000\000\000\000\000\000\000@\001' + _globals['_HOSTEVIDENCE'].fields_by_name['retransmission_ratio']._loaded_options = None + _globals['_HOSTEVIDENCE'].fields_by_name['retransmission_ratio']._serialized_options = b'\272H\r\022\013)\000\000\000\000\000\000\000\000@\001' + _globals['_HOSTEVIDENCE'].fields_by_name['rtt_p95_ms']._loaded_options = None + _globals['_HOSTEVIDENCE'].fields_by_name['rtt_p95_ms']._serialized_options = b'\272H\r\022\013)\000\000\000\000\000\000\000\000@\001' + _globals['_HOSTEVIDENCE']._loaded_options = None + _globals['_HOSTEVIDENCE']._serialized_options = b'\272Hu\032s\n$host_evidence.exposed_within_sockets\022%exposed_sockets cannot exceed sockets\032$this.exposed_sockets <= this.sockets' + _globals['_EVIDENCE'].fields_by_name['id']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_EVIDENCE'].fields_by_name['analyzed_at']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['analyzed_at']._serialized_options = b'\272H\003\310\001\001' + _globals['_EVIDENCE'].fields_by_name['window_start']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['window_start']._serialized_options = b'\272H\003\310\001\001' + _globals['_EVIDENCE'].fields_by_name['window_end']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['window_end']._serialized_options = b'\272H\003\310\001\001' + _globals['_EVIDENCE'].fields_by_name['query_version']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['query_version']._serialized_options = b'\272H\007r\005\020\001\030\200\002' + _globals['_EVIDENCE'].fields_by_name['enrichment_version']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['enrichment_version']._serialized_options = b'\272H\005r\003\030\200\002' + _globals['_EVIDENCE'].fields_by_name['hosts']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['hosts']._serialized_options = b'\272H\010\222\001\005\010\001\020\220N' + _globals['_EVIDENCE'].fields_by_name['artifact_sha256']._loaded_options = None + _globals['_EVIDENCE'].fields_by_name['artifact_sha256']._serialized_options = b'\272H\022r\0202\016^[0-9a-f]{64}$' + _globals['_EVIDENCE']._loaded_options = None + _globals['_EVIDENCE']._serialized_options = b'\272H\263\001\032\260\001\n\021evidence.interval\022Owindow_end must follow window_start and analyzed_at must not precede window_end\032Jthis.window_end > this.window_start && this.analyzed_at >= this.window_end' + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_observation']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_observation']._serialized_options = b'\272H\016\252\001\010\"\004\010\200\365$*\000\310\001\001' + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_phase']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_phase']._serialized_options = b'\272H\016\252\001\010\"\004\010\200\365$*\000\310\001\001' + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_sockets_per_host']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_sockets_per_host']._serialized_options = b'\272H\0042\002 \000' + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_bytes_per_host']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_bytes_per_host']._serialized_options = b'\272H\0042\002 \000' + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_treated_hosts']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_treated_hosts']._serialized_options = b'\272H\007*\005\030\220N(\002' + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_improvement']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['minimum_improvement']._serialized_options = b'\272H\026\022\024\031\000\000\000\000\000\000\360?)\000\000\000\000\000\000\000\000@\001' + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_retransmission_increase']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_retransmission_increase']._serialized_options = b'\272H\026\022\024\031\000\000\000\000\000\000\360?)\000\000\000\000\000\000\000\000@\001' + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_rtt_increase']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_rtt_increase']._serialized_options = b'\272H\026\022\024\031\000\000\000\000\000\000\360?)\000\000\000\000\000\000\000\000@\001' + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_evidence_age']._loaded_options = None + _globals['_EXPERIMENTPOLICY'].fields_by_name['maximum_evidence_age']._serialized_options = b'\272H\016\252\001\010\"\004\010\200\365$*\000\310\001\001' + _globals['_EXPERIMENTPOLICY']._loaded_options = None + _globals['_EXPERIMENTPOLICY']._serialized_options = b'\272H\205\001\032\202\001\n\037policy.observation_within_phase\022/minimum_observation cannot exceed maximum_phase\032.this.minimum_observation <= this.maximum_phase' + _globals['_PHASE'].fields_by_name['target_hosts']._loaded_options = None + _globals['_PHASE'].fields_by_name['target_hosts']._serialized_options = b'\272H\007*\005\030\220N(\001' + _globals['_PHASE'].fields_by_name['outcome']._loaded_options = None + _globals['_PHASE'].fields_by_name['outcome']._serialized_options = b'\272H\005\202\001\002\020\001' + _globals['_PHASE'].fields_by_name['reviewer']._loaded_options = None + _globals['_PHASE'].fields_by_name['reviewer']._serialized_options = b'\272H\005r\003\030\200\001' + _globals['_PHASE'].fields_by_name['reason']._loaded_options = None + _globals['_PHASE'].fields_by_name['reason']._serialized_options = b'\272H\005r\003\030\200 ' + _globals['_EXPERIMENT'].fields_by_name['id']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['id']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_EXPERIMENT'].fields_by_name['location']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['location']._serialized_options = b'\272H&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_EXPERIMENT'].fields_by_name['hypothesis']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['hypothesis']._serialized_options = b'\272H\007r\005\020\001\030\200@' + _globals['_EXPERIMENT'].fields_by_name['treatment']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['treatment']._serialized_options = b'\272H\003\310\001\001' + _globals['_EXPERIMENT'].fields_by_name['policy']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['policy']._serialized_options = b'\272H\003\310\001\001' + _globals['_EXPERIMENT'].fields_by_name['baseline']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['baseline']._serialized_options = b'\272H\003\310\001\001' + _globals['_EXPERIMENT'].fields_by_name['cohort_order']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['cohort_order']._serialized_options = b'\272H2\222\001/\010\003\020\220N\030\001\"&r$2\"^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$' + _globals['_EXPERIMENT'].fields_by_name['phases']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['phases']._serialized_options = b'\272H\005\222\001\002\020@' + _globals['_EXPERIMENT'].fields_by_name['status']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['status']._serialized_options = b'\272H\005\202\001\002\020\001' + _globals['_EXPERIMENT'].fields_by_name['latest_outcome']._loaded_options = None + _globals['_EXPERIMENT'].fields_by_name['latest_outcome']._serialized_options = b'\272H\005\202\001\002\020\001' + _globals['_ROLE']._serialized_start=7436 + _globals['_ROLE']._serialized_end=7499 + _globals['_ASSIGNMENTMODE']._serialized_start=7502 + _globals['_ASSIGNMENTMODE']._serialized_end=7666 + _globals['_APPLYSTATUS']._serialized_start=7669 + _globals['_APPLYSTATUS']._serialized_end=7842 + _globals['_OUTCOME']._serialized_start=7845 + _globals['_OUTCOME']._serialized_end=8393 + _globals['_EXPERIMENTSTATUS']._serialized_start=8396 + _globals['_EXPERIMENTSTATUS']._serialized_end=8673 + _globals['_TCPSETTINGS']._serialized_start=185 + _globals['_TCPSETTINGS']._serialized_end=1094 + _globals['_TREATMENT']._serialized_start=1097 + _globals['_TREATMENT']._serialized_end=1569 + _globals['_ASSIGNMENT']._serialized_start=1572 + _globals['_ASSIGNMENT']._serialized_end=2288 + _globals['_DESIREDSTATE']._serialized_start=2291 + _globals['_DESIREDSTATE']._serialized_end=2583 + _globals['_CAPABILITIES']._serialized_start=2586 + _globals['_CAPABILITIES']._serialized_end=2937 + _globals['_APPLICATIONRECORD']._serialized_start=2940 + _globals['_APPLICATIONRECORD']._serialized_end=3620 + _globals['_LOCALSTATE']._serialized_start=3623 + _globals['_LOCALSTATE']._serialized_end=3928 + _globals['_HOSTEVIDENCE']._serialized_start=3931 + _globals['_HOSTEVIDENCE']._serialized_end=4493 + _globals['_EVIDENCE']._serialized_start=4496 + _globals['_EVIDENCE']._serialized_end=5196 + _globals['_EXPERIMENTPOLICY']._serialized_start=5199 + _globals['_EXPERIMENTPOLICY']._serialized_end=6075 + _globals['_PHASE']._serialized_start=6078 + _globals['_PHASE']._serialized_end=6527 + _globals['_EXPERIMENT']._serialized_start=6530 + _globals['_EXPERIMENT']._serialized_end=7434 +# @@protoc_insertion_point(module_scope) diff --git a/gen/python/xtcp_treatment/v1/treatment_pb2.pyi b/gen/python/xtcp_treatment/v1/treatment_pb2.pyi new file mode 100644 index 000000000..29fda970f --- /dev/null +++ b/gen/python/xtcp_treatment/v1/treatment_pb2.pyi @@ -0,0 +1,349 @@ +import datetime + +from buf.validate import validate_pb2 as _validate_pb2 +from google.protobuf import descriptor_pb2 as _descriptor_pb2 +from google.protobuf import duration_pb2 as _duration_pb2 +from google.protobuf import timestamp_pb2 as _timestamp_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class Role(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ROLE_UNSPECIFIED: _ClassVar[Role] + ROLE_AGENT: _ClassVar[Role] + ROLE_OPERATOR: _ClassVar[Role] + +class AssignmentMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ASSIGNMENT_MODE_UNSPECIFIED: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_TRIAL: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_STABLE: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_SUSPENDED: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_RETIRED: _ClassVar[AssignmentMode] + +class ApplyStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + APPLY_STATUS_UNSPECIFIED: _ClassVar[ApplyStatus] + APPLY_STATUS_PENDING: _ClassVar[ApplyStatus] + APPLY_STATUS_VERIFIED: _ClassVar[ApplyStatus] + APPLY_STATUS_REMOVED: _ClassVar[ApplyStatus] + APPLY_STATUS_EXPIRED: _ClassVar[ApplyStatus] + APPLY_STATUS_FAILED: _ClassVar[ApplyStatus] + +class Outcome(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + OUTCOME_UNSPECIFIED: _ClassVar[Outcome] + OUTCOME_BASELINE: _ClassVar[Outcome] + OUTCOME_AWAITING_APPLICATION: _ClassVar[Outcome] + OUTCOME_AWAITING_EXPOSURE: _ClassVar[Outcome] + OUTCOME_INSUFFICIENT_DURATION: _ClassVar[Outcome] + OUTCOME_INSUFFICIENT_DATA: _ClassVar[Outcome] + OUTCOME_INSUFFICIENT_CONTROLS: _ClassVar[Outcome] + OUTCOME_STALE: _ClassVar[Outcome] + OUTCOME_UNAVAILABLE: _ClassVar[Outcome] + OUTCOME_INCONCLUSIVE: _ClassVar[Outcome] + OUTCOME_SAFETY_ONLY: _ClassVar[Outcome] + OUTCOME_FINAL_SAFETY: _ClassVar[Outcome] + OUTCOME_BENEFICIAL: _ClassVar[Outcome] + OUTCOME_HARMFUL: _ClassVar[Outcome] + OUTCOME_EXPIRED: _ClassVar[Outcome] + OUTCOME_STABLE_OBSERVED: _ClassVar[Outcome] + OUTCOME_STABLE_EVIDENCE_INCOMPLETE: _ClassVar[Outcome] + OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED: _ClassVar[Outcome] + OUTCOME_OBSERVING: _ClassVar[Outcome] + +class ExperimentStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + EXPERIMENT_STATUS_UNSPECIFIED: _ClassVar[ExperimentStatus] + EXPERIMENT_STATUS_PROPOSED: _ClassVar[ExperimentStatus] + EXPERIMENT_STATUS_RUNNING: _ClassVar[ExperimentStatus] + EXPERIMENT_STATUS_PAUSED: _ClassVar[ExperimentStatus] + EXPERIMENT_STATUS_SUSPENDED: _ClassVar[ExperimentStatus] + EXPERIMENT_STATUS_COMPLETE: _ClassVar[ExperimentStatus] + EXPERIMENT_STATUS_RETIRED: _ClassVar[ExperimentStatus] + EXPERIMENT_STATUS_ROLLED_BACK: _ClassVar[ExperimentStatus] +ROLE_UNSPECIFIED: Role +ROLE_AGENT: Role +ROLE_OPERATOR: Role +ASSIGNMENT_MODE_UNSPECIFIED: AssignmentMode +ASSIGNMENT_MODE_TRIAL: AssignmentMode +ASSIGNMENT_MODE_STABLE: AssignmentMode +ASSIGNMENT_MODE_SUSPENDED: AssignmentMode +ASSIGNMENT_MODE_RETIRED: AssignmentMode +APPLY_STATUS_UNSPECIFIED: ApplyStatus +APPLY_STATUS_PENDING: ApplyStatus +APPLY_STATUS_VERIFIED: ApplyStatus +APPLY_STATUS_REMOVED: ApplyStatus +APPLY_STATUS_EXPIRED: ApplyStatus +APPLY_STATUS_FAILED: ApplyStatus +OUTCOME_UNSPECIFIED: Outcome +OUTCOME_BASELINE: Outcome +OUTCOME_AWAITING_APPLICATION: Outcome +OUTCOME_AWAITING_EXPOSURE: Outcome +OUTCOME_INSUFFICIENT_DURATION: Outcome +OUTCOME_INSUFFICIENT_DATA: Outcome +OUTCOME_INSUFFICIENT_CONTROLS: Outcome +OUTCOME_STALE: Outcome +OUTCOME_UNAVAILABLE: Outcome +OUTCOME_INCONCLUSIVE: Outcome +OUTCOME_SAFETY_ONLY: Outcome +OUTCOME_FINAL_SAFETY: Outcome +OUTCOME_BENEFICIAL: Outcome +OUTCOME_HARMFUL: Outcome +OUTCOME_EXPIRED: Outcome +OUTCOME_STABLE_OBSERVED: Outcome +OUTCOME_STABLE_EVIDENCE_INCOMPLETE: Outcome +OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED: Outcome +OUTCOME_OBSERVING: Outcome +EXPERIMENT_STATUS_UNSPECIFIED: ExperimentStatus +EXPERIMENT_STATUS_PROPOSED: ExperimentStatus +EXPERIMENT_STATUS_RUNNING: ExperimentStatus +EXPERIMENT_STATUS_PAUSED: ExperimentStatus +EXPERIMENT_STATUS_SUSPENDED: ExperimentStatus +EXPERIMENT_STATUS_COMPLETE: ExperimentStatus +EXPERIMENT_STATUS_RETIRED: ExperimentStatus +EXPERIMENT_STATUS_ROLLED_BACK: ExperimentStatus +ROLE_FIELD_NUMBER: _ClassVar[int] +role: _descriptor.FieldDescriptor + +class TCPSettings(_message.Message): + __slots__ = ("congestion_control", "congestion_lock", "rto_min_ms", "initial_congestion_window", "initial_receive_window", "quick_ack", "ecn") + CONGESTION_CONTROL_FIELD_NUMBER: _ClassVar[int] + CONGESTION_LOCK_FIELD_NUMBER: _ClassVar[int] + RTO_MIN_MS_FIELD_NUMBER: _ClassVar[int] + INITIAL_CONGESTION_WINDOW_FIELD_NUMBER: _ClassVar[int] + INITIAL_RECEIVE_WINDOW_FIELD_NUMBER: _ClassVar[int] + QUICK_ACK_FIELD_NUMBER: _ClassVar[int] + ECN_FIELD_NUMBER: _ClassVar[int] + congestion_control: str + congestion_lock: bool + rto_min_ms: int + initial_congestion_window: int + initial_receive_window: int + quick_ack: bool + ecn: bool + def __init__(self, congestion_control: _Optional[str] = ..., congestion_lock: _Optional[bool] = ..., rto_min_ms: _Optional[int] = ..., initial_congestion_window: _Optional[int] = ..., initial_receive_window: _Optional[int] = ..., quick_ack: _Optional[bool] = ..., ecn: _Optional[bool] = ...) -> None: ... + +class Treatment(_message.Message): + __slots__ = ("id", "revision", "destination", "settings", "ecn_fabric_verified") + ID_FIELD_NUMBER: _ClassVar[int] + REVISION_FIELD_NUMBER: _ClassVar[int] + DESTINATION_FIELD_NUMBER: _ClassVar[int] + SETTINGS_FIELD_NUMBER: _ClassVar[int] + ECN_FABRIC_VERIFIED_FIELD_NUMBER: _ClassVar[int] + id: str + revision: int + destination: str + settings: TCPSettings + ecn_fabric_verified: bool + def __init__(self, id: _Optional[str] = ..., revision: _Optional[int] = ..., destination: _Optional[str] = ..., settings: _Optional[_Union[TCPSettings, _Mapping]] = ..., ecn_fabric_verified: _Optional[bool] = ...) -> None: ... + +class Assignment(_message.Message): + __slots__ = ("experiment_id", "treatment", "mode", "lease_expires_at", "predecessor", "generation") + EXPERIMENT_ID_FIELD_NUMBER: _ClassVar[int] + TREATMENT_FIELD_NUMBER: _ClassVar[int] + MODE_FIELD_NUMBER: _ClassVar[int] + LEASE_EXPIRES_AT_FIELD_NUMBER: _ClassVar[int] + PREDECESSOR_FIELD_NUMBER: _ClassVar[int] + GENERATION_FIELD_NUMBER: _ClassVar[int] + experiment_id: str + treatment: Treatment + mode: AssignmentMode + lease_expires_at: _timestamp_pb2.Timestamp + predecessor: Treatment + generation: int + def __init__(self, experiment_id: _Optional[str] = ..., treatment: _Optional[_Union[Treatment, _Mapping]] = ..., mode: _Optional[_Union[AssignmentMode, str]] = ..., lease_expires_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., predecessor: _Optional[_Union[Treatment, _Mapping]] = ..., generation: _Optional[int] = ...) -> None: ... + +class DesiredState(_message.Message): + __slots__ = ("agent_id", "revision", "suspended", "assignments", "issued_at") + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + REVISION_FIELD_NUMBER: _ClassVar[int] + SUSPENDED_FIELD_NUMBER: _ClassVar[int] + ASSIGNMENTS_FIELD_NUMBER: _ClassVar[int] + ISSUED_AT_FIELD_NUMBER: _ClassVar[int] + agent_id: str + revision: int + suspended: bool + assignments: _containers.RepeatedCompositeFieldContainer[Assignment] + issued_at: _timestamp_pb2.Timestamp + def __init__(self, agent_id: _Optional[str] = ..., revision: _Optional[int] = ..., suspended: _Optional[bool] = ..., assignments: _Optional[_Iterable[_Union[Assignment, _Mapping]]] = ..., issued_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... + +class Capabilities(_message.Message): + __slots__ = ("boot_id", "kernel_release", "congestion_algorithms", "simple_host_routing", "actuator_enabled", "collection_id") + BOOT_ID_FIELD_NUMBER: _ClassVar[int] + KERNEL_RELEASE_FIELD_NUMBER: _ClassVar[int] + CONGESTION_ALGORITHMS_FIELD_NUMBER: _ClassVar[int] + SIMPLE_HOST_ROUTING_FIELD_NUMBER: _ClassVar[int] + ACTUATOR_ENABLED_FIELD_NUMBER: _ClassVar[int] + COLLECTION_ID_FIELD_NUMBER: _ClassVar[int] + boot_id: str + kernel_release: str + congestion_algorithms: _containers.RepeatedScalarFieldContainer[str] + simple_host_routing: bool + actuator_enabled: bool + collection_id: str + def __init__(self, boot_id: _Optional[str] = ..., kernel_release: _Optional[str] = ..., congestion_algorithms: _Optional[_Iterable[str]] = ..., simple_host_routing: _Optional[bool] = ..., actuator_enabled: _Optional[bool] = ..., collection_id: _Optional[str] = ...) -> None: ... + +class ApplicationRecord(_message.Message): + __slots__ = ("assignment", "desired_revision", "status", "received_at", "attempted_at", "applied_at", "verified_at", "removed_at", "error", "installed_route", "installed_boot_id", "expired_latched") + ASSIGNMENT_FIELD_NUMBER: _ClassVar[int] + DESIRED_REVISION_FIELD_NUMBER: _ClassVar[int] + STATUS_FIELD_NUMBER: _ClassVar[int] + RECEIVED_AT_FIELD_NUMBER: _ClassVar[int] + ATTEMPTED_AT_FIELD_NUMBER: _ClassVar[int] + APPLIED_AT_FIELD_NUMBER: _ClassVar[int] + VERIFIED_AT_FIELD_NUMBER: _ClassVar[int] + REMOVED_AT_FIELD_NUMBER: _ClassVar[int] + ERROR_FIELD_NUMBER: _ClassVar[int] + INSTALLED_ROUTE_FIELD_NUMBER: _ClassVar[int] + INSTALLED_BOOT_ID_FIELD_NUMBER: _ClassVar[int] + EXPIRED_LATCHED_FIELD_NUMBER: _ClassVar[int] + assignment: Assignment + desired_revision: int + status: ApplyStatus + received_at: _timestamp_pb2.Timestamp + attempted_at: _timestamp_pb2.Timestamp + applied_at: _timestamp_pb2.Timestamp + verified_at: _timestamp_pb2.Timestamp + removed_at: _timestamp_pb2.Timestamp + error: str + installed_route: bytes + installed_boot_id: str + expired_latched: bool + def __init__(self, assignment: _Optional[_Union[Assignment, _Mapping]] = ..., desired_revision: _Optional[int] = ..., status: _Optional[_Union[ApplyStatus, str]] = ..., received_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., attempted_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., applied_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., verified_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., removed_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., error: _Optional[str] = ..., installed_route: _Optional[bytes] = ..., installed_boot_id: _Optional[str] = ..., expired_latched: _Optional[bool] = ...) -> None: ... + +class LocalState(_message.Message): + __slots__ = ("desired", "locally_suspended", "suspension_reason", "records", "updated_at") + DESIRED_FIELD_NUMBER: _ClassVar[int] + LOCALLY_SUSPENDED_FIELD_NUMBER: _ClassVar[int] + SUSPENSION_REASON_FIELD_NUMBER: _ClassVar[int] + RECORDS_FIELD_NUMBER: _ClassVar[int] + UPDATED_AT_FIELD_NUMBER: _ClassVar[int] + desired: DesiredState + locally_suspended: bool + suspension_reason: str + records: _containers.RepeatedCompositeFieldContainer[ApplicationRecord] + updated_at: _timestamp_pb2.Timestamp + def __init__(self, desired: _Optional[_Union[DesiredState, _Mapping]] = ..., locally_suspended: _Optional[bool] = ..., suspension_reason: _Optional[str] = ..., records: _Optional[_Iterable[_Union[ApplicationRecord, _Mapping]]] = ..., updated_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... + +class HostEvidence(_message.Message): + __slots__ = ("agent_id", "sockets", "bytes_acked", "goodput_bps", "retransmission_ratio", "rtt_p95_ms", "exposed_sockets", "collection_healthy", "unbound_sockets") + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + SOCKETS_FIELD_NUMBER: _ClassVar[int] + BYTES_ACKED_FIELD_NUMBER: _ClassVar[int] + GOODPUT_BPS_FIELD_NUMBER: _ClassVar[int] + RETRANSMISSION_RATIO_FIELD_NUMBER: _ClassVar[int] + RTT_P95_MS_FIELD_NUMBER: _ClassVar[int] + EXPOSED_SOCKETS_FIELD_NUMBER: _ClassVar[int] + COLLECTION_HEALTHY_FIELD_NUMBER: _ClassVar[int] + UNBOUND_SOCKETS_FIELD_NUMBER: _ClassVar[int] + agent_id: str + sockets: int + bytes_acked: int + goodput_bps: float + retransmission_ratio: float + rtt_p95_ms: float + exposed_sockets: int + collection_healthy: bool + unbound_sockets: int + def __init__(self, agent_id: _Optional[str] = ..., sockets: _Optional[int] = ..., bytes_acked: _Optional[int] = ..., goodput_bps: _Optional[float] = ..., retransmission_ratio: _Optional[float] = ..., rtt_p95_ms: _Optional[float] = ..., exposed_sockets: _Optional[int] = ..., collection_healthy: _Optional[bool] = ..., unbound_sockets: _Optional[int] = ...) -> None: ... + +class Evidence(_message.Message): + __slots__ = ("id", "analyzed_at", "window_start", "window_end", "query_version", "enrichment_version", "hosts", "artifact_sha256") + ID_FIELD_NUMBER: _ClassVar[int] + ANALYZED_AT_FIELD_NUMBER: _ClassVar[int] + WINDOW_START_FIELD_NUMBER: _ClassVar[int] + WINDOW_END_FIELD_NUMBER: _ClassVar[int] + QUERY_VERSION_FIELD_NUMBER: _ClassVar[int] + ENRICHMENT_VERSION_FIELD_NUMBER: _ClassVar[int] + HOSTS_FIELD_NUMBER: _ClassVar[int] + ARTIFACT_SHA256_FIELD_NUMBER: _ClassVar[int] + id: str + analyzed_at: _timestamp_pb2.Timestamp + window_start: _timestamp_pb2.Timestamp + window_end: _timestamp_pb2.Timestamp + query_version: str + enrichment_version: str + hosts: _containers.RepeatedCompositeFieldContainer[HostEvidence] + artifact_sha256: str + def __init__(self, id: _Optional[str] = ..., analyzed_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., window_start: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., window_end: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., query_version: _Optional[str] = ..., enrichment_version: _Optional[str] = ..., hosts: _Optional[_Iterable[_Union[HostEvidence, _Mapping]]] = ..., artifact_sha256: _Optional[str] = ...) -> None: ... + +class ExperimentPolicy(_message.Message): + __slots__ = ("minimum_observation", "maximum_phase", "minimum_sockets_per_host", "minimum_bytes_per_host", "minimum_treated_hosts", "minimum_improvement", "maximum_retransmission_increase", "maximum_rtt_increase", "maximum_evidence_age") + MINIMUM_OBSERVATION_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_PHASE_FIELD_NUMBER: _ClassVar[int] + MINIMUM_SOCKETS_PER_HOST_FIELD_NUMBER: _ClassVar[int] + MINIMUM_BYTES_PER_HOST_FIELD_NUMBER: _ClassVar[int] + MINIMUM_TREATED_HOSTS_FIELD_NUMBER: _ClassVar[int] + MINIMUM_IMPROVEMENT_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_RETRANSMISSION_INCREASE_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_RTT_INCREASE_FIELD_NUMBER: _ClassVar[int] + MAXIMUM_EVIDENCE_AGE_FIELD_NUMBER: _ClassVar[int] + minimum_observation: _duration_pb2.Duration + maximum_phase: _duration_pb2.Duration + minimum_sockets_per_host: int + minimum_bytes_per_host: int + minimum_treated_hosts: int + minimum_improvement: float + maximum_retransmission_increase: float + maximum_rtt_increase: float + maximum_evidence_age: _duration_pb2.Duration + def __init__(self, minimum_observation: _Optional[_Union[datetime.timedelta, _duration_pb2.Duration, _Mapping]] = ..., maximum_phase: _Optional[_Union[datetime.timedelta, _duration_pb2.Duration, _Mapping]] = ..., minimum_sockets_per_host: _Optional[int] = ..., minimum_bytes_per_host: _Optional[int] = ..., minimum_treated_hosts: _Optional[int] = ..., minimum_improvement: _Optional[float] = ..., maximum_retransmission_increase: _Optional[float] = ..., maximum_rtt_increase: _Optional[float] = ..., maximum_evidence_age: _Optional[_Union[datetime.timedelta, _duration_pb2.Duration, _Mapping]] = ...) -> None: ... + +class Phase(_message.Message): + __slots__ = ("target_hosts", "issued_at", "observation_started_at", "evaluated_at", "evidence", "outcome", "reviewer", "reason") + TARGET_HOSTS_FIELD_NUMBER: _ClassVar[int] + ISSUED_AT_FIELD_NUMBER: _ClassVar[int] + OBSERVATION_STARTED_AT_FIELD_NUMBER: _ClassVar[int] + EVALUATED_AT_FIELD_NUMBER: _ClassVar[int] + EVIDENCE_FIELD_NUMBER: _ClassVar[int] + OUTCOME_FIELD_NUMBER: _ClassVar[int] + REVIEWER_FIELD_NUMBER: _ClassVar[int] + REASON_FIELD_NUMBER: _ClassVar[int] + target_hosts: int + issued_at: _timestamp_pb2.Timestamp + observation_started_at: _timestamp_pb2.Timestamp + evaluated_at: _timestamp_pb2.Timestamp + evidence: Evidence + outcome: Outcome + reviewer: str + reason: str + def __init__(self, target_hosts: _Optional[int] = ..., issued_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., observation_started_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., evaluated_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., evidence: _Optional[_Union[Evidence, _Mapping]] = ..., outcome: _Optional[_Union[Outcome, str]] = ..., reviewer: _Optional[str] = ..., reason: _Optional[str] = ...) -> None: ... + +class Experiment(_message.Message): + __slots__ = ("id", "location", "hypothesis", "treatment", "policy", "baseline", "cohort_order", "phases", "status", "revision", "proposed_at", "latest_evidence", "latest_outcome", "updated_at") + ID_FIELD_NUMBER: _ClassVar[int] + LOCATION_FIELD_NUMBER: _ClassVar[int] + HYPOTHESIS_FIELD_NUMBER: _ClassVar[int] + TREATMENT_FIELD_NUMBER: _ClassVar[int] + POLICY_FIELD_NUMBER: _ClassVar[int] + BASELINE_FIELD_NUMBER: _ClassVar[int] + COHORT_ORDER_FIELD_NUMBER: _ClassVar[int] + PHASES_FIELD_NUMBER: _ClassVar[int] + STATUS_FIELD_NUMBER: _ClassVar[int] + REVISION_FIELD_NUMBER: _ClassVar[int] + PROPOSED_AT_FIELD_NUMBER: _ClassVar[int] + LATEST_EVIDENCE_FIELD_NUMBER: _ClassVar[int] + LATEST_OUTCOME_FIELD_NUMBER: _ClassVar[int] + UPDATED_AT_FIELD_NUMBER: _ClassVar[int] + id: str + location: str + hypothesis: str + treatment: Treatment + policy: ExperimentPolicy + baseline: Evidence + cohort_order: _containers.RepeatedScalarFieldContainer[str] + phases: _containers.RepeatedCompositeFieldContainer[Phase] + status: ExperimentStatus + revision: int + proposed_at: _timestamp_pb2.Timestamp + latest_evidence: Evidence + latest_outcome: Outcome + updated_at: _timestamp_pb2.Timestamp + def __init__(self, id: _Optional[str] = ..., location: _Optional[str] = ..., hypothesis: _Optional[str] = ..., treatment: _Optional[_Union[Treatment, _Mapping]] = ..., policy: _Optional[_Union[ExperimentPolicy, _Mapping]] = ..., baseline: _Optional[_Union[Evidence, _Mapping]] = ..., cohort_order: _Optional[_Iterable[str]] = ..., phases: _Optional[_Iterable[_Union[Phase, _Mapping]]] = ..., status: _Optional[_Union[ExperimentStatus, str]] = ..., revision: _Optional[int] = ..., proposed_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., latest_evidence: _Optional[_Union[Evidence, _Mapping]] = ..., latest_outcome: _Optional[_Union[Outcome, str]] = ..., updated_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ... diff --git a/gen/python/xtcp_treatment/v1/treatment_pb2_grpc.py b/gen/python/xtcp_treatment/v1/treatment_pb2_grpc.py new file mode 100644 index 000000000..2daafffeb --- /dev/null +++ b/gen/python/xtcp_treatment/v1/treatment_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/gen/python/xtcp_treatment_journal/v1/journal_pb2.py b/gen/python/xtcp_treatment_journal/v1/journal_pb2.py new file mode 100644 index 000000000..f1abdae3c --- /dev/null +++ b/gen/python/xtcp_treatment_journal/v1/journal_pb2.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: xtcp_treatment_journal/v1/journal.proto +# Protobuf Python Version: 7.36.2 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 7, + 36, + 2, + '', + 'xtcp_treatment_journal/v1/journal.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'xtcp_treatment_journal/v1/journal.proto\x12\x19xtcp_treatment_journal.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb7\x03\n\x0bTCPSettings\x12\x32\n\x12\x63ongestion_control\x18\x01 \x01(\tH\x00R\x11\x63ongestionControl\x88\x01\x01\x12\'\n\x0f\x63ongestion_lock\x18\x02 \x01(\x08R\x0e\x63ongestionLock\x12!\n\nrto_min_ms\x18\x03 \x01(\rH\x01R\x08rtoMinMs\x88\x01\x01\x12?\n\x19initial_congestion_window\x18\x04 \x01(\rH\x02R\x17initialCongestionWindow\x88\x01\x01\x12\x39\n\x16initial_receive_window\x18\x05 \x01(\rH\x03R\x14initialReceiveWindow\x88\x01\x01\x12 \n\tquick_ack\x18\x06 \x01(\x08H\x04R\x08quickAck\x88\x01\x01\x12\x15\n\x03\x65\x63n\x18\x07 \x01(\x08H\x05R\x03\x65\x63n\x88\x01\x01\x42\x15\n\x13_congestion_controlB\r\n\x0b_rto_min_msB\x1c\n\x1a_initial_congestion_windowB\x19\n\x17_initial_receive_windowB\x0c\n\n_quick_ackB\x06\n\x04_ecn\"\xcd\x01\n\tTreatment\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x1a\n\x08revision\x18\x02 \x01(\x04R\x08revision\x12 \n\x0b\x64\x65stination\x18\x03 \x01(\tR\x0b\x64\x65stination\x12\x42\n\x08settings\x18\x04 \x01(\x0b\x32&.xtcp_treatment_journal.v1.TCPSettingsR\x08settings\x12.\n\x13\x65\x63n_fabric_verified\x18\x05 \x01(\x08R\x11\x65\x63nFabricVerified\"\xe2\x02\n\nAssignment\x12#\n\rexperiment_id\x18\x01 \x01(\tR\x0c\x65xperimentId\x12\x42\n\ttreatment\x18\x02 \x01(\x0b\x32$.xtcp_treatment_journal.v1.TreatmentR\ttreatment\x12=\n\x04mode\x18\x03 \x01(\x0e\x32).xtcp_treatment_journal.v1.AssignmentModeR\x04mode\x12\x44\n\x10lease_expires_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0eleaseExpiresAt\x12\x46\n\x0bpredecessor\x18\x05 \x01(\x0b\x32$.xtcp_treatment_journal.v1.TreatmentR\x0bpredecessor\x12\x1e\n\ngeneration\x18\x06 \x01(\x04R\ngeneration\"\xc5\x01\n\x07\x44\x65sired\x12\x1a\n\x08revision\x18\x01 \x01(\x04R\x08revision\x12\x1c\n\tsuspended\x18\x02 \x01(\x08R\tsuspended\x12\x37\n\tissued_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x08issuedAt\x12G\n\x0b\x61ssignments\x18\x04 \x03(\x0b\x32%.xtcp_treatment_journal.v1.AssignmentR\x0b\x61ssignments\"\xfd\x04\n\x06Record\x12\x45\n\nassignment\x18\x01 \x01(\x0b\x32%.xtcp_treatment_journal.v1.AssignmentR\nassignment\x12)\n\x10\x64\x65sired_revision\x18\x02 \x01(\x04R\x0f\x64\x65siredRevision\x12>\n\x06status\x18\x03 \x01(\x0e\x32&.xtcp_treatment_journal.v1.ApplyStatusR\x06status\x12;\n\x0breceived_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nreceivedAt\x12=\n\x0c\x61ttempted_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0b\x61ttemptedAt\x12\x39\n\napplied_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tappliedAt\x12;\n\x0bverified_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nverifiedAt\x12\x39\n\nremoved_at\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tremovedAt\x12\x14\n\x05\x65rror\x18\t \x01(\tR\x05\x65rror\x12\'\n\x0finstalled_route\x18\n \x01(\x0cR\x0einstalledRoute\x12*\n\x11installed_boot_id\x18\x0b \x01(\tR\x0finstalledBootId\x12\'\n\x0f\x65xpired_latched\x18\x0c \x01(\x08R\x0e\x65xpiredLatched\"\x8e\x03\n\x07Journal\x12\x19\n\x08\x61gent_id\x18\x01 \x01(\tR\x07\x61gentId\x12\x1a\n\x08location\x18\x02 \x01(\tR\x08location\x12\x17\n\x07\x62oot_id\x18\x03 \x01(\tR\x06\x62ootId\x12<\n\x07\x64\x65sired\x18\x04 \x01(\x0b\x32\".xtcp_treatment_journal.v1.DesiredR\x07\x64\x65sired\x12+\n\x11locally_suspended\x18\x05 \x01(\x08R\x10locallySuspended\x12+\n\x11suspension_reason\x18\x06 \x01(\tR\x10suspensionReason\x12;\n\x07records\x18\x07 \x03(\x0b\x32!.xtcp_treatment_journal.v1.RecordR\x07records\x12\x39\n\nupdated_at\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12#\n\rcollection_id\x18\t \x01(\tR\x0c\x63ollectionId*\xa4\x01\n\x0e\x41ssignmentMode\x12\x1f\n\x1b\x41SSIGNMENT_MODE_UNSPECIFIED\x10\x00\x12\x19\n\x15\x41SSIGNMENT_MODE_TRIAL\x10\x01\x12\x1a\n\x16\x41SSIGNMENT_MODE_STABLE\x10\x02\x12\x1d\n\x19\x41SSIGNMENT_MODE_SUSPENDED\x10\x03\x12\x1b\n\x17\x41SSIGNMENT_MODE_RETIRED\x10\x04*\xad\x01\n\x0b\x41pplyStatus\x12\x1c\n\x18\x41PPLY_STATUS_UNSPECIFIED\x10\x00\x12\x18\n\x14\x41PPLY_STATUS_PENDING\x10\x01\x12\x19\n\x15\x41PPLY_STATUS_VERIFIED\x10\x02\x12\x18\n\x14\x41PPLY_STATUS_REMOVED\x10\x03\x12\x18\n\x14\x41PPLY_STATUS_EXPIRED\x10\x04\x12\x17\n\x13\x41PPLY_STATUS_FAILED\x10\x05\x42\xea\x01\n\x1d\x63om.xtcp_treatment_journal.v1B\x0cJournalProtoP\x01Z>github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment_journal\xa2\x02\x03XXX\xaa\x02\x17XtcpTreatmentJournal.V1\xca\x02\x17XtcpTreatmentJournal\\V1\xe2\x02#XtcpTreatmentJournal\\V1\\GPBMetadata\xea\x02\x18XtcpTreatmentJournal::V1b\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'xtcp_treatment_journal.v1.journal_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\035com.xtcp_treatment_journal.v1B\014JournalProtoP\001Z>github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment_journal\242\002\003XXX\252\002\027XtcpTreatmentJournal.V1\312\002\027XtcpTreatmentJournal\\V1\342\002#XtcpTreatmentJournal\\V1\\GPBMetadata\352\002\030XtcpTreatmentJournal::V1' + _globals['_ASSIGNMENTMODE']._serialized_start=2352 + _globals['_ASSIGNMENTMODE']._serialized_end=2516 + _globals['_APPLYSTATUS']._serialized_start=2519 + _globals['_APPLYSTATUS']._serialized_end=2692 + _globals['_TCPSETTINGS']._serialized_start=104 + _globals['_TCPSETTINGS']._serialized_end=543 + _globals['_TREATMENT']._serialized_start=546 + _globals['_TREATMENT']._serialized_end=751 + _globals['_ASSIGNMENT']._serialized_start=754 + _globals['_ASSIGNMENT']._serialized_end=1108 + _globals['_DESIRED']._serialized_start=1111 + _globals['_DESIRED']._serialized_end=1308 + _globals['_RECORD']._serialized_start=1311 + _globals['_RECORD']._serialized_end=1948 + _globals['_JOURNAL']._serialized_start=1951 + _globals['_JOURNAL']._serialized_end=2349 +# @@protoc_insertion_point(module_scope) diff --git a/gen/python/xtcp_treatment_journal/v1/journal_pb2.pyi b/gen/python/xtcp_treatment_journal/v1/journal_pb2.pyi new file mode 100644 index 000000000..af969ddab --- /dev/null +++ b/gen/python/xtcp_treatment_journal/v1/journal_pb2.pyi @@ -0,0 +1,149 @@ +import datetime + +from google.protobuf import timestamp_pb2 as _timestamp_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class AssignmentMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + ASSIGNMENT_MODE_UNSPECIFIED: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_TRIAL: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_STABLE: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_SUSPENDED: _ClassVar[AssignmentMode] + ASSIGNMENT_MODE_RETIRED: _ClassVar[AssignmentMode] + +class ApplyStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + APPLY_STATUS_UNSPECIFIED: _ClassVar[ApplyStatus] + APPLY_STATUS_PENDING: _ClassVar[ApplyStatus] + APPLY_STATUS_VERIFIED: _ClassVar[ApplyStatus] + APPLY_STATUS_REMOVED: _ClassVar[ApplyStatus] + APPLY_STATUS_EXPIRED: _ClassVar[ApplyStatus] + APPLY_STATUS_FAILED: _ClassVar[ApplyStatus] +ASSIGNMENT_MODE_UNSPECIFIED: AssignmentMode +ASSIGNMENT_MODE_TRIAL: AssignmentMode +ASSIGNMENT_MODE_STABLE: AssignmentMode +ASSIGNMENT_MODE_SUSPENDED: AssignmentMode +ASSIGNMENT_MODE_RETIRED: AssignmentMode +APPLY_STATUS_UNSPECIFIED: ApplyStatus +APPLY_STATUS_PENDING: ApplyStatus +APPLY_STATUS_VERIFIED: ApplyStatus +APPLY_STATUS_REMOVED: ApplyStatus +APPLY_STATUS_EXPIRED: ApplyStatus +APPLY_STATUS_FAILED: ApplyStatus + +class TCPSettings(_message.Message): + __slots__ = ("congestion_control", "congestion_lock", "rto_min_ms", "initial_congestion_window", "initial_receive_window", "quick_ack", "ecn") + CONGESTION_CONTROL_FIELD_NUMBER: _ClassVar[int] + CONGESTION_LOCK_FIELD_NUMBER: _ClassVar[int] + RTO_MIN_MS_FIELD_NUMBER: _ClassVar[int] + INITIAL_CONGESTION_WINDOW_FIELD_NUMBER: _ClassVar[int] + INITIAL_RECEIVE_WINDOW_FIELD_NUMBER: _ClassVar[int] + QUICK_ACK_FIELD_NUMBER: _ClassVar[int] + ECN_FIELD_NUMBER: _ClassVar[int] + congestion_control: str + congestion_lock: bool + rto_min_ms: int + initial_congestion_window: int + initial_receive_window: int + quick_ack: bool + ecn: bool + def __init__(self, congestion_control: _Optional[str] = ..., congestion_lock: _Optional[bool] = ..., rto_min_ms: _Optional[int] = ..., initial_congestion_window: _Optional[int] = ..., initial_receive_window: _Optional[int] = ..., quick_ack: _Optional[bool] = ..., ecn: _Optional[bool] = ...) -> None: ... + +class Treatment(_message.Message): + __slots__ = ("id", "revision", "destination", "settings", "ecn_fabric_verified") + ID_FIELD_NUMBER: _ClassVar[int] + REVISION_FIELD_NUMBER: _ClassVar[int] + DESTINATION_FIELD_NUMBER: _ClassVar[int] + SETTINGS_FIELD_NUMBER: _ClassVar[int] + ECN_FABRIC_VERIFIED_FIELD_NUMBER: _ClassVar[int] + id: str + revision: int + destination: str + settings: TCPSettings + ecn_fabric_verified: bool + def __init__(self, id: _Optional[str] = ..., revision: _Optional[int] = ..., destination: _Optional[str] = ..., settings: _Optional[_Union[TCPSettings, _Mapping]] = ..., ecn_fabric_verified: _Optional[bool] = ...) -> None: ... + +class Assignment(_message.Message): + __slots__ = ("experiment_id", "treatment", "mode", "lease_expires_at", "predecessor", "generation") + EXPERIMENT_ID_FIELD_NUMBER: _ClassVar[int] + TREATMENT_FIELD_NUMBER: _ClassVar[int] + MODE_FIELD_NUMBER: _ClassVar[int] + LEASE_EXPIRES_AT_FIELD_NUMBER: _ClassVar[int] + PREDECESSOR_FIELD_NUMBER: _ClassVar[int] + GENERATION_FIELD_NUMBER: _ClassVar[int] + experiment_id: str + treatment: Treatment + mode: AssignmentMode + lease_expires_at: _timestamp_pb2.Timestamp + predecessor: Treatment + generation: int + def __init__(self, experiment_id: _Optional[str] = ..., treatment: _Optional[_Union[Treatment, _Mapping]] = ..., mode: _Optional[_Union[AssignmentMode, str]] = ..., lease_expires_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., predecessor: _Optional[_Union[Treatment, _Mapping]] = ..., generation: _Optional[int] = ...) -> None: ... + +class Desired(_message.Message): + __slots__ = ("revision", "suspended", "issued_at", "assignments") + REVISION_FIELD_NUMBER: _ClassVar[int] + SUSPENDED_FIELD_NUMBER: _ClassVar[int] + ISSUED_AT_FIELD_NUMBER: _ClassVar[int] + ASSIGNMENTS_FIELD_NUMBER: _ClassVar[int] + revision: int + suspended: bool + issued_at: _timestamp_pb2.Timestamp + assignments: _containers.RepeatedCompositeFieldContainer[Assignment] + def __init__(self, revision: _Optional[int] = ..., suspended: _Optional[bool] = ..., issued_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., assignments: _Optional[_Iterable[_Union[Assignment, _Mapping]]] = ...) -> None: ... + +class Record(_message.Message): + __slots__ = ("assignment", "desired_revision", "status", "received_at", "attempted_at", "applied_at", "verified_at", "removed_at", "error", "installed_route", "installed_boot_id", "expired_latched") + ASSIGNMENT_FIELD_NUMBER: _ClassVar[int] + DESIRED_REVISION_FIELD_NUMBER: _ClassVar[int] + STATUS_FIELD_NUMBER: _ClassVar[int] + RECEIVED_AT_FIELD_NUMBER: _ClassVar[int] + ATTEMPTED_AT_FIELD_NUMBER: _ClassVar[int] + APPLIED_AT_FIELD_NUMBER: _ClassVar[int] + VERIFIED_AT_FIELD_NUMBER: _ClassVar[int] + REMOVED_AT_FIELD_NUMBER: _ClassVar[int] + ERROR_FIELD_NUMBER: _ClassVar[int] + INSTALLED_ROUTE_FIELD_NUMBER: _ClassVar[int] + INSTALLED_BOOT_ID_FIELD_NUMBER: _ClassVar[int] + EXPIRED_LATCHED_FIELD_NUMBER: _ClassVar[int] + assignment: Assignment + desired_revision: int + status: ApplyStatus + received_at: _timestamp_pb2.Timestamp + attempted_at: _timestamp_pb2.Timestamp + applied_at: _timestamp_pb2.Timestamp + verified_at: _timestamp_pb2.Timestamp + removed_at: _timestamp_pb2.Timestamp + error: str + installed_route: bytes + installed_boot_id: str + expired_latched: bool + def __init__(self, assignment: _Optional[_Union[Assignment, _Mapping]] = ..., desired_revision: _Optional[int] = ..., status: _Optional[_Union[ApplyStatus, str]] = ..., received_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., attempted_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., applied_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., verified_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., removed_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., error: _Optional[str] = ..., installed_route: _Optional[bytes] = ..., installed_boot_id: _Optional[str] = ..., expired_latched: _Optional[bool] = ...) -> None: ... + +class Journal(_message.Message): + __slots__ = ("agent_id", "location", "boot_id", "desired", "locally_suspended", "suspension_reason", "records", "updated_at", "collection_id") + AGENT_ID_FIELD_NUMBER: _ClassVar[int] + LOCATION_FIELD_NUMBER: _ClassVar[int] + BOOT_ID_FIELD_NUMBER: _ClassVar[int] + DESIRED_FIELD_NUMBER: _ClassVar[int] + LOCALLY_SUSPENDED_FIELD_NUMBER: _ClassVar[int] + SUSPENSION_REASON_FIELD_NUMBER: _ClassVar[int] + RECORDS_FIELD_NUMBER: _ClassVar[int] + UPDATED_AT_FIELD_NUMBER: _ClassVar[int] + COLLECTION_ID_FIELD_NUMBER: _ClassVar[int] + agent_id: str + location: str + boot_id: str + desired: Desired + locally_suspended: bool + suspension_reason: str + records: _containers.RepeatedCompositeFieldContainer[Record] + updated_at: _timestamp_pb2.Timestamp + collection_id: str + def __init__(self, agent_id: _Optional[str] = ..., location: _Optional[str] = ..., boot_id: _Optional[str] = ..., desired: _Optional[_Union[Desired, _Mapping]] = ..., locally_suspended: _Optional[bool] = ..., suspension_reason: _Optional[str] = ..., records: _Optional[_Iterable[_Union[Record, _Mapping]]] = ..., updated_at: _Optional[_Union[datetime.datetime, _timestamp_pb2.Timestamp, _Mapping]] = ..., collection_id: _Optional[str] = ...) -> None: ... diff --git a/gen/python/xtcp_treatment_journal/v1/journal_pb2_grpc.py b/gen/python/xtcp_treatment_journal/v1/journal_pb2_grpc.py new file mode 100644 index 000000000..2daafffeb --- /dev/null +++ b/gen/python/xtcp_treatment_journal/v1/journal_pb2_grpc.py @@ -0,0 +1,4 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + diff --git a/go.mod b/go.mod index 19f41c117..bedc7a521 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,11 @@ go 1.27.3 require ( buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.2 buf.build/go/protovalidate v1.4.0 + github.com/cilium/ebpf v0.22.0 github.com/gaissmai/bart v0.30.0 github.com/grafana/pyroscope-go v1.4.3 github.com/grpc-ecosystem/grpc-gateway/v2 v2.33.0 + github.com/jackc/pgx/v5 v5.11.0 github.com/klauspost/compress v1.20.3 github.com/minio/minio-go/v7 v7.4.1 github.com/nats-io/nats.go v1.55.0 @@ -46,7 +48,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cilium/ebpf v0.22.0 // indirect github.com/dustin/go-humanize v1.1.0 // indirect github.com/felixge/fgprof v0.9.5 // indirect github.com/go-logr/logr v1.4.4 // indirect @@ -55,6 +56,9 @@ require ( github.com/google/pprof v0.0.0-20261105003125-4bf881d7fb0b // indirect github.com/google/uuid v1.6.0 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.12 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/klauspost/cpuid/v2 v2.4.2 // indirect github.com/klauspost/crc32 v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect @@ -85,6 +89,7 @@ require ( golang.org/x/crypto v0.58.0 // indirect golang.org/x/exp v0.0.0-20261106192419-47ce03d25ef0 // indirect golang.org/x/net v0.62.0 // indirect + golang.org/x/sync v0.24.0 // indirect golang.org/x/text v0.43.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20261104224025-d1e00e9f33ab // indirect gopkg.in/ini.v1 v1.67.3 // indirect diff --git a/go.sum b/go.sum index d69a5db82..205570d91 100644 --- a/go.sum +++ b/go.sum @@ -53,6 +53,8 @@ github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6 h1:teYtXy9B7y5lHTp8V9KPxpYRAVA7dozigQcMiBust1s= +github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= @@ -79,6 +81,14 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg= +github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/klauspost/compress v1.20.3 h1:zWNoFqq/lSuYQRim3dUXlXeA0IqwuZGicdG5ZTfY5j4= github.com/klauspost/compress v1.20.3/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= @@ -87,6 +97,10 @@ github.com/klauspost/cpuid/v2 v2.4.2 h1:xRw7IZEsAgVCp6trS/DgWbTAqpixhmywgVgBjYGg github.com/klauspost/cpuid/v2 v2.4.2/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM= github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= @@ -141,6 +155,8 @@ github.com/redis/go-redis/v9 v9.23.0 h1:/TTVdJa8BRNsybwwGGnmiYktHNlUXtbOQxlWpHBP github.com/redis/go-redis/v9 v9.23.0/go.mod h1:EWP2UUk+XDaI1s5nQB5mablZN6vccXlmBQTyfnF87D0= github.com/rodaine/protogofakeit v0.1.1 h1:ZKouljuRM3A+TArppfBqnH8tGZHOwM/pjvtXe9DaXH8= github.com/rodaine/protogofakeit v0.1.1/go.mod h1:pXn/AstBYMaSfc1/RqH3N82pBuxtWgejz1AlYpY1mI0= +github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= +github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -149,6 +165,8 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -217,6 +235,8 @@ golang.org/x/exp v0.0.0-20261106192419-47ce03d25ef0 h1:1GO4fJiyGakz0Liu2Ve1qPAwQ golang.org/x/exp v0.0.0-20261106192419-47ce03d25ef0/go.mod h1:J3U+E8RzytcGvwz+uJuAP4zULJ2TkAQBnmPZMexpdXs= golang.org/x/net v0.62.0 h1:18ELalfM5+XNRwzM2nYqXsZQ9ByS1uhj2O/U7+5jqRY= golang.org/x/net v0.62.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= +golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA= +golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/goip/actuate/actuate.go b/internal/goip/actuate/actuate.go new file mode 100644 index 000000000..be18d3b86 --- /dev/null +++ b/internal/goip/actuate/actuate.go @@ -0,0 +1,125 @@ +// Package actuate is the treatment route actuator: the one consumer of goip +// that applies a request to a live kernel. It owns a private routing table, +// a private rule priority and a private route protocol, installs host routes +// that copy the baseline path with TCP metrics changed, and refuses anything +// it does not own (docs/tcp-controller.md, "Supported routes and TCP +// semantics"). +// +// Requests are built with xtcpnl's typed RouteWrite and RuleWrite builders, +// never from argv: the CLI's keyword loop in internal/goip is for parity with +// `ip`, and a library that writes to a kernel should not depend on how an +// operator would have spelled the command. The parity between the two is +// internal/goip's TestRuleWriteTypedMatchesArgv. +// +// The import boundary is goip's: xtcpnl, x/sys/unix and the standard library. +// RPC and journal types stay in pkg/treatment; pkg/treatment/local adapts +// them to RouteTreatment. +package actuate + +import ( + "context" + "errors" + "net/netip" + "time" + + "github.com/randomizedcoder/xtcp2/internal/goip" + "github.com/randomizedcoder/xtcp2/internal/goip/service" + "golang.org/x/sys/unix" +) + +// RouteTreatment is the narrow typed input to the live route backend. Keeping +// RPC and journal types outside goip preserves its independent import +// boundary; pkg/treatment/local maps the domain treatment onto it. +type RouteTreatment struct { + Destination string + Settings *TCPRouteSettings +} + +type TCPRouteSettings struct { + CongestionControl *string + CongestionLock bool + RtoMinMs, InitialCongestionWindow, InitialReceiveWindow *uint32 + QuickAck, Ecn *bool +} + +func (s *TCPRouteSettings) GetCongestionControl() string { + if s == nil || s.CongestionControl == nil { + return "" + } + return *s.CongestionControl +} + +// Backend is the explicitly enabled, narrow live-write consumer of goip. +// The CLI and parity write paths stay generation-only; this is the one place +// a request reaches a kernel, through goip.NetlinkSource.ApplyRouteControl. +// Calls are serialized by the treatment journal; every operation owns its own +// bounded netlink socket and cannot interleave with telemetry collection. +type Backend struct { + Table uint32 + Priority uint32 + Protocol uint8 + Enabled bool + Protected []netip.Prefix + routeCache map[uint64][][]byte + ruleCache map[uint8]error +} + +// BeginReconcile caches one consistent read pass. Mutations invalidate their +// table before readback; the next reconciliation refreshes all forwarding and +// rule state. +func (b *Backend) BeginReconcile() { + b.routeCache = map[uint64][][]byte{} + b.ruleCache = map[uint8]error{} +} + +func (b *Backend) valid() error { + if !b.Enabled { + return errors.New("route actuator disabled") + } + return b.reserved() +} + +// reserved checks the private routing resources alone, so a rule can be +// built (and compared against the kernel's) before the opt-in is examined. +// Table 0 is "no table" on the wire and 1..255 collide with the well-known +// tables; priority 0 is the local rule and 32766+ the main and default +// rules; protocols below 192 are IANA-assigned. +func (b *Backend) reserved() error { + if b.Table < 256 || b.Priority == 0 || b.Priority >= 32766 || b.Protocol < 192 { + return errors.New("reserve a private table >=256, priority 1..32765 and protocol 192..255") + } + return nil +} + +func withSource(ctx context.Context, fn func(*goip.NetlinkSource, *service.Service) error) (err error) { + if err = ctx.Err(); err != nil { + return err + } + s, err := goip.OpenNetlinkTimeout(2 * time.Second) + if err != nil { + return err + } + defer func() { + if cerr := s.Close(); cerr != nil && err == nil { + err = cerr + } + }() + seq := uint32(0) + svc := service.New(s, func() uint32 { seq++; return seq }) + return fn(s, svc) +} + +func (b *Backend) Check(ctx context.Context) error { + if err := b.valid(); err != nil { + return err + } + b.BeginReconcile() + return withSource(ctx, func(_ *goip.NetlinkSource, svc *service.Service) error { + for _, f := range []uint8{unix.AF_INET, unix.AF_INET6} { + if err := b.checkRules(svc, f); err != nil { + return err + } + } + return nil + }) +} diff --git a/internal/goip/actuate/backend_test.go b/internal/goip/actuate/backend_test.go new file mode 100644 index 000000000..236eb2867 --- /dev/null +++ b/internal/goip/actuate/backend_test.go @@ -0,0 +1,79 @@ +package actuate + +import ( + "context" + "os" + "testing" + + "github.com/randomizedcoder/xtcp2/pkg/xtcpnl" + "golang.org/x/sys/unix" +) + +func ptr[T any](v T) *T { return &v } + +func TestTreatmentRoutePreservesPathAndMetrics(t *testing.T) { + b := &Backend{Table: 10002, Priority: 30000, Protocol: 242, Enabled: true} + r := xtcpnl.RouteInfo{Family: unix.AF_INET, Table: unix.RT_TABLE_MAIN, Type: unix.RTN_UNICAST, Oif: 4, Gateway: []byte{192, 0, 2, 254}, PrefSrc: []byte{192, 0, 2, 10}, Metrics: &xtcpnl.RouteMetrics{Present: 1 << unix.RTAX_MTU}} + r.Metrics.Values[unix.RTAX_MTU] = 1400 + treatment := &RouteTreatment{Destination: "198.51.100.10/32", Settings: &TCPRouteSettings{CongestionControl: ptr("cubic"), RtoMinMs: ptr(uint32(5)), QuickAck: ptr(true), InitialCongestionWindow: ptr(uint32(100)), InitialReceiveWindow: ptr(uint32(100))}} + raw, e := b.planRoute(treatment, r) + if e != nil { + t.Fatal(e) + } + got, e := xtcpnl.ParseNewRoute(raw) + if e != nil { + t.Fatal(e) + } + if got.Table != 10002 || got.Protocol != 242 || got.Oif != 4 || got.Metrics.Values[unix.RTAX_MTU] != 1400 || got.Metrics.Values[unix.RTAX_RTO_MIN] != 5 || got.Metrics.CcAlgo != "cubic" { + t.Fatalf("wrong route %+v", got) + } + for metric, want := range map[uint16]uint32{unix.RTAX_INITCWND: 100, unix.RTAX_INITRWND: 100, unix.RTAX_QUICKACK: 1} { + if !got.Metrics.Has(metric) || got.Metrics.Values[metric] != want { + t.Fatalf("metric %d: got %d, want %d", metric, got.Metrics.Values[metric], want) + } + } + if got.Metrics.Values[unix.RTAX_LOCK]&(1< best.DstLen || r.DstLen == best.DstLen && r.Priority < best.Priority: + best = &r + bestRaw = v + ambiguous = false + case r.DstLen == best.DstLen && r.Priority == best.Priority: + ambiguous = true + } + } + if best == nil || ambiguous { + return nil, nil, errors.New("no unique baseline route") + } + return best, bestRaw, nil +} + +// routeCovers reports whether the route's destination prefix contains ip. A +// zero-length destination is the family's default route. +func routeCovers(r *xtcpnl.RouteInfo, family uint8, ip netip.Addr) bool { + a, ok := netip.AddrFromSlice(r.Dst) + if r.DstLen == 0 { + a, ok = netip.IPv4Unspecified(), true + if family == unix.AF_INET6 { + a = netip.IPv6Unspecified() + } + } + return ok && netip.PrefixFrom(a, int(r.DstLen)).Contains(ip) +} + +// supportedAttrs fails when the baseline route carries attributes planRoute +// cannot reproduce. +func supportedAttrs(raw []byte) error { + unsupported := false + if e := xtcpnl.WalkRTAttrs(raw[12:], func(typ uint16, _ []byte) { + switch typ { + case unix.RTA_DST, unix.RTA_GATEWAY, unix.RTA_OIF, unix.RTA_PREFSRC, unix.RTA_PRIORITY, unix.RTA_PREF, unix.RTA_CACHEINFO, unix.RTA_TABLE, unix.RTA_METRICS: + default: + unsupported = true + } + }); e != nil { + return e + } + if unsupported { + return errors.New("baseline route has unsupported attributes") + } + return nil +} + +// planRoute deliberately rejects route forms whose forwarding semantics this +// actuator cannot preserve. It never invents a gateway or alters the main table. +func (b *Backend) planRoute(t *RouteTreatment, r xtcpnl.RouteInfo) ([]byte, error) { + if r.Type != unix.RTN_UNICAST || r.Oif == 0 || r.HasMultipath || r.HasVia || r.NhID != 0 || r.SrcLen != 0 || r.Tos != 0 || r.Flags != 0 || r.HasExpires || r.Metrics != nil && r.Metrics.Unknown != 0 { + return nil, errors.New("unsupported baseline route") + } + ip := netip.MustParsePrefix(t.Destination).Addr() + w := xtcpnl.RouteWrite{MsgType: unix.RTM_NEWROUTE, Flags: unix.NLM_F_ACK | unix.NLM_F_CREATE | unix.NLM_F_EXCL, Family: r.Family, DstLen: uint8(ip.BitLen()), Protocol: b.Protocol, Scope: r.Scope, Type: unix.RTN_UNICAST} + w.Attrs = []xtcpnl.RouteAttr{xtcpnl.RouteAttrBytes(unix.RTA_DST, ip.AsSlice()), xtcpnl.RouteAttrU32(unix.RTA_TABLE, b.Table), xtcpnl.RouteAttrU32(unix.RTA_OIF, r.Oif)} + if len(r.Gateway) > 0 { + w.Attrs = append(w.Attrs, xtcpnl.RouteAttrBytes(unix.RTA_GATEWAY, r.Gateway)) + } + if len(r.PrefSrc) > 0 { + w.Attrs = append(w.Attrs, xtcpnl.RouteAttrBytes(unix.RTA_PREFSRC, r.PrefSrc)) + } + if r.HasPriority { + w.Attrs = append(w.Attrs, xtcpnl.RouteAttrU32(unix.RTA_PRIORITY, r.Priority)) + } + if r.HasPref { + w.Attrs = append(w.Attrs, xtcpnl.RouteAttrBytes(unix.RTA_PREF, []byte{r.Pref})) + } + m := xtcpnl.RouteMetrics{} + if r.Metrics != nil { + m = *r.Metrics + } + set := func(k uint16, v uint32) { m.Present |= 1 << k; m.Values[k] = v } + s := t.Settings + if s.CongestionControl != nil { + m.CcAlgo = *s.CongestionControl + m.Present |= 1 << unix.RTAX_CC_ALGO + lock := m.Values[unix.RTAX_LOCK] &^ (1 << unix.RTAX_CC_ALGO) + if s.CongestionLock { + lock |= 1 << unix.RTAX_CC_ALGO + } + set(unix.RTAX_LOCK, lock) + } + if s.RtoMinMs != nil { + set(unix.RTAX_RTO_MIN, *s.RtoMinMs) + set(unix.RTAX_LOCK, m.Values[unix.RTAX_LOCK]|1< 1 { + return errors.New("missing/duplicate baseline routing rules") + } + if b.ruleCache != nil { + b.ruleCache[family] = nil + } + return nil +} + +func (b *Backend) rules(ctx context.Context, enable bool) error { + if err := b.valid(); err != nil { + return err + } + return withSource(ctx, func(s *goip.NetlinkSource, svc *service.Service) error { + for _, f := range []uint8{unix.AF_INET, unix.AF_INET6} { + if enable { + if err := b.checkRules(svc, f); err != nil { + return err + } + } + rs, err := svc.Rules(f) + if err != nil { + return err + } + owned := 0 + for i := range rs { + r := xtcpnl.RuleInfo(rs[i]) + if b.ownRule(r) { + owned++ + } else if enable && (r.Priority == b.Priority || r.Table == b.Table) { + return errors.New("reserved routing rule collision") + } + } + if enable { + routes, e := b.routeBodies(svc, f, b.Table) + if e != nil { + return e + } + for _, raw := range routes { + r, e := xtcpnl.ParseNewRoute(raw) + if e != nil { + return e + } + if r.Protocol != b.Protocol { + return errors.New("foreign route in reserved treatment table") + } + } + } + if enable && owned == 0 || !enable && owned > 0 { + msg, err := b.rule(f, !enable) + if err != nil { + return err + } + for range max(1, owned) { + if err = s.ApplyRouteControl(msg); err != nil { + return err + } + } + } + rs, err = svc.Rules(f) + if err != nil { + return err + } + owned = 0 + for i := range rs { + if b.ownRule(xtcpnl.RuleInfo(rs[i])) { + owned++ + } + } + if enable && owned != 1 || !enable && owned != 0 { + return errors.New("rule readback mismatch") + } + } + return nil + }) +} + +func (b *Backend) Enable(ctx context.Context) error { return b.rules(ctx, true) } + +func (b *Backend) Disable(ctx context.Context) error { return b.rules(ctx, false) } diff --git a/internal/goip/imports_test.go b/internal/goip/imports_test.go index 705a071ed..f0603f637 100644 --- a/internal/goip/imports_test.go +++ b/internal/goip/imports_test.go @@ -22,6 +22,7 @@ const ( var goipPackages = []string{ modulePath + "/cmd/goip", modulePath + "/internal/goip", + modulePath + "/internal/goip/actuate", modulePath + "/internal/goip/model", modulePath + "/internal/goip/render", modulePath + "/internal/goip/req", @@ -166,6 +167,7 @@ func TestGoipImportSetIsHermetic(t *testing.T) { modulePath + "/internal/goip/req": "the pure request builders", modulePath + "/internal/goip/service": "shared request, decode, filter and ordering application layer", modulePath + "/internal/goip/goiphttp": "the read-only /ip HTTP paths over goip.Show", + modulePath + "/internal/goip/actuate": "the treatment route actuator, the one live-write consumer, on xtcpnl's typed builders", modulePath + "/pkg/xtcpnl": "the subject under test", modulePath + "/pkg/nlparity": "the tolerant walker, for ReplaySource", modulePath + "/pkg/cint": "the C int conversions; stdlib only", diff --git a/internal/goip/route_control.go b/internal/goip/route_control.go new file mode 100644 index 000000000..cc017f1c0 --- /dev/null +++ b/internal/goip/route_control.go @@ -0,0 +1,38 @@ +package goip + +import ( + "encoding/binary" + "errors" + + "github.com/randomizedcoder/xtcp2/pkg/xtcpnl" + "golang.org/x/sys/unix" +) + +// This file is the one path from goip to a live kernel. Every other write +// verb serializes to GOIP_WRITE_OUT (docs/netlink/link-write-path.md, +// decision 5); the treatment actuator in internal/goip/actuate reaches the +// socket only through ApplyRouteControl, which stays here because it needs +// the socket's own descriptor and address. + +// ApplyRouteControl is deliberately separate from the read and CLI byte-output +// paths. Only acknowledged route/rule mutations are admitted here. +func (s *NetlinkSource) ApplyRouteControl(request []byte) error { + if len(request) < 28 { + return errors.New("short route-control request") + } + typ := binary.LittleEndian.Uint16(request[4:6]) + if typ != unix.RTM_NEWROUTE && typ != unix.RTM_DELROUTE && typ != unix.RTM_NEWRULE && typ != unix.RTM_DELRULE { + return errors.New("not a route-control mutation") + } + if binary.LittleEndian.Uint16(request[6:8])&unix.NLM_F_ACK == 0 { + return errors.New("mutation requires acknowledgement") + } + got, _, err := xtcpnl.TalkRtnetlink(s.fd, request, s.sa) + if err != nil { + return err + } + if got != 0 { + return errors.New("unexpected non-ACK mutation response") + } + return nil +} diff --git a/internal/goip/rule_write_typed_test.go b/internal/goip/rule_write_typed_test.go new file mode 100644 index 000000000..18ba0ef41 --- /dev/null +++ b/internal/goip/rule_write_typed_test.go @@ -0,0 +1,97 @@ +package goip + +import ( + "bytes" + "strings" + "testing" + + "github.com/randomizedcoder/xtcp2/pkg/xtcpnl" + "golang.org/x/sys/unix" +) + +// TestRuleWriteTypedMatchesArgv is the claim xtcpnl_rule_write.go makes and +// cannot test alone: a RuleWrite and iprule_modify's argv loop produce the +// same bytes for the same rule. Both encoders are visible here. The argv is +// spelled with `table` first because the typed builder writes FRA_TABLE +// first; the kernel reads the attributes as a set, so internal/goip/actuate +// and `ip rule` agree on the request even though the CLI would let an +// operator type the keywords in another order. +// +// go test ./internal/goip -run TestRuleWriteTypedMatchesArgv +func TestRuleWriteTypedMatchesArgv(t *testing.T) { + const addAck = uint16(unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK) + treatmentAttrs := []xtcpnl.RuleAttr{ + xtcpnl.RuleAttrU32(unix.FRA_PRIORITY, 30000), xtcpnl.RuleAttrU8(unix.FRA_IP_PROTO, unix.IPPROTO_TCP), + xtcpnl.RuleAttrName(unix.FRA_IIFNAME, "lo"), xtcpnl.RuleAttrU8(unix.FRA_PROTOCOL, 242), + } + tests := []struct { + description string + family uint8 + typed xtcpnl.RuleWrite + argv string + }{ + { + description: "positive: the IPv4 treatment rule add is byte for byte `ip rule add table 10002 priority 30000 ipproto tcp iif lo protocol 242`", + family: unix.AF_INET, + typed: xtcpnl.RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, Table: 10002, Attrs: treatmentAttrs}, + argv: "table 10002 priority 30000 ipproto tcp iif lo protocol 242", + }, + { + description: "positive: the IPv6 treatment rule is the same request under `ip -6`", + family: unix.AF_INET6, + typed: xtcpnl.RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET6, Action: unix.FR_ACT_TO_TBL, Table: 10002, Attrs: treatmentAttrs}, + argv: "table 10002 priority 30000 ipproto tcp iif lo protocol 242", + }, + { + description: "positive: the delete keeps every selector and drops the action and the create flags", + family: unix.AF_INET, + typed: xtcpnl.RuleWrite{MsgType: unix.RTM_DELRULE, Flags: unix.NLM_F_ACK, Family: unix.AF_INET, Action: unix.FR_ACT_UNSPEC, Table: 10002, Attrs: treatmentAttrs}, + argv: "table 10002 priority 30000 ipproto tcp iif lo protocol 242", + }, + { + description: "boundary: table 255 stays in the header byte on both paths", + family: unix.AF_INET, + typed: xtcpnl.RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, Table: 255, Attrs: treatmentAttrs[:1]}, + argv: "table 255 priority 30000", + }, + { + description: "boundary: a /32 destination is FRA_DST with the full length, as `to 192.0.2.1/32`", + family: unix.AF_INET, + typed: xtcpnl.RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, DstLen: 32, Action: unix.FR_ACT_TO_TBL, Table: 10002, + Attrs: []xtcpnl.RuleAttr{xtcpnl.RuleAttrBytes(unix.FRA_DST, []byte{192, 0, 2, 1})}}, + argv: "table 10002 to 192.0.2.1/32", + }, + { + description: "boundary: a /128 destination is sixteen bytes of FRA_DST, as `to 2001:db8::1/128`", + family: unix.AF_INET6, + typed: xtcpnl.RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET6, DstLen: 128, Action: unix.FR_ACT_TO_TBL, Table: 10002, + Attrs: []xtcpnl.RuleAttr{xtcpnl.RuleAttrBytes(unix.FRA_DST, []byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})}}, + argv: "table 10002 to 2001:db8::1/128", + }, + { + description: "corner: `not` is the header flag on both paths", + family: unix.AF_INET, + typed: xtcpnl.RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, FrhFlags: unix.FIB_RULE_INVERT, Table: 10002, Attrs: treatmentAttrs[:1]}, + argv: "not table 10002 priority 30000", + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + want, err := parseRuleWriteArgs(tc.family, tc.typed.MsgType, strings.Fields(tc.argv)) + if err != nil { + t.Fatalf("%s: argv: %v", tc.description, err) + } + expected, err := xtcpnl.BuildWriteRequest(tc.typed.MsgType, tc.typed.Flags, 1, want.frh(), want.attrs.Bytes()) + if err != nil { + t.Fatalf("%s: argv build: %v", tc.description, err) + } + got, err := xtcpnl.BuildRuleWriteRequest(tc.typed, 1) + if err != nil { + t.Fatalf("%s: typed: %v", tc.description, err) + } + if !bytes.Equal(got, expected) { + t.Fatalf("%s:\n typed %x\n argv %x", tc.description, got, expected) + } + }) + } +} diff --git a/nix/README.md b/nix/README.md index b7d9cc31f..64bd11629 100644 --- a/nix/README.md +++ b/nix/README.md @@ -218,7 +218,7 @@ Use the full path: `nix build path:.#checks.x86_64-linux.NAME -L`. | `vm-linkmonitor-performance-bundle` | Performance evidence-bundle validation | | `test-go-race`, `test-go-flavor-*`, `test-linkmonitor` | Behavioral suites registered alongside static checks | | `test-ipmeta-bootstrap-artifact`, `test-oci-ipmeta-bootstrap-contents`, `test-ipmeta-bootstrap-snapshot`, `test-oci-ipmeta-bootstrap-snapshot-contents` | Fixture and real-snapshot bootstrap checks, also available as packages above | -| `microvm-lifecycle-x86_64`, `vm-*`, `vm-all` | Actual guest checks described next; `vm-*` here refers to the nine guest checks, not the host helpers above | +| `microvm-lifecycle-x86_64`, `vm-*`, `vm-all` | Actual guest checks described next; `vm-*` here refers to guest checks, not the host helpers above | ## Nix integration testing @@ -241,9 +241,9 @@ are failures/unverified runs, not passing skips. | Entry point | Runs | Does not cover | |---|---|---| -| `checks.x86_64-linux.vm-all` | Seven registered monitor/goip guest checks; cached | Daemon lifecycle flavor sweep, captures, long soaks | +| `checks.x86_64-linux.vm-all` | Registered monitor/goip/controller guest checks; cached | Daemon lifecycle flavor sweep, captures, long soaks | | `checks.x86_64-linux.microvm-lifecycle-x86_64` | Base daemon lifecycle guest; cached | Other lifecycle flavors | -| `integration-all` app | Sequential lifecycle flavor sweep plus goip parity; fresh | Monitor `vm-all`, interface-naming/ipmeta-bootstrap lifecycle cases, capture jobs, discovery/rate benchmarks | +| `integration-all` app | Sequential lifecycle flavor sweep, TCP controller and goip parity; fresh | Monitor `vm-all`, interface-naming/ipmeta-bootstrap lifecycle cases, capture jobs, discovery/rate benchmarks | | `integration-all -- --soak --duration 1h` | The sweep plus each configured soak for the given duration | Other investigation variants and physical-hardware validation | | `nix flake check` | All registered checks, including the cached guest groups above | Unregistered lifecycle runners, capture apps, fresh performance/soak measurements | @@ -301,6 +301,8 @@ Each pair below offers a fresh runnable package and a cached check. See | `test-xtcp2-linkmonitor-vm` | `vm-xtcp2-linkmonitor` | Real xtcp2 NixOS service, baseline persistence/reload, missing-link and degradation behavior | | `test-xtcp2-scrape-auth-vm` | `vm-xtcp2-scrape-auth` | vmagent read-token scraping, 401/403 authorization, healthcheck, and token rotation | | `test-xtcp2-ip-listen-vm` | `vm-xtcp2-ip-listen` | Separate unauthenticated loopback inspection listener, route separation, and rejection of a non-loopback peer through `route_localnet` | +| `test-tcp-controller-vm` | `vm-tcp-controller` | Go-driven seven-guest TCP/netem test: ClickHouse evidence, reviewed canaries, holds, persistence, harmful-treatment rollback and watchdog expiry | +| `test-tcp-controller-soak-vm` | `vm-tcp-controller-soak` (opt-in, outside `vm-all`) | Repeated RTT changes, scheduled discovery, test-operator approval, automatic rollback and cooldown; defaults to ~30m, configurable with `--cycles=2..6 --interval=3m\|4m\|5m` | `demo-linkmonitor-ionic-profiles` is a separate interactive/emulator scenario runner: `nix run path:.#demo-linkmonitor-ionic-profiles -- --out=/tmp/ionic-demo`. diff --git a/nix/binaries.nix b/nix/binaries.nix index 871a3d2ab..e43dc9cc9 100644 --- a/nix/binaries.nix +++ b/nix/binaries.nix @@ -89,6 +89,13 @@ let "nsTest" "register_schema" "xtcp2" + "xtcp2-controller" + "xtcp2-controllerctl" + # The standalone treatment agent pairs with slim xtcp2 flavors, which do + # not embed it (mkGoBinary's `treatment` knob); the watchdog is separate + # in both arrangements. See docs/tcp-controller.md, "Agent deployment". + "xtcp2-treatment-agent" + "xtcp2-treatmentctl" "xtcp2client" "xtcp2ctl" "xtcp2_kafka_client" diff --git a/nix/checks/cli-help-smoke.nix b/nix/checks/cli-help-smoke.nix index acf8864dc..55cae5d52 100644 --- a/nix/checks/cli-help-smoke.nix +++ b/nix/checks/cli-help-smoke.nix @@ -35,9 +35,14 @@ let # A tools/ binary, exported beside the cmd ones (nix/binaries.nix). "rtnlmon-probe" "xtcp2" + "xtcp2-controller" + "xtcp2-controllerctl" + "xtcp2-treatment-agent" + "xtcp2-treatmentctl" "xtcp2client" "xtcp2ctl" "xtcp2_kafka_client" + "zstd-probe" ]; mkSmoke = diff --git a/nix/default.nix b/nix/default.nix index 514978506..e5be398ad 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -184,6 +184,15 @@ let }; in { + tcp-controller = import ./tests/tcp-controller { + inherit + pkgs + lib + binaries + nixpkgs + ; + inherit (goSource) vendoredSource; + }; goip-argv-paths = import ./tests/goip-argv-paths.nix { inherit pkgs lib nixpkgs; monitor = linkmonitorPackages.go-link-monitor; @@ -220,6 +229,17 @@ let }; }; vmChecks = lib.mapAttrs' (name: t: lib.nameValuePair "vm-${name}" t.vmCheck.check) vmTests; + # Longer repeated discovery/rollback run; opt in separately from vm-all. + tcpControllerSoak = import ./tests/tcp-controller { + inherit + pkgs + lib + binaries + nixpkgs + ; + inherit (goSource) vendoredSource; + soak = true; + }; # Dev shell devshell = import ./devshell.nix { inherit pkgs; }; @@ -345,7 +365,8 @@ let "$FLAKE_REF#test-focused-asn-locality" \ "$FLAKE_REF#test-focused-goip" \ "$FLAKE_REF#test-focused-gordma" \ - "$FLAKE_REF#test-focused-xtcp-enrich" + "$FLAKE_REF#test-focused-xtcp-enrich" \ + "$FLAKE_REF#test-focused-xtcp-treatment" echo "==> focused quality checks passed" ''; @@ -833,18 +854,14 @@ let drv = microvms.s3ParquetLowfreq.x86_64.runner; } ]; - # Neither a lifecycle flavor nor a soak: it runs to completion in minutes - # like the first list, but it self-terminates on a parity verdict rather - # than on XTCP2_SELF_TEST_OVERALL, and there is no xtcp2 daemon in the - # guest to emit that sentinel. Its own list, so the lifecycle sweep's - # description stays true of every member of it. - # - # It belongs in `integration-all` for the same reason everything else - # here does: SERIAL_PORT is fixed per arch, so it cannot run concurrently - # with any other VM, and this is the one command that runs them one at a - # time. Same 0/1/2 = PASS/FAIL/TIMEOUT contract, so run_job needs no - # special case. + # Finite runners with their own verdicts, separate from lifecycle and + # duration-based soak runners. Keep the aggregate sequential to bound + # resource use and avoid the older guests' fixed serial-port conflicts. verdictFlavors = [ + { + label = "tcp-controller"; + drv = vmTests.tcp-controller; + } { label = "goip-parity"; drv = microvms.goipParity.x86_64.runner; @@ -875,13 +892,16 @@ let " default the 17 lifecycle flavors; each self-terminates on its" \ " XTCP2_SELF_TEST_OVERALL sentinel (minutes each; the" \ " clickhouse-http one can take up to ~20m), then the" \ - " verdict runners: goip-parity, which captures an" \ + " verdict runners: tcp-controller (seven guests," \ + " measured canaries and netem rollback), then" \ + " goip-parity, which captures an" \ " ip/goip/ip triple per command and compares them in" \ " the guest (~5m)." \ " --soak additionally run the 7 duration-bounded runners:" \ " soak, tcp-stress, clickhouse-pipeline-stress," \ " s3parquet-long, s3parquet-stress," \ " s3parquet-stress-iouring, s3parquet-lowfreq." \ + " Also runs tcp-controller-soak (~30m, fixed cycles)." \ " --duration per-soak duration (default 1h). Ignored without --soak." \ "" \ " Prints a PASS/FAIL/TIMEOUT summary; exits non-zero if any flavor failed." \ @@ -942,6 +962,7 @@ let [ -z "$label" ] && continue run_job "$label" "$bin" --duration "$DURATION" done < <(printf '%s\n' "$SOAK_JOBS") + run_job "tcp-controller-soak" "${lib.getExe tcpControllerSoak}" fi echo "" @@ -1008,6 +1029,8 @@ in # IA4-T01 of cmd/go-link-monitor/IP-ARGV-PATHS-IMPLEMENTATION-PLAN.md: # `nix run .#test-goip-argv-paths-vm`, which needs /dev/kvm or TCG. test-goip-argv-paths-vm = vmTests.goip-argv-paths; + test-tcp-controller-vm = vmTests.tcp-controller; + test-tcp-controller-soak-vm = tcpControllerSoak; test-linkmonitor-embedding-vm = vmTests.linkmonitor-embedding; test-linkmonitor-performance-vm = linkmonitorPerformanceVm; test-linkmonitor-rdma-vm = vmTests.linkmonitor-rdma; @@ -1101,6 +1124,10 @@ in # `nix build .#test-go-unit`, etc. test-go-unit = tests.go-unit; test-go-bench = tests.go-bench; + test-tcp-controller-unit = tests.tcp-controller-quality.unit; + test-tcp-controller-race = tests.tcp-controller-quality.race; + bench-tcp-controller = tests.tcp-controller-quality.bench; + bench-tcp-controller-postgres-indexes = tests.tcp-controller-quality.postgres-indexes; test-go-race = tests.go-race; test-listener-security = tests.listener-security; test-proto-deserialize-golden = tests.proto-deserialize-golden; @@ -1113,6 +1140,7 @@ in test-focused-goip = tests.focused.focused-goip; test-focused-gordma = tests.focused.focused-gordma; test-focused-xtcp-enrich = tests.focused.focused-xtcp-enrich; + test-focused-xtcp-treatment = tests.focused.focused-xtcp-treatment; test-microvm-lifecycle-x86_64 = tests.microvm-lifecycle.x86_64.fullTest; test-microvm-lifecycle-x86_64-ipmeta-bootstrap = tests.microvm-lifecycle-ipmeta-bootstrap.x86_64.fullTest; @@ -1173,6 +1201,9 @@ in # sandbox (extra-sandbox-paths); without it, it fails with # VM_CHECK_NO_TUN. See linkmonitor-ionic.nix. vm-all = pkgs.linkFarm "vm-all" (lib.mapAttrsToList (name: path: { inherit name path; }) vmChecks); + vm-tcp-controller-soak = tcpControllerSoak.vmCheck.check; + tcp-controller-unit = tests.tcp-controller-quality.unit; + tcp-controller-race = tests.tcp-controller-quality.race; # Race-detector + per-flavor builds. These run as part of # `nix flake check` so a flavor-tag regression (e.g. dest_kafka @@ -1203,6 +1234,14 @@ in // (lib.filterAttrs (n: _v: lib.hasPrefix "test-go-flavor-" n) tests); apps = { + test-tcp-controller-vm = { + type = "app"; + program = "${vmTests.tcp-controller}/bin/test-tcp-controller-vm"; + }; + test-tcp-controller-soak-vm = { + type = "app"; + program = "${tcpControllerSoak}/bin/test-tcp-controller-soak-vm"; + }; regen-protos = { type = "app"; program = "${protos.regenerate}/bin/regen-protos"; diff --git a/nix/lib/mkGoBinary.nix b/nix/lib/mkGoBinary.nix index d1d989ca2..f2ea1f488 100644 --- a/nix/lib/mkGoBinary.nix +++ b/nix/lib/mkGoBinary.nix @@ -14,6 +14,10 @@ # destinationFlavors); null = all, [] = stdlib only # enrichments — enrichment features to compile in (see versions.nix # enrichmentFlavors); null = all, [] = none +# treatment — compile the TCP route treatment agent into cmd/xtcp2 +# (`-tags treatment`, see docs/tcp-controller.md); null = +# only for the full destination set, i.e. the fat builds. +# Slim flavors read a standalone agent's journal instead. # commit, date, # version — injected into main.{commit,date,version} via -ldflags -X # extraLdflags — additional -ldflags entries appended after the variant's @@ -52,6 +56,13 @@ in # A list like `[ "asn" ]` → just those. See versions.nix enrichmentFlavors # for why these two are compile-time gated when the other enrichers are not. enrichments ? null, + # Whether cmd/xtcp2 embeds the treatment agent (build tag `treatment`). + # `null` → follow the destination axis: the fat builds (destinations == + # null) embed it, the slim per-destination flavors do not and pair with + # the standalone xtcp2-treatment-agent + -treatmentAttribution. A build + # without the tag refuses -treatmentConfig at startup, like a slim build + # refuses an enricher it lacks. + treatment ? null, vendorHash ? versions.goVendorHash, commit ? "nix", date ? "1970-01-01-00:00", @@ -111,6 +122,11 @@ let enrichmentTags = map (f: "enrich_${f}") effectiveEnrichments; + # The treatment agent rides the destination axis unless told otherwise: + # embedded in the fat builds, left to the standalone binary in slim ones. + embedTreatment = if treatment == null then destinations == null else treatment; + treatmentTags = lib.optional embedTreatment "treatment"; + # Unlike destSuffix there is no "-min" equivalent: the empty enrichment set # is the plain name, so `xtcp2-min` / `xtcp2-s3parquet` keep the names they # have always had while gaining `-asn` / `-locality` / `-asn-locality` @@ -138,7 +154,7 @@ buildGoModule { CGO_ENABLED = if versions.cgoEnabled then "1" else "0"; }; - tags = versions.buildTags ++ destinationTags ++ enrichmentTags ++ extraTags; + tags = versions.buildTags ++ destinationTags ++ enrichmentTags ++ treatmentTags ++ extraTags; ldflags = variantCfg.extraLdflags diff --git a/nix/modules/xtcp2-service.nix b/nix/modules/xtcp2-service.nix index 55e49a692..6d8d27322 100644 --- a/nix/modules/xtcp2-service.nix +++ b/nix/modules/xtcp2-service.nix @@ -99,6 +99,48 @@ in ''; }; + treatments = { + enable = lib.mkEnableOption "reviewed TCP route treatments and the independent expiry watchdog"; + mode = lib.mkOption { + type = lib.types.enum [ + "embedded" + "standalone" + ]; + default = "embedded"; + description = '' + How the treatment agent runs. `embedded` passes `-treatmentConfig` + to xtcp2, which must be a build with the `treatment` tag (the fat + `xtcp2` attribute; slim flavors refuse the flag at startup). + `standalone` runs `xtcp2-treatment-agent` as its own service from + `agentPackage` and passes `-treatmentAttribution=` + to xtcp2, which then only reads the journal to stamp provenance. The + watchdog service is independent in both modes. + ''; + }; + configFile = lib.mkOption { + type = lib.types.str; + default = "/etc/xtcp2/controller-agent.json"; + description = "Runtime agent JSON file; keep private keys outside the Nix store."; + }; + journalDirectory = lib.mkOption { + type = lib.types.str; + default = "/var/lib/xtcp2/routes"; + description = '' + The agent's journal directory (`directory` in configFile). In + standalone mode xtcp2 reads `state.textproto` from here. + ''; + }; + agentPackage = lib.mkOption { + type = lib.types.nullOr lib.types.package; + default = null; + description = "Package providing bin/xtcp2-treatment-agent, required in standalone mode."; + }; + watchdogPackage = lib.mkOption { + type = lib.types.package; + description = "Package providing bin/xtcp2-treatmentctl, required when treatments are enabled."; + }; + }; + listeners = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; @@ -233,6 +275,12 @@ in assertion = lm.ipListen == null || lm.ipPaths; message = "services.xtcp2.linkMonitor.ipListen needs linkMonitor.ipPaths"; } + { + assertion = + !(cfg.treatments.enable && cfg.treatments.mode == "standalone") + || cfg.treatments.agentPackage != null; + message = "services.xtcp2.treatments.mode = \"standalone\" needs services.xtcp2.treatments.agentPackage"; + } ]; systemd.services.xtcp2 = { @@ -260,7 +308,16 @@ in # surface for forward-compatibility — when the daemon learns to # parse a JSON config, flip this back to `-config ${cfg.configFile}`. ExecStartPre = lib.mkIf (cfg.listenerTokenFile == null) [ "${generateToken}" ]; - ExecStart = xtcp2Exec.mkExecStart cfg.package (linkMonitorArgs ++ cfg.extraArgs); + ExecStart = xtcp2Exec.mkExecStart cfg.package ( + linkMonitorArgs + ++ lib.optionals (cfg.treatments.enable && cfg.treatments.mode == "embedded") [ + "-treatmentConfig=${cfg.treatments.configFile}" + ] + ++ lib.optionals (cfg.treatments.enable && cfg.treatments.mode == "standalone") [ + "-treatmentAttribution=${cfg.treatments.journalDirectory}" + ] + ++ cfg.extraArgs + ); # `systemctl reload xtcp2` asks the link monitor to relearn the # expected up-link count, as SIGUSR1 does for go-link-monitor. ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID"; @@ -292,5 +349,70 @@ in LimitNPROC = 8192; }; }; + + # Standalone agent: owns the journal and the kernel routes; xtcp2 only + # reads the journal. Restarting one does not restart the other, and the + # journal replay on agent start restores stable routes without a + # controller round trip. + systemd.services.xtcp2-treatment-agent = + lib.mkIf (cfg.treatments.enable && cfg.treatments.mode == "standalone") + { + description = "xtcp2 route treatment agent"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + serviceConfig = { + Type = "simple"; + User = cfg.user; + StateDirectory = "xtcp2"; + StateDirectoryMode = "0750"; + ExecStart = xtcp2Exec.escapeSystemdExecArgs [ + "${cfg.treatments.agentPackage}/bin/xtcp2-treatment-agent" + "-config=${cfg.treatments.configFile}" + ]; + # `systemctl reload` checks in and reconciles now, as SIGHUP does for + # the embedded agent. + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + Restart = "always"; + RestartSec = "2s"; + AmbientCapabilities = [ + "CAP_NET_ADMIN" + "CAP_SYS_PTRACE" + ]; + CapabilityBoundingSet = [ + "CAP_NET_ADMIN" + "CAP_SYS_PTRACE" + ]; + }; + }; + + # Deliberately independent of xtcp2.service: daemon crashes must not leave + # trial routes installed past their local lease deadline. + systemd.services.xtcp2-treatment-watchdog = lib.mkIf cfg.treatments.enable { + description = "xtcp2 route treatment lease watchdog"; + wantedBy = [ "multi-user.target" ]; + after = [ "local-fs.target" ]; + serviceConfig = { + Type = "simple"; + User = cfg.user; + StateDirectory = "xtcp2"; + StateDirectoryMode = "0750"; + ExecStart = xtcp2Exec.escapeSystemdExecArgs [ + "${cfg.treatments.watchdogPackage}/bin/xtcp2-treatmentctl" + "-mode=watchdog" + "-config=${cfg.treatments.configFile}" + ]; + Restart = "always"; + RestartSec = "2s"; + AmbientCapabilities = [ + "CAP_NET_ADMIN" + "CAP_SYS_PTRACE" + ]; + CapabilityBoundingSet = [ + "CAP_NET_ADMIN" + "CAP_SYS_PTRACE" + ]; + }; + }; }; } diff --git a/nix/tests/default.nix b/nix/tests/default.nix index 502297bed..05c25ccff 100644 --- a/nix/tests/default.nix +++ b/nix/tests/default.nix @@ -36,6 +36,7 @@ in { go-unit = import ./go-unit.nix { inherit pkgs vendoredSource; }; go-bench = import ./go-bench.nix { inherit pkgs vendoredSource; }; + tcp-controller-quality = import ./tcp-controller/quality.nix { inherit pkgs vendoredSource; }; # No lib: that runner has no such argument any more. This file's own lib arg # stays — focused-quality.nix, both go-test-* imports and the mapAttrs' below # all need it. diff --git a/nix/tests/focused-quality.nix b/nix/tests/focused-quality.nix index 9405a5d6e..8d8459e3a 100644 --- a/nix/tests/focused-quality.nix +++ b/nix/tests/focused-quality.nix @@ -83,4 +83,17 @@ in "./cmd/xtcp2" ]; }; + + # cmd/xtcp2 with the embedded treatment agent (`-tags treatment`): the + # default `go test ./cmd/xtcp2` compiles treatments_embedded.go out, so + # without this leg a regression in the tagged file is invisible until the + # fat Nix build. pkg/treatment itself is covered by test-tcp-controller-unit. + focused-xtcp-treatment = mkFocusedTest "xtcp-treatment" { + tags = "treatment"; + ldflags = "-checklinkname=0"; + paths = [ + "./cmd/xtcp2" + "./cmd/xtcp2-treatment-agent" + ]; + }; } diff --git a/nix/tests/tcp-controller/default.nix b/nix/tests/tcp-controller/default.nix new file mode 100644 index 000000000..4ae592f12 --- /dev/null +++ b/nix/tests/tcp-controller/default.nix @@ -0,0 +1,401 @@ +# Go-driven, rootless seven-guest integration using the existing TCP load tools. +{ + pkgs, + lib, + nixpkgs, + binaries, + vendoredSource, + soak ? false, +}: +let + name = if soak then "tcp-controller-soak" else "tcp-controller"; + agents = lib.genList (i: "agent${toString (i + 1)}") 6; + controllerAddress = "192.168.1.254"; + versions = import ../../versions.nix { inherit pkgs; }; + harness = pkgs.runCommand "tcp-controller-integration" { nativeBuildInputs = [ versions.go ]; } '' + cp -r ${vendoredSource} source + chmod -R u+w source + cd source + export GOTOOLCHAIN=local GOFLAGS=-mod=vendor CGO_ENABLED=0 + export GOCACHE="$TMPDIR/go-cache" GOMODCACHE="$TMPDIR/go-modcache" + mkdir -p "$out/bin" + go build -trimpath -o "$out/bin/tcp-controller-integration" ./tools/tcp-controller-integration + ''; + pki = pkgs.writeShellApplication { + name = "controller-test-pki"; + runtimeInputs = [ + pkgs.openssl + pkgs.coreutils + ]; + text = '' + mkdir -p /var/lib/controller-test/pki + cd /var/lib/controller-test/pki + umask 077 + openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \ + -keyout ca.key -out ca.crt -days 2 -subj /CN=xtcp-integration-CA + issue() { + local name=$1 san=$2 usage=$3 + openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \ + -keyout "$name.key" -out "$name.csr" -subj "/CN=$name" + printf 'subjectAltName=%s\nextendedKeyUsage=%s\nkeyUsage=digitalSignature\n' "$san" "$usage" > "$name.ext" + openssl x509 -req -in "$name.csr" -CA ca.crt -CAkey ca.key -CAcreateserial \ + -out "$name.crt" -days 2 -extfile "$name.ext" + } + issue controller 'DNS:controller,IP:${controllerAddress}' serverAuth + issue operator 'URI:spiffe://xtcp/operator/integration' clientAuth + for agent in ${lib.escapeShellArgs agents}; do + issue "$agent" "URI:spiffe://xtcp/agent/test-dc/$agent" clientAuth + done + ''; + }; + fixturePath = [ + pkgs.iproute2 + pkgs.coreutils + pkgs.systemd + pkgs.procps + binaries.xtcp2-treatmentctl + ]; + base = { + system.stateVersion = "26.05"; + networking.firewall.enable = false; + networking.useDHCP = false; + networking.usePredictableInterfaceNames = false; + services.timesyncd.enable = false; + virtualisation = { + graphics = false; + memorySize = 768; + cores = 1; + diskImage = null; + qemu.options = [ "-no-reboot" ]; + }; + boot.kernelModules = [ + "sch_netem" + "sch_prio" + "cls_u32" + "tcp_cubic" + ]; + environment.etc."xtcp-controller-integration".text = "Disposable VM fixture only.\n"; + environment.systemPackages = fixturePath; + }; + # Point-to-point UNIX datagram NICs form a star, bridged inside the control + # guest. No host bridge, tap, root privileges or external network is needed. + nic = + index: controller: + let + localName = if controller then "controller" else "agent"; + remoteName = if controller then "agent" else "controller"; + macPrefix = if controller then "01" else "02"; + in + [ + "-netdev dgram,id=link${toString index},local.type=unix,local.path=$TEST_NETWORK/${localName}${toString index},remote.type=unix,remote.path=$TEST_NETWORK/${remoteName}${toString index}" + "-device virtio-net-pci,netdev=link${toString index},mac=02:00:00:${macPrefix}:00:0${toString index}" + ]; + mkVM = + name: config: + (nixpkgs.lib.nixosSystem { + system = pkgs.stdenv.hostPlatform.system; + modules = [ + "${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix" + base + { + nixpkgs.pkgs = pkgs; + networking.hostName = name; + } + config + ]; + }).config.system.build.vm; + agentVM = + index: + let + name = "agent${toString index}"; + host = toString (10 + index); + in + mkVM name { + imports = [ ../../modules/xtcp2-service.nix ]; + virtualisation.qemu.networkingOptions = lib.mkForce (nic index false); + networking.interfaces.eth0.ipv4.addresses = [ + { + address = "192.168.1.${host}"; + prefixLength = 24; + } + { + address = "198.18.0.${host}"; + prefixLength = 24; + } + ]; + boot.kernel.sysctl."net.ipv4.tcp_congestion_control" = "reno"; + environment.etc."xtcp2/controller-agent.json".text = builtins.toJSON { + agent_id = name; + location = "test-dc"; + controller = "${controllerAddress}:9443"; + server_name = "controller"; + certificate = "/var/lib/controller-test/pki/agent.crt"; + private_key = "/var/lib/controller-test/pki/agent.key"; + ca = "/var/lib/controller-test/pki/ca.crt"; + enable_apply = true; + protected_prefixes = [ "192.168.1.0/24" ]; + }; + services.xtcp2 = { + enable = true; + # The slim daemon does not embed the agent, so this fixture runs the + # standalone arrangement: xtcp2-treatment-agent owns the journal and + # the routes, xtcp2 reads the journal to stamp provenance. + package = binaries.xtcp2-min; + configFile = "/etc/xtcp2/unused.json"; + linkMonitor.enable = false; + treatments = { + enable = true; + mode = "standalone"; + agentPackage = binaries.xtcp2-treatment-agent; + watchdogPackage = binaries.xtcp2-treatmentctl; + }; + extraArgs = [ + "-frequency=2s" + "-timeout=1s" + "-pollJitterPct=0" + "-marshal=protobufList" + "-dest=http://${controllerAddress}:8123/?query=INSERT+INTO+xtcp.ingest+FORMAT+ProtobufList&format_schema=xtcp_flat_record.proto:XtcpFlatRecord" + ]; + }; + # The Go fixture installs runtime credentials before starting the daemon. + systemd.services.xtcp2.wantedBy = lib.mkForce [ ]; + systemd.services.xtcp2-treatment-agent.wantedBy = lib.mkForce [ ]; + systemd.services.xtcp2-treatment-watchdog.wantedBy = lib.mkForce [ ]; + systemd.services.controller-test-agent = { + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + path = fixturePath; + serviceConfig.ExecStart = "${harness}/bin/tcp-controller-integration -role=agent -listen=192.168.1.${host}:9009 -agentUnit=xtcp2-treatment-agent"; + }; + systemd.services.load-near.serviceConfig = { + EnvironmentFile = "/var/lib/controller-test/load.env"; + ExecStart = "${binaries.tcp_client}/bin/tcp_client -count 32 -connect $TCP_TEST_DESTINATION -sleep 50ms -startsleep 5ms -pads 1024 -rto 3s -wto 3s"; + Restart = "always"; + RestartSec = 1; + StandardOutput = "null"; + StandardError = "null"; + }; + systemd.services.load-far.serviceConfig = { + ExecStart = "${binaries.tcp_client}/bin/tcp_client -count 32 -connect 198.18.0.2 -sleep 50ms -startsleep 5ms -pads 1024 -rto 3s -wto 3s"; + Restart = "always"; + RestartSec = 1; + StandardOutput = "null"; + StandardError = "null"; + }; + }; + agentVMs = lib.genList (i: agentVM (i + 1)) 6; + controllerVM = mkVM "controller" { + virtualisation.memorySize = lib.mkForce 4096; + virtualisation.cores = lib.mkForce 2; + virtualisation.qemu.networkingOptions = lib.mkForce (lib.concatMap (i: nic i true) (lib.range 1 6)); + virtualisation.sharedDirectories.evidence = { + source = "$VM_EVIDENCE/artifacts"; + target = "/var/lib/controller-test/evidence"; + writable = true; + }; + networking.bridges.br0.interfaces = lib.genList (i: "eth${toString i}") 6; + networking.interfaces.br0.ipv4.addresses = [ + { + address = controllerAddress; + prefixLength = 24; + } + { + address = "198.18.0.1"; + prefixLength = 24; + } + { + address = "198.18.0.2"; + prefixLength = 24; + } + ] + ++ lib.optionals soak ( + lib.genList (i: { + address = "198.18.0.${toString (101 + i)}"; + prefixLength = 24; + }) 6 + ); + services.postgresql = { + enable = true; + package = pkgs.postgresql_15; + ensureDatabases = [ "xtcp" ]; + ensureUsers = [ + { + name = "root"; + ensureClauses.superuser = true; + } + ]; + }; + services.clickhouse = { + enable = true; + serverConfig = { + listen_host = "0.0.0.0"; + format_schema_path = "/etc/xtcp-test/schemas/"; + max_server_memory_usage = 1500000000; + background_pool_size = 4; + background_merges_mutations_concurrency_ratio = 8; + }; + usersConfig.profiles.default = { + max_threads = 2; + max_memory_usage = 1000000000; + }; + }; + systemd.services.clickhouse.serviceConfig.TimeoutStopSec = "10s"; + environment.etc."xtcp-test/schemas/xtcp_flat_record.proto".source = + ../../../proto/xtcp_flat_record/v1/xtcp_flat_record.proto; + environment.etc."xtcp-test/schema.sql".source = + ../../../build/containers/clickhouse/initdb.d/sql/xtcp_xtcp_flat_records.sql; + environment.etc."xtcp-test/discovery.json".text = builtins.toJSON [ + { + id = "soak-nearby-cubic"; + location = "test-dc"; + congestion_control = "cubic"; + rto_min_ms = 5; + quick_ack = true; + initial_congestion_window = 100; + initial_receive_window = 100; + # A 10% guard at 5ms allows only ~0.5ms of VM scheduling variation. + # Keep this fixture tolerant of small changes but require withdrawal + # for the deliberate 5ms -> 180ms regression. Production stays at 10%. + maximum_rtt_increase = 1.0; + minimum_rtt_ms = 0; + maximum_rtt_ms = 15; + minimum_retransmission_ratio = 0; + prefixes = lib.genList (i: "198.18.0.${toString (101 + i)}/32") 6; + } + ]; + systemd.services.controller-test-pki = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = lib.getExe pki; + }; + }; + systemd.services.xtcp-controller = { + after = [ + "postgresql.service" + "postgresql-setup.service" + "controller-test-pki.service" + ]; + requires = [ + "postgresql.service" + "controller-test-pki.service" + ]; + environment.XTCP_CONTROLLER_DATABASE_DSN = "host=/run/postgresql dbname=xtcp user=root sslmode=disable"; + serviceConfig = { + ExecStart = + "${binaries.xtcp2-controller}/bin/xtcp2-controller -migrate -cert=/var/lib/controller-test/pki/controller.crt -key=/var/lib/controller-test/pki/controller.key -ca=/var/lib/controller-test/pki/ca.crt -clickhouse=http://127.0.0.1:8123" + + lib.optionalString soak " -discoveryTemplates=/etc/xtcp-test/discovery.json -discoveryInterval=1m -discoveryWindow=1m"; + Restart = "on-failure"; + }; + }; + systemd.services.tcp-echo = { + wantedBy = [ "multi-user.target" ]; + serviceConfig.ExecStart = "${binaries.tcp_server}/bin/tcp_server -count 32 -bind 0.0.0.0"; + serviceConfig.StandardOutput = "null"; + serviceConfig.StandardError = "null"; + }; + systemd.services.controller-integration = { + wantedBy = [ "multi-user.target" ]; + after = [ + "network-online.target" + "postgresql.service" + "postgresql-setup.service" + "clickhouse.service" + "controller-test-pki.service" + "tcp-echo.service" + ]; + wants = [ "network-online.target" ]; + requires = [ + "postgresql.service" + "clickhouse.service" + "controller-test-pki.service" + "tcp-echo.service" + ]; + path = fixturePath ++ [ + pkgs.clickhouse + pkgs.postgresql_15 + ]; + script = '' + trap 'systemctl poweroff --no-block' EXIT + ${harness}/bin/tcp-controller-integration -role=controller ${lib.optionalString soak "-soak"} + ''; + serviceConfig = { + Type = "oneshot"; + StandardOutput = "journal+console"; + StandardError = "journal+console"; + TimeoutStartSec = if soak then "115min" else "30min"; + }; + }; + }; + vmCheck = import ../../microvms/mkVmCheck.nix { inherit pkgs lib; } { + inherit name; + timeout = if soak then "120m" else "35m"; + launch = '' + mkdir -p links "$VM_EVIDENCE/artifacts" + ${lib.optionalString soak '' + printf '{"cycles":%s,"interval_seconds":%s}\n' \ + "''${XTCP_SOAK_CYCLES:-3}" "''${XTCP_SOAK_INTERVAL_SECONDS:-180}" > "$VM_EVIDENCE/artifacts/soak-config.json" + ''} + export TEST_NETWORK="$PWD/links" + pids=() + cleanup() { + kill "''${pids[@]}" 2>/dev/null || true + wait "''${pids[@]}" 2>/dev/null || true + } + trap cleanup EXIT + ${lib.concatImapStringsSep "\n" (i: vm: '' + mkdir agent${toString i} + (cd agent${toString i}; exec ${vm}/bin/run-agent${toString i}-vm) > "$VM_EVIDENCE/agent${toString i}.log" 2>&1 & + pids+=("$!") + '') agentVMs} + mkdir controller + cd controller + ${controllerVM}/bin/run-controller-vm + ''; + sentinels = + if soak then + [ + "TCP_CONTROLLER_SOAK_CYCLE_1_PASS" + "TCP_CONTROLLER_SOAK_CYCLE_2_PASS" + "TCP_CONTROLLER_SOAK_COOLDOWN_PASS" + "TCP_CONTROLLER_SOAK_PASS" + ] + else + [ + "TCP_CONTROLLER_RTT_PASS" + "TCP_CONTROLLER_CANARY_PASS" + "TCP_CONTROLLER_PERSIST_PASS" + "TCP_CONTROLLER_HOLD_PASS" + "TCP_CONTROLLER_BINDING_PASS" + "TCP_CONTROLLER_ROLLBACK_PASS" + "TCP_CONTROLLER_WATCHDOG_PASS" + "TCP_CONTROLLER_PASS" + ]; + failPattern = "TCP_CONTROLLER_FAIL"; + evidence = { + inherit harness; + controller = controllerVM; + }; + }; + soakApp = pkgs.writeShellApplication { + name = "test-tcp-controller-soak-vm"; + text = '' + export XTCP_SOAK_CYCLES=3 XTCP_SOAK_INTERVAL_SECONDS=180 + args=() + for arg in "$@"; do + case "$arg" in + --cycles=[2-6]) XTCP_SOAK_CYCLES=''${arg#--cycles=} ;; + --interval=3m) XTCP_SOAK_INTERVAL_SECONDS=180 ;; + --interval=4m) XTCP_SOAK_INTERVAL_SECONDS=240 ;; + --interval=5m) XTCP_SOAK_INTERVAL_SECONDS=300 ;; + --accel=*|--keep=*) args+=("$arg") ;; + *) echo 'usage: test-tcp-controller-soak-vm [--cycles=2..6] [--interval=3m|4m|5m] [--accel=auto|kvm|tcg] [--keep=N]' >&2; exit 2 ;; + esac + done + exec ${vmCheck.app}/bin/test-tcp-controller-soak-vm "''${args[@]}" + ''; + }; +in +(if soak then soakApp else vmCheck.app) // { inherit vmCheck; } diff --git a/nix/tests/tcp-controller/quality.nix b/nix/tests/tcp-controller/quality.nix new file mode 100644 index 000000000..d28976514 --- /dev/null +++ b/nix/tests/tcp-controller/quality.nix @@ -0,0 +1,98 @@ +# Focused Go checks with real disposable database fixtures. No VM or root needed. +{ pkgs, vendoredSource }: +let + versions = import ../../versions.nix { inherit pkgs; }; + # Source tree plus a disposable PostgreSQL on a Unix socket, exported as + # XTCP_CONTROLLER_TEST_DSN for the store tests. + postgresFixture = '' + cp -r ${vendoredSource} source + chmod -R u+w source + cd source + export GOTOOLCHAIN=local GOFLAGS=-mod=vendor CGO_ENABLED=1 + export GOCACHE="$TMPDIR/go-cache" GOMODCACHE="$TMPDIR/go-modcache" + mkdir -p "$out" "$TMPDIR/pg-socket" + initdb -D "$TMPDIR/pg-data" -A trust --no-locale > "$out/postgres-init.log" 2>&1 + trap 'pg_ctl -D "$TMPDIR/pg-data" -m immediate -w stop >/dev/null 2>&1 || true' EXIT + pg_ctl -D "$TMPDIR/pg-data" -l "$out/postgres.log" \ + -o "-k $TMPDIR/pg-socket -h ''' -p 55439" -w start + export XTCP_CONTROLLER_TEST_DSN="host=$TMPDIR/pg-socket port=55439 dbname=postgres sslmode=disable" + ''; + # Per-package statement coverage from the unit logs as a markdown table, + # pasted into docs/tcp-controller-testing.md. actuate runs its treatment + # tests only. + coverageTable = '' + go tool cover -func "$out/coverage.out" > "$out/coverage.txt" + { + echo "| Package | Statements covered |" + echo "| --- | ---: |" + cat "$out/tests.log" "$out/routes.log" | awk -F'\t' '/^ok/ && /coverage:/ { + pkg = $2; sub("github.com/randomizedcoder/xtcp2/", "", pkg) + match($0, /coverage: [0-9.]+%/) + print "| `" pkg "` | " substr($0, RSTART + 10, RLENGTH - 10) " |" + }' + } > "$out/coverage-table.md" + ''; + check = + race: + pkgs.runCommand "xtcp2-controller-${if race then "race" else "unit"}" + { + nativeBuildInputs = [ + versions.go + pkgs.gcc + pkgs.postgresql + pkgs.clickhouse # clickhouse_test.go finds it on PATH + ]; + } + '' + ${postgresFixture} + go test -ldflags=-checklinkname=0 ${ + if race then "-race -count=3" else "-count=1 -coverprofile=$out/coverage.out" + } \ + -timeout 5m -v ./pkg/treatment/... ./tools/tcp-controller-integration \ + > "$out/tests.log" 2>&1 || { cat "$out/tests.log"; exit 1; } + # These fixtures must execute, never silently skip in the focused checks. + grep -q -- '--- PASS: TestPostgresConcurrentReviewFencesReplicas' "$out/tests.log" + grep -q -- '--- PASS: TestClickHouseAnalysisCounterDeltas' "$out/tests.log" + go test -ldflags=-checklinkname=0 ${if race then "-race -count=3" else "-count=1 -cover"} \ + -timeout 5m -v -run '^TestTreatment' ./internal/goip/actuate > "$out/routes.log" 2>&1 \ + || { cat "$out/routes.log"; exit 1; } + ${if race then "" else coverageTable} + ''; +in +{ + unit = check false; + race = check true; + # Query-plan timings for the discovery indexes, three runs; the source of + # docs/benchmarks/tcp-controller/postgres-indexes.txt. + postgres-indexes = + pkgs.runCommand "xtcp2-controller-postgres-indexes" + { + nativeBuildInputs = [ + versions.go + pkgs.gcc + pkgs.postgresql + ]; + } + '' + ${postgresFixture} + { + echo "# nix build .#bench-tcp-controller-postgres-indexes" + echo "# $(postgres --version), $(go version)" + go test -ldflags=-checklinkname=0 -count=3 -timeout 10m -v \ + -run '^TestPostgresExperimentQueryIndexes$' ./pkg/treatment/controller/store/postgres + } > "$out/postgres-indexes.txt" 2>&1 || { cat "$out/postgres-indexes.txt"; exit 1; } + grep -q -- '--- PASS: TestPostgresExperimentQueryIndexes' "$out/postgres-indexes.txt" + ''; + bench = pkgs.runCommand "xtcp2-controller-bench" { nativeBuildInputs = [ versions.go ]; } '' + cp -r ${vendoredSource} source + chmod -R u+w source + cd source + export GOTOOLCHAIN=local GOFLAGS=-mod=vendor CGO_ENABLED=0 + export GOCACHE="$TMPDIR/go-cache" GOMODCACHE="$TMPDIR/go-modcache" + mkdir -p "$out" + go test -ldflags=-checklinkname=0 -run '^$' -bench . -benchmem -benchtime=1s -count=5 \ + ./pkg/treatment/... > "$out/benchmarks.txt" 2>&1 || { cat "$out/benchmarks.txt"; exit 1; } + go test -ldflags=-checklinkname=0 -run '^$' -bench '^BenchmarkTreatment' -benchmem -benchtime=1s -count=5 \ + ./internal/goip/actuate >> "$out/benchmarks.txt" 2>&1 || { cat "$out/benchmarks.txt"; exit 1; } + ''; +} diff --git a/nix/versions.nix b/nix/versions.nix index 310873ae9..3832fe7ce 100644 --- a/nix/versions.nix +++ b/nix/versions.nix @@ -189,5 +189,5 @@ # Go vendor hash. Update by running `nix build .#xtcp2` and pasting the # `got:` value from the hash mismatch error. Used by every Nix check that # needs deps in the sandbox (see nix/lib/goModules.nix). - goVendorHash = "sha256-XChzSZIrfD/+1oYQOnfkPpUDi5jL2DVmuS1NhrUHKjw="; + goVendorHash = "sha256-edC07JgIpw07SXDd1ieNNBGLhRvNDTkqNUIpmYUsx0Q="; } diff --git a/pkg/treatment/agent/agent.go b/pkg/treatment/agent/agent.go new file mode 100644 index 000000000..43ca5128f --- /dev/null +++ b/pkg/treatment/agent/agent.go @@ -0,0 +1,251 @@ +// Package agent is the controller-facing half of a treatment host: the mTLS +// check-in loop, the desired-state watch and telemetry stamping, over the +// offline Host from package local. It is a library with two front ends: +// cmd/xtcp2-treatment-agent runs it standalone and cmd/xtcp2 embeds it when +// built with the treatment tag. +package agent + +import ( + "context" + "crypto/rand" + "crypto/x509" + "encoding/hex" + "fmt" + "log" + "math/big" + "net" + "net/netip" + "os" + "strings" + "sync" + "sync/atomic" + "time" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/attribution" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "github.com/randomizedcoder/xtcp2/pkg/treatment/local" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "golang.org/x/sys/unix" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +// Config is the shared host configuration file; see local.Config. +type Config = local.Config + +// LoadConfig reads the shared host configuration file. +func LoadConfig(path string) (Config, error) { return local.LoadConfig(path) } + +// Agent is one host's connection to the controller. +type Agent struct { + Config Config + Host *local.Host + Reconciler *reconcile.Reconciler + client pb.AgentControlServiceClient + conn *grpc.ClientConn + state atomic.Pointer[reconcile.State] + stamper attribution.Stamper + wake chan struct{} + // collectionID is a per-process nonce; see attribution.Identity. + collectionID string +} + +// newLocal builds the offline part. A nil identity inspects the host. +func newLocal(c Config, id *local.Identity) (*Agent, error) { + h, err := local.New(c, id) + if err != nil { + return nil, err + } + var nonce [16]byte + if _, err = rand.Read(nonce[:]); err != nil { + return nil, err + } + a := &Agent{Config: h.Config, Host: h, Reconciler: h.Reconciler, wake: make(chan struct{}, 1), collectionID: hex.EncodeToString(nonce[:])} + // The agent owns the nonce: it goes into every journal header it writes, + // where a telemetry-only daemon reads it, and into every check-in. + h.Reconciler.CollectionID = a.collectionID + a.publish(nil) + return a, nil +} + +// New validates identity before constructing any mutation-capable path. DNS +// resolution is only needed to add management destinations to the exclusions; +// deployments should list stable management prefixes for offline reboot use. +func New(ctx context.Context, c Config) (*Agent, error) { + tlsConfig, e := identity.TLSConfig(c.Certificate, c.PrivateKey, c.CA, c.ServerName, false) + if e != nil { + return nil, e + } + cert, e := x509.ParseCertificate(tlsConfig.Certificates[0].Certificate[0]) + if e != nil { + return nil, e + } + id, e := identity.FromCertificate(cert) + if e != nil { + return nil, e + } + if id.Role != identity.RoleAgent || id.ID != c.AgentID || id.Location != c.Location { + return nil, fmt.Errorf("agent config names %s/%s but the certificate's URI SAN is %s/%s/%s; location and agent_id are certificate-bound", c.Location, c.AgentID, id.Role, id.Location, id.ID) + } + a, e := newLocal(c, nil) + if e != nil { + return nil, e + } + host, _, e := net.SplitHostPort(c.Controller) + if e != nil { + return nil, e + } + lookupCtx, cancel := context.WithTimeout(ctx, 3*time.Second) + defer cancel() + if ip, e := netip.ParseAddr(host); e == nil { + a.Host.Protect(netip.PrefixFrom(ip, ip.BitLen())) + } else if ips, e := net.DefaultResolver.LookupNetIP(lookupCtx, "ip", host); e == nil { + for _, ip := range ips { + ip = ip.Unmap() + a.Host.Protect(netip.PrefixFrom(ip, ip.BitLen())) + } + } + conn, e := grpc.NewClient(c.Controller, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(treatment.MaxStateBytes), grpc.MaxCallSendMsgSize(treatment.MaxStateBytes))) + if e != nil { + return nil, e + } + a.conn = conn + a.client = pb.NewAgentControlServiceClient(conn) + return a, nil +} + +// Close releases the controller connection. +func (a *Agent) Close() error { + if a.conn == nil { + return nil + } + return a.conn.Close() +} + +// Wake asks the run loop to check in now; concurrent wakes coalesce. +func (a *Agent) Wake() { + select { + case a.wake <- struct{}{}: + default: + } +} + +// State returns a copy of the last journal snapshot, nil before the first pass. +func (a *Agent) State() *reconcile.State { return a.state.Load().Clone() } + +func (a *Agent) identity() attribution.Identity { + return attribution.Identity{AgentID: a.Config.AgentID, Location: a.Config.Location, BootID: a.Host.Identity.BootID, CollectionID: a.collectionID, NetnsInode: a.Host.Identity.NetnsInode} +} + +func (a *Agent) reconcile(ctx context.Context, d *treatment.DesiredState) { + ctx, cancel := context.WithTimeout(ctx, 15*time.Second) + defer cancel() + s, e := a.Reconciler.Run(ctx, d, reconcile.ModeFull) + if s != nil { + a.publish(s) + } + if e != nil { + log.Printf("treatment reconcile: %v", e) + } +} + +func (a *Agent) publish(s *reconcile.State) { + if s != nil { + a.state.Store(s) + } + a.stamper.Publish(attribution.Build(s, a.identity(), true)) +} + +// Run checks in, reconciles and watches until ctx ends. +func (a *Agent) Run(ctx context.Context) { + var workers sync.WaitGroup + workers.Add(1) + go func() { defer workers.Done(); a.watchRouting(ctx) }() + defer workers.Wait() + a.reconcile(ctx, nil) + watchStarted := false + for { + a.reconcile(ctx, nil) + callCtx, cancel := context.WithTimeout(ctx, 10*time.Second) + report := &treatment.AgentReport{AgentID: a.Config.AgentID, Location: a.Config.Location, Capabilities: a.capabilities(callCtx)} + if s := a.state.Load(); s != nil { + report.DesiredRevision = s.Revision() + report.LocallySuspended = s.LocallySuspended + report.Records = s.Reports() + } + response, e := a.client.CheckIn(callCtx, wire.Report(report)) + cancel() + if e != nil { + log.Printf("treatment check-in: %v", e) + } else { + if response.Desired != nil { + if d, e := wire.ParseDesired(response.Desired); e != nil { + log.Printf("treatment check-in: invalid desired state: %v", e) + } else { + a.reconcile(ctx, d) + } + } + if !watchStarted { + watchStarted = true + workers.Add(1) + go func() { defer workers.Done(); a.watch(ctx) }() + } + } + // Without entropy the check-in simply runs unjittered. + delay := 27 * time.Second + if jitter, jerr := rand.Int(rand.Reader, big.NewInt(6000)); jerr == nil { + delay += time.Duration(jitter.Int64()) * time.Millisecond + } + timer := time.NewTimer(delay) + select { + case <-ctx.Done(): + timer.Stop() + return + case <-a.wake: + timer.Stop() + case <-timer.C: + } + } +} + +func (a *Agent) watch(ctx context.Context) { + for ctx.Err() == nil { + stream, e := a.client.WatchDesiredState(ctx, &pb.WatchDesiredStateRequest{AgentId: a.Config.AgentID, AfterRevision: a.state.Load().Revision()}) + if e == nil { + for { + _, e = stream.Recv() + if e != nil { + break + } + a.Wake() + } + } + t := time.NewTimer(5 * time.Second) + select { + case <-ctx.Done(): + t.Stop() + return + case <-t.C: + } + } +} + +func (a *Agent) capabilities(ctx context.Context) treatment.Capabilities { + c := treatment.Capabilities{BootID: a.Host.Identity.BootID, CollectionID: a.collectionID, ActuatorEnabled: a.Config.EnableApply} + var u unix.Utsname + if unix.Uname(&u) == nil { + c.KernelRelease = unix.ByteSliceToString(u.Release[:]) + } + if data, e := os.ReadFile("/proc/sys/net/ipv4/tcp_available_congestion_control"); e == nil { + c.CongestionAlgorithms = strings.Fields(string(data)) + } + c.SimpleHostRouting = a.Host.SimpleHostRouting(ctx) + return c +} + +// Stamp is the hot-path telemetry hook; see attribution.Index.Stamp. +func (a *Agent) Stamp(r *flat.XtcpFlatRecord) { a.stamper.Stamp(r) } diff --git a/pkg/treatment/agent/agent_test.go b/pkg/treatment/agent/agent_test.go new file mode 100644 index 000000000..62d93ea45 --- /dev/null +++ b/pkg/treatment/agent/agent_test.go @@ -0,0 +1,103 @@ +package agent + +import ( + "context" + "net/netip" + "strconv" + "testing" + "time" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/local" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" +) + +func ptr[T any](v T) *T { return &v } + +var testIdentity = &local.Identity{BootID: "boot-1", NetnsInode: 123} + +func testAgent(t testing.TB) *Agent { + t.Helper() + a, err := newLocal(Config{AgentID: "host-1", Location: "dc", Directory: t.TempDir()}, testIdentity) + if err != nil { + t.Fatal(err) + } + return a +} + +func TestStampDistinguishesAssignedAndActuallyExposed(t *testing.T) { + a := testAgent(t) + s := &reconcile.State{Desired: &treatment.DesiredState{Revision: 2}, Records: []reconcile.Record{{ApplicationRecord: treatment.ApplicationRecord{Status: treatment.ApplyVerified, AppliedAt: time.Now(), Assignment: treatment.Assignment{ExperimentID: "exp-1", Generation: 1, Mode: treatment.ModeStable, Treatment: treatment.Treatment{Destination: netip.MustParsePrefix("192.0.2.1/32"), Settings: treatment.TCPSettings{CongestionControl: ptr("cubic")}}}}}}} + a.publish(s) + r := &flat.XtcpFlatRecord{NetnsInode: 123, InetDiagMsgFamily: 2, InetDiagMsgSocketDestination: []byte{192, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, InetDiagCong: "bbr"} + a.Stamp(r) + if r.TreatmentAssignmentId != "exp-1" || r.TreatmentAlgorithmExposed { + t.Fatal("assignment mistaken for exposure") + } + if r.AgentId != "host-1" || r.Location != "dc" || r.HostBootId != "boot-1" || len(r.CollectionId) != 32 || r.TreatmentStateRevision != 2 { + t.Fatalf("identity not stamped from the agent: %+v", r) + } + r.InetDiagCong = "cubic" + a.Stamp(r) + if !r.TreatmentAlgorithmExposed { + t.Fatal("matching algorithm not attributed") + } + r.NetnsInode = 124 + a.Stamp(r) + if r.TreatmentAssignmentId != "" || r.TreatmentAlgorithmExposed { + t.Fatal("host route attributed to another namespace") + } + r.NetnsInode = 123 + s.Records[0].Assignment.Mode = treatment.ModeTrial + s.Records[0].Assignment.LeaseExpiresAt = time.Now().Add(-time.Second) + a.publish(s) + a.Stamp(r) + if r.TreatmentAlgorithmExposed { + t.Fatal("expired trial remained exposed") + } +} + +// Before the first reconcile pass the agent already stamps its identity so +// records are attributable to the host even while the controller is away. +func TestStampBeforeFirstReconcile(t *testing.T) { + a := testAgent(t) + r := &flat.XtcpFlatRecord{NetnsInode: 123, TreatmentAssignmentId: "stale"} + a.Stamp(r) + if r.AgentId != "host-1" || r.HostBootId != "boot-1" || r.TreatmentStateRevision != 0 || r.TreatmentAssignmentId != "" { + t.Fatalf("identity-only stamp wrong: %+v", r) + } + if a.State() != nil { + t.Fatal("state published before any pass") + } +} + +// TestAgentOwnsCollectionID: one nonce per agent process, the same in the +// journal header a telemetry-only daemon reads, in the check-in report and +// on records the agent stamps itself; a second process draws another. +func TestAgentOwnsCollectionID(t *testing.T) { + a := testAgent(t) + a.reconcile(context.Background(), nil) + journal, err := reconcile.ReadSnapshot(a.Config.Directory) + if err != nil { + t.Fatal(err) + } + r := &flat.XtcpFlatRecord{} + a.Stamp(r) + reported := a.capabilities(context.Background()).CollectionID + tests := []struct { + description string + got string + expected string + }{ + {"positive: the nonce is well formed", strconv.FormatBool(treatment.ValidCollectionID(reported)), "true"}, + {"positive: the journal header carries the reported nonce", journal.CollectionID, reported}, + {"positive: embedded stamping uses the same nonce", r.CollectionId, reported}, + {"corner: another agent process draws a different nonce", strconv.FormatBool(testAgent(t).collectionID == reported), "false"}, + } + for _, tc := range tests { + if tc.got != tc.expected { + t.Errorf("%s: got %q, want %q", tc.description, tc.got, tc.expected) + } + } +} diff --git a/pkg/treatment/agent/benchmark_test.go b/pkg/treatment/agent/benchmark_test.go new file mode 100644 index 000000000..0fac72cff --- /dev/null +++ b/pkg/treatment/agent/benchmark_test.go @@ -0,0 +1,56 @@ +package agent + +import ( + "fmt" + "net/netip" + "testing" + "time" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" +) + +func stampFixture(t testing.TB, n int) (*Agent, *reconcile.State, *flat.XtcpFlatRecord) { + a := testAgent(t) + s := &reconcile.State{Desired: &treatment.DesiredState{Revision: 1}} + for i := range n { + ip := netip.AddrFrom4([4]byte{192, 0, byte(i >> 8), byte(i)}) + s.Records = append(s.Records, reconcile.Record{ApplicationRecord: treatment.ApplicationRecord{Status: treatment.ApplyVerified, AppliedAt: time.Unix(1700000000, 0), Assignment: treatment.Assignment{ExperimentID: fmt.Sprintf("assignment-%d", i), Generation: 1, Mode: treatment.ModeStable, Treatment: treatment.Treatment{Destination: netip.PrefixFrom(ip, 32), Settings: treatment.TCPSettings{CongestionControl: ptr("cubic")}}}}}) + } + a.publish(s) + r := &flat.XtcpFlatRecord{NetnsInode: 123, InetDiagMsgFamily: 2, InetDiagMsgSocketDestination: []byte{192, 0, 0, 0}, InetDiagCong: "cubic"} + return a, s, r +} + +func BenchmarkStamp(b *testing.B) { + for _, n := range []int{1, 100, 4096} { + for _, match := range []bool{true, false} { + b.Run(fmt.Sprintf("routes=%d/match=%t", n, match), func(b *testing.B) { + a, _, r := stampFixture(b, n) + if !match { + r.InetDiagMsgSocketDestination = []byte{198, 51, 100, 1} + } + b.ReportAllocs() + for b.Loop() { + a.Stamp(r) + } + if r.TreatmentAlgorithmExposed != match { + b.Fatal("wrong exposure") + } + }) + } + } +} + +func BenchmarkPublish(b *testing.B) { + for _, n := range []int{1, 100, 4096} { + b.Run(fmt.Sprint(n), func(b *testing.B) { + a, s, _ := stampFixture(b, n) + b.ReportAllocs() + for b.Loop() { + a.publish(s) + } + }) + } +} diff --git a/pkg/treatment/agent/contracts_test.go b/pkg/treatment/agent/contracts_test.go new file mode 100644 index 000000000..7426b9548 --- /dev/null +++ b/pkg/treatment/agent/contracts_test.go @@ -0,0 +1,52 @@ +package agent + +import ( + "sync" + "testing" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" +) + +// Reconciliation publishes immutable snapshots while socket workers stamp +// independent records and RPC check-ins clone the current state. +func TestConcurrentPublishStampState(t *testing.T) { + a, s, _ := stampFixture(t, 16) + var wg sync.WaitGroup + wg.Go(func() { + for i := range 200 { + next := s.Clone() + next.Desired.Revision = uint64(i + 2) + a.publish(next) + a.Wake() + } + }) + for range 8 { + wg.Go(func() { + r := &flat.XtcpFlatRecord{NetnsInode: 123, InetDiagMsgFamily: 2, InetDiagMsgSocketDestination: []byte{192, 0, 0, 0}, InetDiagCong: "cubic"} + for range 200 { + a.Stamp(r) + if r.TreatmentAssignmentId != "assignment-0" || !r.TreatmentAlgorithmExposed { + t.Error("inconsistent exposure snapshot") + return + } + state := a.State() + state.Records[0].Assignment.ExperimentID = "caller mutation" + a.Wake() + } + }) + } + wg.Wait() + if a.State().Records[0].Assignment.ExperimentID != "assignment-0" { + t.Fatal("State leaked mutable internal snapshot") + } + select { + case <-a.wake: + default: + t.Fatal("Wake dropped every notification") + } + select { + case <-a.wake: + t.Fatal("Wake did not coalesce") + default: + } +} diff --git a/pkg/treatment/agent/lifecycle_test.go b/pkg/treatment/agent/lifecycle_test.go new file mode 100644 index 000000000..9fa52f158 --- /dev/null +++ b/pkg/treatment/agent/lifecycle_test.go @@ -0,0 +1,86 @@ +package agent + +import ( + "context" + "errors" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/timestamppb" +) + +type lifecycleClient struct { + pb.AgentControlServiceClient + t *testing.T + cancel context.CancelFunc + fail bool + badDesired bool + checked, watched bool // inspected only after Run has joined all workers +} + +func (c *lifecycleClient) CheckIn(_ context.Context, r *pb.CheckInRequest, _ ...grpc.CallOption) (*pb.CheckInResponse, error) { + c.checked = true + if r.AgentId != "host-1" || r.Location != "dc" || r.Capabilities.BootId != "boot-1" || r.Capabilities.ActuatorEnabled { + c.t.Error("incorrect check-in identity/capabilities") + } + for _, v := range r.Records { + if len(v.InstalledRoute) != 0 || v.InstalledBootId != "" { + c.t.Error("local kernel state leaked into RPC") + } + } + if c.fail { + c.cancel() + return nil, errors.New("controller offline") + } + if c.badDesired { + c.cancel() + return &pb.CheckInResponse{Desired: &pb.DesiredState{AgentId: "host-1", Revision: 7, IssuedAt: ×tamppb.Timestamp{Nanos: -1}}}, nil + } + return &pb.CheckInResponse{Desired: &pb.DesiredState{AgentId: "host-1", Revision: 7, IssuedAt: timestamppb.Now()}}, nil +} +func (c *lifecycleClient) WatchDesiredState(_ context.Context, r *pb.WatchDesiredStateRequest, _ ...grpc.CallOption) (grpc.ServerStreamingClient[pb.WatchDesiredStateResponse], error) { + c.watched = true + if r.AgentId != "host-1" || r.AfterRevision != 7 { + c.t.Error("watch did not resume from reconciled revision") + } + c.cancel() + return nil, errors.New("stream disconnected") +} + +func TestAgentRunCancellation(t *testing.T) { + for _, tc := range []struct { + name, description string + fail, badDesired bool + wantWatch bool + wantRevision uint64 + }{ + {"connected", "positive: a successful check-in reconciles and starts the watch", false, false, true, 7}, + {"offline", "negative: an offline controller leaves the journal untouched and never watches", true, false, false, 0}, + {"undecodable", "corner: a desired state that fails to decode is logged, not reconciled", false, true, false, 0}, + } { + t.Run(tc.name, func(t *testing.T) { + a := testAgent(t) + defer a.Close() + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + c := &lifecycleClient{t: t, cancel: cancel, fail: tc.fail, badDesired: tc.badDesired} + a.client = c + a.Run(ctx) + if !c.checked || c.watched != tc.wantWatch { + t.Fatalf("%s: checked=%t watched=%t", tc.description, c.checked, c.watched) + } + if got := a.State().Revision(); got != tc.wantRevision { + t.Fatalf("%s: revision %d, want %d", tc.description, got, tc.wantRevision) + } + }) + } +} + +func TestLocalIdentityFailure(t *testing.T) { + a, err := newLocal(Config{AgentID: "../host", Location: "dc"}, testIdentity) + if a != nil || err == nil { + t.Fatalf("invalid identity must prevent construction: %v %v", a, err) + } +} diff --git a/pkg/treatment/agent/watch_linux.go b/pkg/treatment/agent/watch_linux.go new file mode 100644 index 000000000..534e6e80d --- /dev/null +++ b/pkg/treatment/agent/watch_linux.go @@ -0,0 +1,54 @@ +package agent + +import ( + "context" + "log" + + "golang.org/x/sys/unix" +) + +func (a *Agent) watchRouting(ctx context.Context) { + fd, e := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW|unix.SOCK_CLOEXEC|unix.SOCK_NONBLOCK, unix.NETLINK_ROUTE) + if e != nil { + log.Printf("treatment route watch unavailable: %v; periodic reconciliation remains enabled", e) + return + } + defer func() { + if cerr := unix.Close(fd); cerr != nil { + log.Printf("treatment route watch close: %v", cerr) + } + }() + groups := uint32(unix.RTMGRP_LINK | unix.RTMGRP_IPV4_IFADDR | unix.RTMGRP_IPV6_IFADDR | unix.RTMGRP_IPV4_ROUTE | unix.RTMGRP_IPV6_ROUTE | unix.RTMGRP_IPV4_RULE) + // RTNLGRP_IPV6_RULE is a group number; sockaddr_nl expects its bitmask. + groups |= 1 << (unix.RTNLGRP_IPV6_RULE - 1) + if e = unix.Bind(fd, &unix.SockaddrNetlink{Family: unix.AF_NETLINK, Groups: groups}); e != nil { + log.Printf("treatment route watch bind: %v", e) + return + } + buf := make([]byte, 64<<10) + for ctx.Err() == nil { + p := []unix.PollFd{{Fd: int32(fd), Events: unix.POLLIN}} + _, e := unix.Poll(p, 1000) + if e == unix.EINTR { + continue + } + if e != nil { + log.Printf("treatment route watch: %v", e) + return + } + if p[0].Revents == 0 { + continue + } + _, from, e := unix.Recvfrom(fd, buf, 0) + if e == unix.EAGAIN { + continue + } + if e != nil { + a.Wake() + continue + } // ENOBUFS requires a complete resnapshot. + if peer, ok := from.(*unix.SockaddrNetlink); ok && peer.Pid == 0 { + a.Wake() + } + } +} diff --git a/pkg/treatment/attribution/index.go b/pkg/treatment/attribution/index.go new file mode 100644 index 000000000..e33419b9e --- /dev/null +++ b/pkg/treatment/attribution/index.go @@ -0,0 +1,151 @@ +// Package attribution stamps controller provenance onto socket telemetry: which +// agent collected a record, under which boot and desired-state revision, and +// whether the socket's destination had a verified treatment route when it +// was observed. Both agent modes feed it the same way, from a journal +// snapshot: the embedded agent after each reconcile pass, the telemetry-only +// daemon from the journal directory a standalone agent writes. +// +// Stamp runs on the socket hot path. It is one atomic load, one map lookup +// and no allocation; the index is rebuilt off the hot path on every publish. +package attribution + +import ( + "net/netip" + "sync/atomic" + "time" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" + "golang.org/x/sys/unix" +) + +// Identity is the collection provenance written on every record. +type Identity struct { + AgentID string + Location string + BootID string + // CollectionID is the agent process's nonce (see + // treatment.ValidCollectionID). The controller counts a record as + // evidence only when its agent reported this nonce with this boot ID. + CollectionID string + // NetnsInode is the namespace the treatment routes live in; sockets in + // any other namespace are never attributed. + NetnsInode uint64 +} + +type exposure struct { + experimentID string + generation uint64 + appliedNs int64 + algorithm string + trial bool + leaseExpires time.Time +} + +// Index is an immutable snapshot of what to stamp. +type Index struct { + identity Identity + // setLocation says whether the record's location is replaced by the + // identity's: true for the embedded agent, whose location is certificate + // bound; false for a telemetry-only daemon, which keeps its own label. + setLocation bool + revision uint64 + held bool + routes map[netip.Addr]exposure +} + +// Build indexes the verified, applied routes of a snapshot. A nil snapshot +// yields an index that stamps identity only. +func Build(s *reconcile.State, id Identity, setLocation bool) *Index { + x := &Index{identity: id, setLocation: setLocation, routes: map[netip.Addr]exposure{}} + if s == nil { + return x + } + x.revision = s.Revision() + x.held = s.Held() + for i := range s.Records { + v := &s.Records[i] + if v.Status != treatment.ApplyVerified || v.AppliedAt.IsZero() || !v.Assignment.Treatment.Destination.IsValid() { + continue + } + a := &v.Assignment + x.routes[a.Treatment.Destination.Addr()] = exposure{experimentID: a.ExperimentID, generation: a.Generation, appliedNs: v.AppliedAt.UnixNano(), algorithm: a.Treatment.Settings.Algorithm(), trial: a.Mode == treatment.ModeTrial, leaseExpires: a.LeaseExpiresAt} + } + return x +} + +// Identity returns the provenance the index stamps. +func (x *Index) Identity() Identity { return x.identity } + +// Routes is the number of attributable destinations. +func (x *Index) Routes() int { return len(x.routes) } + +// Revision is the desired-state revision the index was built from. +func (x *Index) Revision() uint64 { return x.revision } + +// Held reports whether a hold suppressed attribution. +func (x *Index) Held() bool { return x.held } + +func clearTreatment(r *flat.XtcpFlatRecord) { + r.TreatmentStateRevision = 0 + r.TreatmentAssignmentId = "" + r.TreatmentGeneration = 0 + r.TreatmentAppliedTimestampNs = 0 + r.TreatmentAlgorithmExposed = false +} + +// Stamp writes provenance onto r. A nil index clears everything except the +// record's own location: with no journal there is no agent to speak for. +func (x *Index) Stamp(r *flat.XtcpFlatRecord) { + clearTreatment(r) + if x == nil { + r.AgentId = "" + r.HostBootId = "" + r.CollectionId = "" + return + } + r.AgentId = x.identity.AgentID + if x.setLocation { + // Experiment location is certificate-bound, so it must not depend + // on a second independently configured telemetry label. + r.Location = x.identity.Location + } + r.HostBootId = x.identity.BootID + r.CollectionId = x.identity.CollectionID + r.TreatmentStateRevision = x.revision + if x.held || r.NetnsInode != x.identity.NetnsInode { + return + } + raw := r.InetDiagMsgSocketDestination + if r.InetDiagMsgFamily == unix.AF_INET && len(raw) >= 4 { + raw = raw[:4] + } + ip, ok := netip.AddrFromSlice(raw) + if !ok { + return + } + v, ok := x.routes[ip] + if !ok { + return + } + if v.trial && (v.leaseExpires.IsZero() || !v.leaseExpires.After(time.Now())) { + return + } + r.TreatmentAssignmentId = v.experimentID + r.TreatmentGeneration = v.generation + r.TreatmentAppliedTimestampNs = v.appliedNs + r.TreatmentAlgorithmExposed = v.algorithm != "" && r.InetDiagCong == v.algorithm +} + +// Stamper is the hot-path handle: Publish swaps the index, Stamp reads it. +type Stamper struct{ index atomic.Pointer[Index] } + +// Publish makes x the current index for subsequent stamps. +func (s *Stamper) Publish(x *Index) { s.index.Store(x) } + +// Current returns the published index, nil before the first publish. +func (s *Stamper) Current() *Index { return s.index.Load() } + +// Stamp applies the current index to r; safe before any publish. +func (s *Stamper) Stamp(r *flat.XtcpFlatRecord) { s.index.Load().Stamp(r) } diff --git a/pkg/treatment/attribution/index_test.go b/pkg/treatment/attribution/index_test.go new file mode 100644 index 000000000..270723bb9 --- /dev/null +++ b/pkg/treatment/attribution/index_test.go @@ -0,0 +1,200 @@ +package attribution + +import ( + "fmt" + "net/netip" + "sync" + "testing" + "time" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" +) + +func ptr[T any](v T) *T { return &v } + +var testIdentity = Identity{AgentID: "host", Location: "dc", BootID: "boot", CollectionID: "session", NetnsInode: 123} + +// fixture is n verified stable CUBIC routes on 192.0.x.y plus a matching record. +func fixture(n int) (*reconcile.State, *flat.XtcpFlatRecord) { + s := &reconcile.State{AgentID: "host", Desired: &treatment.DesiredState{Revision: 1}} + for i := range n { + ip := netip.AddrFrom4([4]byte{192, 0, byte(i >> 8), byte(i)}) + s.Records = append(s.Records, reconcile.Record{ApplicationRecord: treatment.ApplicationRecord{Status: treatment.ApplyVerified, AppliedAt: time.Unix(1700000000, 0), Assignment: treatment.Assignment{ExperimentID: fmt.Sprintf("assignment-%d", i), Generation: 1, Mode: treatment.ModeStable, Treatment: treatment.Treatment{Destination: netip.PrefixFrom(ip, 32), Settings: treatment.TCPSettings{CongestionControl: ptr("cubic")}}}}}) + } + r := &flat.XtcpFlatRecord{Location: "daemon-dc", NetnsInode: 123, InetDiagMsgFamily: 2, InetDiagMsgSocketDestination: []byte{192, 0, 0, 0}, InetDiagCong: "cubic"} + return s, r +} + +func TestStampContracts(t *testing.T) { + for _, tc := range []struct { + name, description string + change func(*reconcile.State, *flat.XtcpFlatRecord) + wantAssignment, wantExposed bool + }{ + {"match", "positive: verified matching algorithm is exposed", func(*reconcile.State, *flat.XtcpFlatRecord) {}, true, true}, + {"different-algorithm", "positive: assigned is distinct from exposed", func(_ *reconcile.State, r *flat.XtcpFlatRecord) { r.InetDiagCong = "bbr" }, true, false}, + {"foreign-netns", "negative: host routes do not apply in other namespaces", func(_ *reconcile.State, r *flat.XtcpFlatRecord) { r.NetnsInode++ }, false, false}, + {"unknown-destination", "negative: unmatched socket has no treatment", func(_ *reconcile.State, r *flat.XtcpFlatRecord) { + r.InetDiagMsgSocketDestination = []byte{198, 51, 100, 1} + }, false, false}, + {"malformed-address", "corner: short addresses are ignored", func(_ *reconcile.State, r *flat.XtcpFlatRecord) { r.InetDiagMsgSocketDestination = []byte{192} }, false, false}, + {"local-hold", "negative: local hold clears attribution", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { s.LocallySuspended = true }, false, false}, + {"fleet-hold", "negative: controller hold clears attribution", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { s.Desired.Suspended = true }, false, false}, + {"failed", "negative: failed application is never attributed", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { + s.Records[0].Status = treatment.ApplyFailed + }, false, false}, + {"no-applied-time", "negative: unapplied record is not attributed", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { s.Records[0].AppliedAt = time.Time{} }, false, false}, + {"expired", "boundary: expired trial loses attribution", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { + a := &s.Records[0].Assignment + a.Mode = treatment.ModeTrial + a.LeaseExpiresAt = time.Unix(1, 0) + }, false, false}, + {"trial-no-lease", "boundary: a trial without a lease is never exposed", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { + s.Records[0].Assignment.Mode = treatment.ModeTrial + }, false, false}, + {"trial", "positive: unexpired trial is exposed", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { + a := &s.Records[0].Assignment + a.Mode = treatment.ModeTrial + a.LeaseExpiresAt = time.Now().Add(time.Hour) + }, true, true}, + {"no-algorithm", "corner: a treatment without an algorithm is attributed but never algorithm-exposed", func(s *reconcile.State, _ *flat.XtcpFlatRecord) { + s.Records[0].Assignment.Treatment.Settings = treatment.TCPSettings{QuickAck: ptr(true)} + }, true, false}, + {"ipv6", "positive: IPv6 host route matches 16-byte socket address", func(s *reconcile.State, r *flat.XtcpFlatRecord) { + s.Records[0].Assignment.Treatment.Destination = netip.MustParsePrefix("2001:db8::1/128") + r.InetDiagMsgFamily = 10 + r.InetDiagMsgSocketDestination = []byte{0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + }, true, true}, + {"ipv4-padded", "corner: kernel padded IPv4 addresses match", func(_ *reconcile.State, r *flat.XtcpFlatRecord) { + r.InetDiagMsgSocketDestination = append(r.InetDiagMsgSocketDestination, make([]byte, 12)...) + }, true, true}, + } { + t.Run(tc.name, func(t *testing.T) { + s, r := fixture(1) + tc.change(s, r) + x := Build(s, testIdentity, true) + r.TreatmentAssignmentId = "old" + r.TreatmentAlgorithmExposed = true + r.TreatmentGeneration = 99 + x.Stamp(r) + if (r.TreatmentAssignmentId != "") != tc.wantAssignment || r.TreatmentAlgorithmExposed != tc.wantExposed { + t.Fatalf("%s: assignment=%q exposed=%t; want %t/%t", tc.description, r.TreatmentAssignmentId, r.TreatmentAlgorithmExposed, tc.wantAssignment, tc.wantExposed) + } + if !tc.wantAssignment && (r.TreatmentGeneration != 0 || r.TreatmentAppliedTimestampNs != 0) { + t.Fatal("stale attribution was not cleared") + } + if tc.wantAssignment && (r.TreatmentGeneration != 1 || r.TreatmentAppliedTimestampNs != 1700000000e9) { + t.Fatalf("generation/applied not stamped: %d %d", r.TreatmentGeneration, r.TreatmentAppliedTimestampNs) + } + if r.AgentId != "host" || r.Location != "dc" || r.HostBootId != "boot" || r.CollectionId != "session" || r.TreatmentStateRevision != 1 { + t.Fatal("collection identity missing") + } + }) + } +} + +func TestStampIdentityModes(t *testing.T) { + for _, tc := range []struct { + name, description string + index func() *Index + wantLocation string + wantAgent string + wantRevision uint64 + }{ + {"embedded", "positive: the embedded agent replaces the record location with the certificate-bound one", func() *Index { s, _ := fixture(1); return Build(s, testIdentity, true) }, "dc", "host", 1}, + {"attribution", "positive: a telemetry-only daemon keeps its own location label", func() *Index { s, _ := fixture(1); return Build(s, testIdentity, false) }, "daemon-dc", "host", 1}, + {"identity-only", "boundary: before the first reconcile pass only identity is stamped", func() *Index { return Build(nil, testIdentity, true) }, "dc", "host", 0}, + {"nil", "corner: with no index at all the record is left as an observation-only producer", func() *Index { return nil }, "daemon-dc", "", 0}, + } { + t.Run(tc.name, func(t *testing.T) { + _, r := fixture(1) + r.AgentId, r.HostBootId, r.CollectionId, r.TreatmentAssignmentId = "stale", "stale", "stale", "stale" + x := tc.index() + x.Stamp(r) + if r.Location != tc.wantLocation || r.AgentId != tc.wantAgent || r.TreatmentStateRevision != tc.wantRevision { + t.Fatalf("%s: location=%q agent=%q revision=%d", tc.description, r.Location, r.AgentId, r.TreatmentStateRevision) + } + if tc.wantAgent == "" && (r.HostBootId != "" || r.CollectionId != "") { + t.Fatal("nil index left stale identity") + } + if x != nil && x.Routes() != len(x.routes) || tc.wantRevision == 1 && (x.Routes() != 1 || x.Held() || x.Identity() != testIdentity) { + t.Fatalf("%s: accessors disagree", tc.description) + } + if r.TreatmentAssignmentId != "" && tc.wantRevision == 0 { + t.Fatal("attributed without routes") + } + }) + } +} + +// Publish swaps immutable indexes while socket workers stamp concurrently. +func TestStamperConcurrentPublish(t *testing.T) { + s, _ := fixture(16) + var st Stamper + st.Publish(Build(s, testIdentity, true)) + var wg sync.WaitGroup + wg.Go(func() { + for i := range 200 { + next := s.Clone() + next.Desired.Revision = uint64(i + 2) + st.Publish(Build(next, testIdentity, true)) + } + }) + for range 8 { + wg.Go(func() { + _, r := fixture(0) + for range 200 { + st.Stamp(r) + if r.TreatmentAssignmentId != "assignment-0" || !r.TreatmentAlgorithmExposed || r.TreatmentStateRevision == 0 { + t.Error("inconsistent exposure snapshot") + return + } + } + }) + } + wg.Wait() + if st.Current().Revision() != 201 { + t.Fatalf("last publish not visible: %d", st.Current().Revision()) + } + var empty Stamper + _, r := fixture(0) + empty.Stamp(r) + if empty.Current() != nil || r.AgentId != "" { + t.Fatal("unpublished stamper must behave as nil index") + } +} + +func BenchmarkStamp(b *testing.B) { + for _, n := range []int{1, 100, 4096} { + for _, match := range []bool{true, false} { + b.Run(fmt.Sprintf("routes=%d/match=%t", n, match), func(b *testing.B) { + s, r := fixture(n) + x := Build(s, testIdentity, true) + if !match { + r.InetDiagMsgSocketDestination = []byte{198, 51, 100, 1} + } + b.ReportAllocs() + for b.Loop() { + x.Stamp(r) + } + if r.TreatmentAlgorithmExposed != match { + b.Fatal("wrong exposure") + } + }) + } + } +} + +func BenchmarkBuild(b *testing.B) { + for _, n := range []int{1, 100, 4096} { + b.Run(fmt.Sprint(n), func(b *testing.B) { + s, _ := fixture(n) + b.ReportAllocs() + for b.Loop() { + Build(s, testIdentity, true) + } + }) + } +} diff --git a/pkg/treatment/attribution/watch.go b/pkg/treatment/attribution/watch.go new file mode 100644 index 000000000..988655efc --- /dev/null +++ b/pkg/treatment/attribution/watch.go @@ -0,0 +1,268 @@ +package attribution + +import ( + "errors" + "fmt" + "log" + "os" + "path/filepath" + "sync" + "time" + "unsafe" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" + "golang.org/x/sys/unix" +) + +// WatchConfig tells a Watcher where the standalone agent writes its journal. +type WatchConfig struct { + // Dir is the journal directory (local.Config.Directory of the agent). + Dir string + // Location is this daemon's own telemetry label. When it is set the + // journal's location is never written onto records and a difference is + // logged once. When it is empty (no -location/LOCATION) the journal's + // location is adopted so evidence queries can find the host. + Location string + // Poll bounds staleness when inotify is unavailable, the directory does + // not exist yet or an event was missed. Zero means 30s. + Poll time.Duration + // NetnsInode is the namespace the agent's routes live in. Zero means this + // process's own namespace, which is right whenever daemon and agent run + // in the host namespace, as the agent requires. + NetnsInode uint64 + // Log receives diagnostics; nil means log.Printf. + Log func(format string, args ...any) +} + +// Watcher feeds a Stamper from a journal directory written by another +// process. It reads the snapshot without the journal lock (the file is +// replaced atomically), on an inotify event for the snapshot's name, on +// Wake, and on the poll interval as a fallback. A missing or invalid +// snapshot publishes a nil index: with no trustworthy journal there is no +// agent to speak for, and the daemon degrades to an observation-only +// producer rather than attributing from stale state. +type Watcher struct { + cfg WatchConfig + stamper *Stamper + wake chan struct{} + mu sync.Mutex + lastModTime time.Time + lastSize int64 + lastErr string + warnedFor string + // warnedUnbound is set once a journal without a collection nonce has + // been logged, so the warning is not repeated on every refresh. + warnedUnbound bool +} + +// NewWatcher validates the configuration and resolves the namespace. It +// does not read the journal; Run or Refresh does. +func NewWatcher(cfg WatchConfig, s *Stamper) (*Watcher, error) { + if cfg.Dir == "" || s == nil { + return nil, errors.New("attribution: journal directory and stamper are required") + } + if cfg.Poll <= 0 { + cfg.Poll = 30 * time.Second + } + if cfg.Log == nil { + cfg.Log = log.Printf + } + if cfg.NetnsInode == 0 { + var st unix.Stat_t + if err := unix.Stat("/proc/self/ns/net", &st); err != nil { + return nil, fmt.Errorf("attribution: network namespace: %w", err) + } + cfg.NetnsInode = st.Ino + } + return &Watcher{cfg: cfg, stamper: s, wake: make(chan struct{}, 1)}, nil +} + +// Wake asks Run to re-read the snapshot now; concurrent wakes coalesce. +func (w *Watcher) Wake() { + select { + case w.wake <- struct{}{}: + default: + } +} + +// Refresh re-reads the snapshot and publishes the resulting index. force +// re-reads even when size and modification time are unchanged. The error +// is the load failure, if any; it is also logged once per distinct message. +func (w *Watcher) Refresh(force bool) error { + w.mu.Lock() + defer w.mu.Unlock() + path := filepath.Join(w.cfg.Dir, reconcile.SnapshotFile) + info, err := os.Lstat(path) + if err == nil && !force && info.ModTime().Equal(w.lastModTime) && info.Size() == w.lastSize && w.stamper.Current() != nil { + return nil + } + if err != nil { + w.lastModTime, w.lastSize = time.Time{}, 0 + w.stamper.Publish(nil) + if errors.Is(err, os.ErrNotExist) { + w.note("") + return nil + } + w.note(err.Error()) + return err + } + s, err := reconcile.ReadSnapshot(w.cfg.Dir) + if err != nil { + w.lastModTime, w.lastSize = time.Time{}, 0 + w.stamper.Publish(nil) + w.note(err.Error()) + return err + } + w.lastModTime, w.lastSize = info.ModTime(), info.Size() + w.note("") + if s.Location != "" && w.cfg.Location != "" && s.Location != w.cfg.Location && w.warnedFor != s.Location { + w.warnedFor = s.Location + w.cfg.Log("treatment attribution: journal location %q differs from this daemon's -location %q; records keep %q", s.Location, w.cfg.Location, w.cfg.Location) + } + adoptLocation := w.cfg.Location == "" + if adoptLocation && s.Location != "" && w.warnedFor != s.Location { + w.warnedFor = s.Location + w.cfg.Log("treatment attribution: this daemon has no -location; records take the journal's %q", s.Location) + } + if s.CollectionID == "" && !w.warnedUnbound { + w.warnedUnbound = true + w.cfg.Log("treatment attribution: the journal carries no collection nonce; records are stamped without one and the controller will not count them as evidence until the agent rewrites the journal") + } + // The nonce is the agent's, read from the journal, so the controller + // can bind these records to the session the agent reported. + w.stamper.Publish(Build(s, Identity{AgentID: s.AgentID, Location: s.Location, BootID: s.BootID, CollectionID: s.CollectionID, NetnsInode: w.cfg.NetnsInode}, adoptLocation)) + return nil +} + +// refreshRetryCst bounds the poll interval while the journal is unreadable. +const refreshRetryCst = 5 * time.Second + +// pollAfter is the wait before the next unprompted refresh: the configured +// period, or sooner while the last refresh failed so a journal that becomes +// readable again is noticed without waiting a full period. Refresh has +// already logged the failure once. +func (w *Watcher) pollAfter(lastErr error) time.Duration { + if lastErr != nil { + return min(w.cfg.Poll, refreshRetryCst) + } + return w.cfg.Poll +} + +// note logs a load failure once per distinct message and a recovery once. +func (w *Watcher) note(msg string) { + if msg == w.lastErr { + return + } + if msg == "" { + w.cfg.Log("treatment attribution: journal %s readable again", w.cfg.Dir) + } else { + w.cfg.Log("treatment attribution: %s; records are not attributed until the journal is valid", msg) + } + w.lastErr = msg +} + +// Run watches until ctx is done. It never returns an error: attribution is +// best effort and a broken watch degrades to polling. +func (w *Watcher) Run(ctx interface { + Done() <-chan struct{} + Err() error +}) { + refreshed := w.Refresh(true) + fd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK) + if err != nil { + w.cfg.Log("treatment attribution: inotify unavailable (%v); polling every %s", err, w.cfg.Poll) + fd = -1 + } else { + defer func() { + if cerr := unix.Close(fd); cerr != nil { + w.cfg.Log("treatment attribution: inotify close: %v", cerr) + } + }() + } + watching := false + addWatch := func() { + if fd < 0 || watching { + return + } + _, err := unix.InotifyAddWatch(fd, w.cfg.Dir, unix.IN_MOVED_TO|unix.IN_CLOSE_WRITE|unix.IN_CREATE|unix.IN_DELETE|unix.IN_DELETE_SELF|unix.IN_MOVE_SELF|unix.IN_ONLYDIR) + watching = err == nil + } + addWatch() + buf := make([]byte, 64<<10) + timer := time.NewTimer(w.pollAfter(refreshed)) + defer timer.Stop() + events := make(chan bool, 1) // true: the snapshot changed; false: the directory itself went away + if fd >= 0 { + go w.readEvents(ctx, fd, buf, events) + } + for { + select { + case <-ctx.Done(): + return + case <-w.wake: + refreshed = w.Refresh(true) + case changed := <-events: + if !changed { + watching = false + } + refreshed = w.Refresh(true) + case <-timer.C: + addWatch() + refreshed = w.Refresh(false) + } + if !timer.Stop() { + select { + case <-timer.C: + default: + } + } + timer.Reset(w.pollAfter(refreshed)) + } +} + +// readEvents turns inotify events for the snapshot into notifications. +func (w *Watcher) readEvents(ctx interface{ Err() error }, fd int, buf []byte, events chan<- bool) { + for ctx.Err() == nil { + p := []unix.PollFd{{Fd: int32(fd), Events: unix.POLLIN}} + if _, err := unix.Poll(p, 1000); err != nil && err != unix.EINTR { + return + } + if p[0].Revents == 0 { + continue + } + n, err := unix.Read(fd, buf) + if err == unix.EAGAIN || err == unix.EINTR { + continue + } + if err != nil { + return + } + changed, gone := false, false + for off := 0; off+unix.SizeofInotifyEvent <= n; { + ev := (*unix.InotifyEvent)(unsafe.Pointer(&buf[off])) + nameLen := int(ev.Len) + name := "" + if nameLen > 0 && off+unix.SizeofInotifyEvent+nameLen <= n { + name = unix.ByteSliceToString(buf[off+unix.SizeofInotifyEvent : off+unix.SizeofInotifyEvent+nameLen]) + } + switch { + case ev.Mask&(unix.IN_DELETE_SELF|unix.IN_MOVE_SELF|unix.IN_IGNORED) != 0: + gone = true + case ev.Mask&unix.IN_Q_OVERFLOW != 0 || name == reconcile.SnapshotFile: + changed = true + } + off += unix.SizeofInotifyEvent + nameLen + } + if gone { + select { + case events <- false: + default: + } + } else if changed { + select { + case events <- true: + default: + } + } + } +} diff --git a/pkg/treatment/attribution/watch_test.go b/pkg/treatment/attribution/watch_test.go new file mode 100644 index 000000000..05e15f202 --- /dev/null +++ b/pkg/treatment/attribution/watch_test.go @@ -0,0 +1,230 @@ +package attribution + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strings" + "sync" + "testing" + "time" + + flat "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" +) + +// writeJournal commits a snapshot the way the agent does: under the lock, +// by atomic rename. +func writeJournal(t *testing.T, dir string, s *reconcile.State) { + t.Helper() + err := reconcile.Journal{Dir: dir}.WithLock(context.Background(), func(cur *reconcile.State, save func() error) error { + *cur = *s + return save() + }) + if err != nil { + t.Fatal(err) + } +} + +func verifiedState(revision uint64) *reconcile.State { + now := time.Unix(1700000000, 0) + d := fixtures.Desired(now) + d.Revision = revision + d.Assignments[0].Mode = treatment.ModeStable + d.Assignments[0].LeaseExpiresAt = time.Time{} + return &reconcile.State{AgentID: "host-1", Location: "dc1", BootID: "boot-1", CollectionID: fixtures.CollectionID, Desired: d, Records: []reconcile.Record{{ApplicationRecord: treatment.ApplicationRecord{Assignment: d.Assignments[0], Status: treatment.ApplyVerified, AppliedAt: now, DesiredRevision: revision}, InstalledRoute: []byte{1}, InstalledBootID: "boot-1"}}} +} + +func record() *flat.XtcpFlatRecord { + return &flat.XtcpFlatRecord{Location: "dc1", NetnsInode: 7, InetDiagMsgFamily: 2, InetDiagMsgSocketDestination: []byte{192, 0, 2, 1}, InetDiagCong: "cubic"} +} + +type logSink struct { + mu sync.Mutex + lines []string +} + +func (l *logSink) printf(format string, args ...any) { + l.mu.Lock() + defer l.mu.Unlock() + l.lines = append(l.lines, fmt.Sprintf(format, args...)) +} + +func (l *logSink) count(sub string) int { + l.mu.Lock() + defer l.mu.Unlock() + n := 0 + for _, v := range l.lines { + if strings.Contains(v, sub) { + n++ + } + } + return n +} + +func eventually(t *testing.T, what string, fn func() bool) { + t.Helper() + deadline := time.Now().Add(5 * time.Second) + for time.Now().Before(deadline) { + if fn() { + return + } + time.Sleep(10 * time.Millisecond) + } + t.Fatalf("%s: condition not met within 5s", what) +} + +func TestWatcherRefreshContracts(t *testing.T) { + for _, tc := range []struct { + name, description string + prepare func(t *testing.T, dir string) + wantErr string + wantAgent string + wantAssignment string + wantLogged string + daemonLocation string + wantLocation string + wantCollection string + }{ + {"journal", "positive: a committed journal attributes records with the journal's agent, nonce and the daemon's location", func(t *testing.T, dir string) { writeJournal(t, dir, verifiedState(3)) }, "", "host-1", "trial-1", "", "dc1", "dc1", fixtures.CollectionID}, + {"missing-file", "negative: no snapshot yet means identity is not invented", func(*testing.T, string) {}, "", "", "", "", "dc1", "dc1", ""}, + {"missing-dir", "negative: a directory that does not exist yet is not an error", func(t *testing.T, dir string) { + if err := os.RemoveAll(dir); err != nil { + t.Fatal(err) + } + }, "", "", "", "", "dc1", "dc1", ""}, + {"corrupt", "negative: an invalid snapshot clears attribution and is logged", func(t *testing.T, dir string) { + if err := os.WriteFile(filepath.Join(dir, reconcile.SnapshotFile), []byte("nonsense {"), 0600); err != nil { + t.Fatal(err) + } + }, "invalid treatment journal", "", "", "not attributed", "dc1", "dc1", ""}, + {"held", "boundary: a journal under a hold stamps identity but no treatment", func(t *testing.T, dir string) { + s := verifiedState(4) + s.LocallySuspended = true + writeJournal(t, dir, s) + }, "", "host-1", "", "", "dc1", "dc1", fixtures.CollectionID}, + {"location-mismatch", "corner: a journal from another location keeps the daemon's label and warns once", func(t *testing.T, dir string) { + s := verifiedState(5) + s.Location = "elsewhere" + writeJournal(t, dir, s) + }, "", "host-1", "trial-1", "differs from this daemon", "dc1", "dc1", fixtures.CollectionID}, + {"adopt-location", "corner: a daemon without its own -location takes the journal's so evidence queries can find it", func(t *testing.T, dir string) { + s := verifiedState(6) + s.Location = "journal-dc" + writeJournal(t, dir, s) + }, "", "host-1", "trial-1", "records take the journal's", "", "journal-dc", fixtures.CollectionID}, + {"no-nonce", "boundary: a journal written before the agent owned a nonce stamps none and warns once", func(t *testing.T, dir string) { + s := verifiedState(7) + s.CollectionID = "" + writeJournal(t, dir, s) + }, "", "host-1", "trial-1", "carries no collection nonce", "dc1", "dc1", ""}, + } { + t.Run(tc.name, func(t *testing.T) { + dir := t.TempDir() + tc.prepare(t, dir) + var sink logSink + var st Stamper + w, err := NewWatcher(WatchConfig{Dir: dir, Location: tc.daemonLocation, NetnsInode: 7, Log: sink.printf}, &st) + if err != nil { + t.Fatal(err) + } + err = w.Refresh(true) + if tc.wantErr == "" && err != nil || tc.wantErr != "" && (err == nil || !strings.Contains(err.Error(), tc.wantErr)) { + t.Fatalf("%s: refresh error %v, want %q", tc.description, err, tc.wantErr) + } + r := record() + st.Stamp(r) + if r.AgentId != tc.wantAgent || r.TreatmentAssignmentId != tc.wantAssignment || r.Location != tc.wantLocation { + t.Fatalf("%s: agent=%q assignment=%q location=%q", tc.description, r.AgentId, r.TreatmentAssignmentId, r.Location) + } + if tc.wantAgent != "" && r.HostBootId != "boot-1" || r.CollectionId != tc.wantCollection { + t.Fatalf("%s: boot/collection not stamped: %+v", tc.description, r) + } + // A second refresh logs nothing new: errors and warnings are once per cause. + _ = w.Refresh(true) + if tc.wantLogged != "" && sink.count(tc.wantLogged) != 1 { + t.Fatalf("%s: expected one log line containing %q, got %v", tc.description, tc.wantLogged, sink.lines) + } + if tc.wantLogged == "" && sink.count("not attributed")+sink.count("differs")+sink.count("collection nonce") != 0 { + t.Fatalf("%s: unexpected log lines %v", tc.description, sink.lines) + } + }) + } + if _, err := NewWatcher(WatchConfig{}, nil); err == nil { + t.Fatal("empty configuration accepted") + } +} + +func TestWatcherFollowsRenames(t *testing.T) { + dir := t.TempDir() + writeJournal(t, dir, verifiedState(1)) + var st Stamper + w, err := NewWatcher(WatchConfig{Dir: dir, NetnsInode: 7, Poll: time.Hour, Log: func(string, ...any) {}}, &st) + if err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + done := make(chan struct{}) + go func() { defer close(done); w.Run(ctx) }() + revision := func() uint64 { + r := record() + st.Stamp(r) + return r.TreatmentStateRevision + } + eventually(t, "initial load", func() bool { return revision() == 1 }) + // Atomic rename of a new snapshot: the inotify path, with the hour-long + // poll ruling out the fallback. + writeJournal(t, dir, verifiedState(2)) + eventually(t, "rename picked up", func() bool { return revision() == 2 }) + // Removal clears attribution. + if err := os.Remove(filepath.Join(dir, reconcile.SnapshotFile)); err != nil { + t.Fatal(err) + } + eventually(t, "removal picked up", func() bool { return st.Current() == nil }) + // Re-creation restores it. + writeJournal(t, dir, verifiedState(3)) + eventually(t, "re-creation picked up", func() bool { return revision() == 3 }) + // A change that leaves size and mtime identical is still visible on Wake. + w.Wake() + eventually(t, "wake refreshes", func() bool { return revision() == 3 }) + cancel() + <-done +} + +func TestWatcherPollsWhenDirectoryAppearsLater(t *testing.T) { + parent := t.TempDir() + dir := filepath.Join(parent, "routes") + var st Stamper + w, err := NewWatcher(WatchConfig{Dir: dir, NetnsInode: 7, Poll: 20 * time.Millisecond, Log: func(string, ...any) {}}, &st) + if err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + done := make(chan struct{}) + go func() { defer close(done); w.Run(ctx) }() + time.Sleep(50 * time.Millisecond) + if st.Current() != nil { + t.Fatal("index published before any journal existed") + } + writeJournal(t, dir, verifiedState(9)) + eventually(t, "late directory", func() bool { + r := record() + st.Stamp(r) + return r.TreatmentStateRevision == 9 && r.AgentId == "host-1" + }) + // The directory now exists, so the watch is added on the next poll and + // a rename is seen even if polling were slow. + writeJournal(t, dir, verifiedState(10)) + eventually(t, "post-attach rename", func() bool { + r := record() + st.Stamp(r) + return r.TreatmentStateRevision == 10 + }) + cancel() + <-done +} diff --git a/pkg/treatment/boundaries_test.go b/pkg/treatment/boundaries_test.go new file mode 100644 index 000000000..27ce940c8 --- /dev/null +++ b/pkg/treatment/boundaries_test.go @@ -0,0 +1,318 @@ +package treatment + +import ( + "go/build" + "go/parser" + "go/token" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + "testing" +) + +// The treatment feature is split by audience, and the split only means +// something if it is enforced. This test walks first-party imports with the +// parser (no toolchain, no module cache, works outside nix exactly like +// internal/goip/imports_test.go) and asserts the layering below. +// +// pkg/treatment domain types, limits, validators: proto-free [everyone] +// pkg/treatment/wire domain <-> generated proto conversion [gRPC boundary] +// pkg/treatment/identity SPIFFE identity + TLS [agent, controller, tools] +// pkg/treatment/reconcile journal (xtcp_treatment_journal.v1) + reconciler + Backend; no RPC proto, no gRPC [agent, watchdog] +// pkg/treatment/local host config + goip-backed reconciler; no TLS, no gRPC [agent, watchdog, treatmentctl] +// pkg/treatment/attribution ExposureIndex + telemetry stamping from a journal snapshot [daemon, agent] +// pkg/treatment/experiment statistics + state machine, pure [controller] +// pkg/treatment/agent check-in loop + watch over local + attribution [daemon (treatment tag), agent binary] +// pkg/treatment/controller gRPC handlers over store and evidence ports [controller binary only] +// pkg/treatment/controller/store ports; postgres/ and memory/ implement them [controller] +// pkg/treatment/controller/evidence warehouse ports; clickhouse/ implements them [controller] +// +// The daemon (cmd/xtcp2) must never reach the controller, a SQL driver or the +// ClickHouse client: that was the regression that prompted this file. +const ( + modulePath = "github.com/randomizedcoder/xtcp2" + repoRoot = "../.." +) + +// boundaryRule is one root whose transitive first-party closure must not +// contain any forbidden package, and whose third-party edges must not match +// any forbidden substring. +type boundaryRule struct { + description string + root string + tags []string // build tags in effect for the walk; files excluded by //go:build are skipped + forbidden []string // first-party package paths + forbidden3p []string // substrings of third-party import paths + expectAny []string // first-party packages that must be present, so the walk is not vacuous +} + +func treatmentBoundaryRules() []boundaryRule { + tp := func(p string) string { return modulePath + "/" + p } + return []boundaryRule{ + { + description: "positive: the untagged daemon reads journals only: no agent, no TLS identity, no RPC proto, no controller, no SQL driver, no ClickHouse", + root: tp("cmd/xtcp2"), + forbidden: []string{tp("pkg/treatment/agent"), tp("pkg/treatment/identity"), tp("pkg/treatment/local"), tp("pkg/treatment/wire"), tp("gen/go/xtcp_treatment"), tp("pkg/treatment/controller"), tp("pkg/treatment/experiment")}, + forbidden3p: []string{"database/sql", "jackc/pgx", "clickhouse"}, + expectAny: []string{tp("pkg/xtcp"), tp("pkg/treatment/attribution")}, + }, + { + description: "positive: the daemon built with the treatment tag embeds the agent but still never the controller, a SQL driver or ClickHouse", + root: tp("cmd/xtcp2"), + tags: []string{"treatment"}, + forbidden: []string{tp("pkg/treatment/controller"), tp("pkg/treatment/experiment")}, + forbidden3p: []string{"database/sql", "jackc/pgx", "clickhouse"}, + expectAny: []string{tp("pkg/xtcp"), tp("pkg/treatment/agent"), tp("pkg/treatment/identity")}, + }, + { + description: "positive: the standalone agent binary stands on the agent library, never on the controller or a database", + root: tp("cmd/xtcp2-treatment-agent"), + forbidden: []string{tp("pkg/treatment/controller"), tp("pkg/treatment/experiment"), tp("pkg/xtcp")}, + forbidden3p: []string{"database/sql", "jackc/pgx", "clickhouse"}, + expectAny: []string{tp("pkg/treatment/agent"), tp("pkg/treatment/local"), tp("pkg/treatment/attribution")}, + }, + { + description: "positive: the agent library stands on identity and the contract, never on the controller", + root: tp("pkg/treatment/agent"), + forbidden: []string{tp("pkg/treatment/controller"), tp("pkg/treatment/experiment")}, + forbidden3p: []string{"database/sql", "jackc/pgx"}, + expectAny: []string{tp("pkg/treatment/identity"), tp("pkg/treatment")}, + }, + { + description: "positive: the domain package is proto-free and depends on nothing first-party", + root: tp("pkg/treatment"), + forbidden: []string{tp("gen/go/xtcp_treatment"), tp("pkg/treatment/wire"), tp("pkg/treatment/identity"), tp("pkg/treatment/controller")}, + forbidden3p: []string{"google.golang.org/protobuf", "google.golang.org/grpc", "database/sql"}, + expectAny: []string{tp("pkg/treatment")}, + }, + { + description: "negative: the identity package is a leaf below the domain and gRPC credentials, never the proto", + root: tp("pkg/treatment/identity"), + forbidden: []string{tp("gen/go/xtcp_treatment"), tp("pkg/treatment/wire"), tp("pkg/treatment/controller"), tp("pkg/treatment/agent")}, + forbidden3p: []string{"database/sql"}, + expectAny: []string{tp("pkg/treatment")}, + }, + { + // TODO(flat-record stubs): also forbid google.golang.org/grpc here + // and for pkg/treatment/local. Today pkg/xtcpnl imports + // gen/go/xtcp_flat_record, whose Go package carries the gRPC and + // gateway stubs of that proto, so every goip user links gRPC + // through the netlink library. The treatment packages themselves + // are clean: the reconcile rule below forbids gRPC. + description: "boundary: the watchdog never reaches the controller, a database, TLS identity, the agent or the RPC proto", + root: tp("cmd/xtcp2-treatmentctl"), + forbidden: []string{tp("pkg/treatment/controller"), tp("pkg/treatment/identity"), tp("pkg/treatment/agent"), tp("pkg/treatment/attribution"), tp("pkg/treatment/wire"), tp("pkg/treatment/experiment"), tp("gen/go/xtcp_treatment")}, + forbidden3p: []string{"database/sql", "jackc/pgx", "clickhouse", "google.golang.org/grpc/credentials"}, + expectAny: []string{tp("pkg/treatment"), tp("pkg/treatment/local"), tp("pkg/treatment/reconcile")}, + }, + { + description: "positive: the reconcile package is host-side only: journal proto and domain, never the RPC proto, gRPC, identity, goip or experiment statistics", + root: tp("pkg/treatment/reconcile"), + forbidden: []string{tp("pkg/treatment/identity"), tp("pkg/treatment/experiment"), tp("pkg/treatment/agent"), tp("pkg/treatment/controller"), tp("pkg/treatment/wire"), tp("gen/go/xtcp_treatment"), tp("internal/goip")}, + forbidden3p: []string{"database/sql", "google.golang.org/grpc"}, + expectAny: []string{tp("pkg/treatment"), tp("gen/go/xtcp_treatment_journal")}, + }, + { + description: "positive: the local package builds the kernel-backed reconciler on the goip actuator, without TLS or the RPC proto", + root: tp("pkg/treatment/local"), + forbidden: []string{tp("pkg/treatment/identity"), tp("pkg/treatment/agent"), tp("pkg/treatment/attribution"), tp("pkg/treatment/controller"), tp("pkg/treatment/experiment"), tp("pkg/treatment/wire"), tp("gen/go/xtcp_treatment")}, + forbidden3p: []string{"database/sql", "google.golang.org/grpc/credentials"}, + expectAny: []string{tp("pkg/treatment/reconcile"), tp("internal/goip/actuate"), tp("internal/goip")}, + }, + { + description: "positive: attribution reads journal snapshots and the flat record; never identity, goip, the agent or the RPC proto", + root: tp("pkg/treatment/attribution"), + forbidden: []string{tp("pkg/treatment/identity"), tp("pkg/treatment/agent"), tp("pkg/treatment/local"), tp("pkg/treatment/controller"), tp("pkg/treatment/experiment"), tp("pkg/treatment/wire"), tp("gen/go/xtcp_treatment"), tp("internal/goip")}, + forbidden3p: []string{"database/sql", "jackc/pgx"}, + expectAny: []string{tp("pkg/treatment/reconcile"), tp("gen/go/xtcp_flat_record")}, + }, + { + description: "positive: the experiment package is pure: no proto, no gRPC, no journal, no identity, no syscalls", + root: tp("pkg/treatment/experiment"), + forbidden: []string{tp("gen/go/xtcp_treatment"), tp("pkg/treatment/wire"), tp("pkg/treatment/reconcile"), tp("pkg/treatment/identity"), tp("pkg/treatment/agent"), tp("pkg/treatment/controller")}, + forbidden3p: []string{"google.golang.org/protobuf", "google.golang.org/grpc", "database/sql", "golang.org/x/sys"}, + expectAny: []string{tp("pkg/treatment")}, + }, + { + description: "positive: the store ports and the memory store know no driver and no proto", + root: tp("pkg/treatment/controller/store/memory"), + forbidden: []string{tp("gen/go/xtcp_treatment"), tp("pkg/treatment/wire"), tp("pkg/treatment/controller"), tp("pkg/treatment/controller/store/postgres")}, + forbidden3p: []string{"database/sql", "jackc/pgx", "google.golang.org/protobuf", "google.golang.org/grpc"}, + expectAny: []string{tp("pkg/treatment/controller/store"), tp("pkg/treatment")}, + }, + { + description: "corner: every SQL string lives in the postgres package, which never reaches the handlers", + root: tp("pkg/treatment/controller/store/postgres"), + forbidden: []string{tp("pkg/treatment/controller"), tp("pkg/treatment/wire"), tp("gen/go/xtcp_treatment"), tp("pkg/treatment/experiment")}, + expectAny: []string{tp("pkg/treatment/controller/store")}, + }, + { + description: "negative: the controller never reaches the host-side reconcile, local or attribution packages, goip or the journal proto", + root: tp("pkg/treatment/controller"), + forbidden: []string{tp("pkg/treatment/reconcile"), tp("pkg/treatment/local"), tp("pkg/treatment/attribution"), tp("internal/goip"), tp("gen/go/xtcp_treatment_journal")}, + expectAny: []string{tp("pkg/treatment/experiment")}, + }, + { + description: "corner: the controller never imports the agent (the dependency points one way)", + root: tp("pkg/treatment/controller"), + forbidden: []string{tp("pkg/treatment/agent"), tp("internal/goip")}, + expectAny: []string{tp("pkg/treatment/identity")}, + }, + { + description: "negative: the controller depends on the evidence port, never on the ClickHouse adapter (main wires the adapter)", + root: tp("pkg/treatment/controller"), + forbidden: []string{tp("pkg/treatment/controller/evidence/clickhouse")}, + expectAny: []string{tp("pkg/treatment/controller/evidence")}, + }, + { + description: "boundary: the evidence port is a leaf over the contract: no controller, no store, no proto, no HTTP client", + root: tp("pkg/treatment/controller/evidence"), + forbidden: []string{tp("pkg/treatment/controller"), tp("pkg/treatment/controller/store"), tp("pkg/treatment/wire"), tp("gen/go/xtcp_treatment"), tp("pkg/treatment/experiment")}, + forbidden3p: []string{"net/http", "database/sql"}, + expectAny: []string{tp("pkg/treatment")}, + }, + { + description: "corner: the ClickHouse adapter implements the port and knows nothing of the controller, store, wire types or proto", + root: tp("pkg/treatment/controller/evidence/clickhouse"), + forbidden: []string{tp("pkg/treatment/controller"), tp("pkg/treatment/controller/store"), tp("pkg/treatment/wire"), tp("gen/go/xtcp_treatment"), tp("pkg/treatment/experiment")}, + forbidden3p: []string{"database/sql", "google.golang.org/grpc"}, + expectAny: []string{tp("pkg/treatment/controller/evidence")}, + }, + } +} + +// go test ./pkg/treatment -run TestTreatmentImportBoundaries +func TestTreatmentImportBoundaries(t *testing.T) { + for _, r := range treatmentBoundaryRules() { + t.Run(r.description, func(t *testing.T) { + closure, thirdParty := firstPartyClosure(t, r.root, r.tags) + for _, p := range r.forbidden { + if closure[p] { + t.Errorf("%s reaches %s; the chain is: %s", r.root, p, importChain(t, r.root, p, r.tags)) + } + } + for imp, from := range thirdParty { + for _, bad := range r.forbidden3p { + if strings.Contains(imp+"\"", bad) { + t.Errorf("%s reaches third-party %q via %s", r.root, imp, from) + } + } + } + for _, p := range r.expectAny { + if !closure[p] { + t.Errorf("%s no longer reaches %s; the walk may be vacuous, update expectAny if intentional", r.root, p) + } + } + }) + } +} + +type anImport struct{ path, file string } + +// packageImports lists the non-test imports of one package under the given +// build tags, honoring //go:build lines and _GOOS/_GOARCH suffixes the way +// the compiler would for the host platform, so a file such as +// cmd/xtcp2/treatments_embedded.go (//go:build treatment) only counts when +// the rule asks for that tag. +func packageImports(t *testing.T, pkgPath string, tags []string) []anImport { + t.Helper() + dir := filepath.Join(repoRoot, strings.TrimPrefix(pkgPath, modulePath+"/")) + entries, err := os.ReadDir(dir) + if err != nil { + t.Fatalf("read package dir %s (for import %q): %v", dir, pkgPath, err) + } + ctx := build.Default + ctx.BuildTags = append([]string(nil), tags...) + var out []anImport + fset := token.NewFileSet() + for _, e := range entries { + if e.IsDir() || !strings.HasSuffix(e.Name(), ".go") || strings.HasSuffix(e.Name(), "_test.go") { + continue + } + if ok, merr := ctx.MatchFile(dir, e.Name()); merr != nil { + t.Fatalf("match %s: %v", filepath.Join(dir, e.Name()), merr) + } else if !ok { + continue + } + path := filepath.Join(dir, e.Name()) + f, perr := parser.ParseFile(fset, path, nil, parser.ImportsOnly|parser.SkipObjectResolution) + if perr != nil { + t.Fatalf("parse %s: %v", path, perr) + } + for _, spec := range f.Imports { + imp, uerr := strconv.Unquote(spec.Path.Value) + if uerr != nil { + t.Fatalf("%s: unquote import %s: %v", path, spec.Path.Value, uerr) + } + out = append(out, anImport{path: imp, file: path}) + } + } + return out +} + +func isFirstParty(imp string) bool { + return imp == modulePath || strings.HasPrefix(imp, modulePath+"/") +} + +// firstPartyClosure follows non-test first-party imports from root and returns +// the packages reached plus third-party edges mapped to one importer. +func firstPartyClosure(t *testing.T, root string, tags []string) (map[string]bool, map[string]string) { + t.Helper() + closure := map[string]bool{} + thirdParty := map[string]string{} + var walk func(string) + walk = func(p string) { + if closure[p] { + return + } + closure[p] = true + for _, imp := range packageImports(t, p, tags) { + switch { + case isFirstParty(imp.path): + walk(imp.path) + case !strings.Contains(strings.SplitN(imp.path, "/", 2)[0], "."): + // stdlib: only database/sql is interesting, record it as a third-party edge. + if imp.path == "database/sql" { + thirdParty[imp.path] = p + } + default: + if _, seen := thirdParty[imp.path]; !seen { + thirdParty[imp.path] = p + } + } + } + } + walk(root) + return closure, thirdParty +} + +// importChain finds one path root -> ... -> target so a failure says where the +// edge came from instead of only that it exists. +func importChain(t *testing.T, root, target string, tags []string) string { + t.Helper() + parent := map[string]string{root: ""} + queue := []string{root} + for len(queue) > 0 { + p := queue[0] + queue = queue[1:] + if p == target { + var chain []string + for q := p; q != ""; q = parent[q] { + chain = append(chain, strings.TrimPrefix(q, modulePath+"/")) + } + sort.SliceStable(chain, func(i, j int) bool { return i > j }) + return strings.Join(chain, " -> ") + } + for _, imp := range packageImports(t, p, tags) { + if isFirstParty(imp.path) { + if _, seen := parent[imp.path]; !seen { + parent[imp.path] = p + queue = append(queue, imp.path) + } + } + } + } + return "(no chain found)" +} diff --git a/pkg/treatment/controller/analyze.go b/pkg/treatment/controller/analyze.go new file mode 100644 index 000000000..e9696d820 --- /dev/null +++ b/pkg/treatment/controller/analyze.go @@ -0,0 +1,86 @@ +package controller + +import ( + "context" + "errors" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/experiment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// Analyze refreshes evidence for review without accepting or promoting it. +// Warehouse work stays outside the transaction; the revision fence rejects +// evidence computed across an intervening operator decision. +func (s *Server) Analyze(ctx context.Context, r *pb.AnalyzeRequest) (*pb.AnalyzeResponse, error) { + actor, e := identity.Operator(ctx) + if e != nil { + return nil, e + } + if !treatment.ValidID(r.ExperimentId) { + return nil, status.Error(codes.InvalidArgument, "invalid experiment ID") + } + if s.EvidenceSource == nil { + return nil, status.Error(codes.Unavailable, "evidence analysis is disabled: no warehouse configured") + } + var n *treatment.Experiment + e = s.Store.Tx(ctx, func(rp store.Repos) error { + var e error + n, e = rp.Experiments.Get(ctx, r.ExperimentId) + if e != nil { + return e + } + if n.Revision != r.ExpectedRevision { + return errors.New("experiment revision changed") + } + if n.Status == treatment.StatusRunning { + return s.startObservation(ctx, rp, n) + } + return nil + }) + if e != nil { + return nil, failure(e) + } + input := n + if n.Status == treatment.StatusComplete { + input = s.driftInput(n) + } + ev, e := s.boundEvidence(ctx, s.EvidenceSource, evidence.WindowFor(input, s.now())) + if e != nil { + return nil, failure(e) + } + outcome := treatment.OutcomeBaseline + if len(n.Phases) > 0 { + v, e := experiment.Evaluate(input, ev, s.now()) + if e != nil { + return nil, failure(e) + } + outcome = v.Outcome + } + out := &pb.AnalyzeResponse{Evidence: wire.Evidence(ev), Outcome: wire.Outcome(outcome)} + e = s.Store.Tx(ctx, func(rp store.Repos) error { + current, e := rp.Experiments.Get(ctx, n.ID) + if e != nil { + return e + } + if current.Revision != r.ExpectedRevision { + return errors.New("experiment changed during analysis; analyze again") + } + if e = saveEvidence(ctx, rp, n.ID, ev); e != nil { + return e + } + current.LatestEvidence = ev + current.LatestOutcome = outcome + if e = s.save(ctx, rp, current); e != nil { + return e + } + return audit(ctx, rp, actor, "", "analysis", out) + }) + return out, failure(e) +} diff --git a/pkg/treatment/controller/auth.go b/pkg/treatment/controller/auth.go new file mode 100644 index 000000000..add8d17b0 --- /dev/null +++ b/pkg/treatment/controller/auth.go @@ -0,0 +1,65 @@ +package controller + +import ( + "fmt" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" +) + +// serviceFiles are the proto files whose services the controller serves. +var serviceFiles = []protoreflect.FileDescriptor{pb.File_xtcp_treatment_v1_agent_proto, pb.File_xtcp_treatment_v1_operator_proto} + +// RolePolicy derives the per-RPC authorization table from the +// (xtcp_treatment.v1.role) option on every method of the served services. +// A method declared without a role (or ROLE_UNSPECIFIED) is left out of the +// policy, and the interceptor then refuses it for everyone; TestRolePolicy +// fails the build's test run if that ever happens, so the declaration is +// the single place a new RPC's audience is decided. +func RolePolicy() identity.Policy { + p := identity.Policy{} + for _, f := range serviceFiles { + services := f.Services() + for i := 0; i < services.Len(); i++ { + sd := services.Get(i) + methods := sd.Methods() + for j := 0; j < methods.Len(); j++ { + m := methods.Get(j) + name := fmt.Sprintf("/%s/%s", sd.FullName(), m.Name()) + role, ok := proto.GetExtension(m.Options(), pb.E_Role).(pb.Role) + if !ok { + continue + } + switch role { + case pb.Role_ROLE_AGENT: + p[name] = identity.RoleAgent + case pb.Role_ROLE_OPERATOR: + p[name] = identity.RoleOperator + case pb.Role_ROLE_UNSPECIFIED: + // Left out of the policy, so the interceptors deny the method + // and the coverage test names it. + } + } + } + } + return p +} + +// GRPCOptions are the server options every controller listener uses: the +// authorization interceptors over RolePolicy and the message bounds. The +// caller adds transport credentials; without mTLS the interceptors refuse +// every call as unauthenticated. +func GRPCOptions() []grpc.ServerOption { + p := RolePolicy() + return []grpc.ServerOption{ + grpc.ChainUnaryInterceptor(p.UnaryInterceptor()), + grpc.ChainStreamInterceptor(p.StreamInterceptor()), + grpc.MaxRecvMsgSize(treatment.MaxStateBytes), + grpc.MaxSendMsgSize(treatment.MaxStateBytes), + grpc.MaxConcurrentStreams(8), + } +} diff --git a/pkg/treatment/controller/auth_test.go b/pkg/treatment/controller/auth_test.go new file mode 100644 index 000000000..052cdb5a5 --- /dev/null +++ b/pkg/treatment/controller/auth_test.go @@ -0,0 +1,107 @@ +package controller + +import ( + "context" + "strings" + "testing" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// servedMethods lists every RPC the controller registers, from the generated +// service descriptors, so a new RPC is covered the moment it exists. +func servedMethods() map[string]bool { + out := map[string]bool{} + for _, sd := range []grpc.ServiceDesc{pb.AgentControlService_ServiceDesc, pb.OperatorService_ServiceDesc} { + for _, m := range sd.Methods { + out["/"+sd.ServiceName+"/"+m.MethodName] = false + } + for _, s := range sd.Streams { + out["/"+sd.ServiceName+"/"+s.StreamName] = true + } + } + return out +} + +// go test ./pkg/treatment/controller -run TestRolePolicy +func TestRolePolicy(t *testing.T) { + policy := RolePolicy() + served := servedMethods() + if len(served) == 0 { + t.Fatal("no served methods found") + } + for method := range served { + role, ok := policy[method] + if !ok { + t.Errorf("%s has no (xtcp_treatment.v1.role) declaration; the interceptor refuses it for everyone", method) + continue + } + want := identity.RoleOperator + if strings.HasPrefix(method, "/xtcp_treatment.v1.AgentControlService/") { + want = identity.RoleAgent + } + if role != want { + t.Errorf("%s declares %s, expected %s: agents must never reach operator RPCs and vice versa", method, role, want) + } + } + for method := range policy { + if _, ok := served[method]; !ok { + t.Errorf("policy names %s, which no served service has", method) + } + } +} + +// TestEveryMethodAgainstEveryRole is the exhaustive matrix: each served +// method is attempted with an agent certificate, an operator certificate +// and no certificate, and only the declared role may reach the handler. +func TestEveryMethodAgainstEveryRole(t *testing.T) { + policy := RolePolicy() + callers := []struct { + description string + ctx context.Context + role identity.Role + }{ + {"agent certificate", testIdentity("agent/dc1/host"), identity.RoleAgent}, + {"operator certificate", testIdentity("operator/alice"), identity.RoleOperator}, + {"no certificate", context.Background(), ""}, + } + for method, stream := range servedMethods() { + for _, c := range callers { + t.Run(method+"/"+c.description, func(t *testing.T) { + expected := codes.PermissionDenied + if c.role == "" { + expected = codes.Unauthenticated + } else if policy[method] == c.role { + expected = codes.OK + } + reached := false + var err error + if stream { + err = policy.StreamInterceptor()(nil, &desiredTestStream{ctx: c.ctx}, &grpc.StreamServerInfo{FullMethod: method}, func(any, grpc.ServerStream) error { reached = true; return nil }) + } else { + // A request with no agent fields so only the role decides. + _, err = policy.UnaryInterceptor()(c.ctx, struct{}{}, &grpc.UnaryServerInfo{FullMethod: method}, func(context.Context, any) (any, error) { reached = true; return nil, nil }) + } + if status.Code(err) != expected || reached != (expected == codes.OK) { + t.Fatalf("%s with %s: err=%v reached=%t expected %v", method, c.description, err, reached, expected) + } + }) + } + } +} + +func TestGRPCOptionsCarryInterceptors(t *testing.T) { + // The options must at least construct a server; the interceptor behavior + // itself is covered above and by the identity package's mTLS test. + s := grpc.NewServer(GRPCOptions()...) + defer s.Stop() + pb.RegisterAgentControlServiceServer(s, &Server{}) + pb.RegisterOperatorServiceServer(s, &Server{}) + if len(s.GetServiceInfo()) != 2 { + t.Fatalf("services registered: %d", len(s.GetServiceInfo())) + } +} diff --git a/pkg/treatment/controller/bind.go b/pkg/treatment/controller/bind.go new file mode 100644 index 000000000..719c79c15 --- /dev/null +++ b/pkg/treatment/controller/bind.go @@ -0,0 +1,43 @@ +package controller + +import ( + "context" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" +) + +// sessionSlack widens the session lookup beyond the window on both sides. A +// known session's LastSeen is refreshed only every store.SessionRefresh, and +// a new session is first seen at the check-in after the agent starts, so +// records near either edge may belong to a session the store places just +// outside the window. +const sessionSlack = store.SessionRefresh + 5*time.Minute + +// sessionRetention keeps sessions for longer than the longest window any +// evidence query may cover. +const sessionRetention = evidence.MaxWindow + 24*time.Hour + +// boundWindow attaches the sessions the population reported over mTLS, so +// the warehouse measures only records stamped with one of them and counts +// the rest as unbound. +func (s *Server) boundWindow(ctx context.Context, w evidence.Window) (evidence.Window, error) { + sessions, err := s.Store.Repos().Agents.Sessions(ctx, w.Agents, w.Start.Add(-sessionSlack), w.End.Add(sessionSlack)) + if err != nil { + return w, err + } + w.Sessions = sessions + return w, nil +} + +// boundEvidence measures w through source, bound to the population's +// sessions. +func (s *Server) boundEvidence(ctx context.Context, source evidence.Source, w evidence.Window) (*treatment.Evidence, error) { + w, err := s.boundWindow(ctx, w) + if err != nil { + return nil, err + } + return source.Evidence(ctx, w) +} diff --git a/pkg/treatment/controller/bind_test.go b/pkg/treatment/controller/bind_test.go new file mode 100644 index 000000000..d6c183654 --- /dev/null +++ b/pkg/treatment/controller/bind_test.go @@ -0,0 +1,82 @@ +package controller + +import ( + "context" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "google.golang.org/protobuf/proto" +) + +// capturingSource returns fixed evidence and records the windows it saw. +type capturingSource struct { + value *treatment.Evidence + windows []evidence.Window +} + +func (c *capturingSource) Evidence(_ context.Context, w evidence.Window) (*treatment.Evidence, error) { + c.windows = append(c.windows, w) + return c.value, nil +} + +// TestEvidenceWindowsCarrySessions: every evidence window the controller +// asks for names the sessions its population reported, so the warehouse can +// drop records stamped by anyone else; housekeeping prunes old sessions. +func TestEvidenceWindowsCarrySessions(t *testing.T) { + const restarted = "fedcba9876543210fedcba9876543210" + for _, tc := range []struct { + name, description string + prepare func(t *testing.T, s *Server, now *time.Time) + expected int // sessions in the analysis window + }{ + {"one-each", "positive: each cohort host contributes the session it checked in with", func(*testing.T, *Server, *time.Time) {}, 8}, + {"restart", "positive: a host that restarted mid-window contributes both sessions", func(t *testing.T, s *Server, now *time.Time) { + *now = now.Add(time.Minute) + c := capabilities() + c.CollectionId = restarted + if _, e := s.CheckIn(testIdentity("agent/dc1/host-0"), &pb.CheckInRequest{AgentId: "host-0", Location: "dc1", Capabilities: c}); e != nil { + t.Fatal(e) + } + }, 9}, + {"pruned", "corner: sessions older than the retention are pruned and no longer bind evidence", func(t *testing.T, s *Server, now *time.Time) { + *now = now.Add(sessionRetention + time.Hour) + if _, e := s.Housekeep(context.Background(), nil, nil, nil); e != nil { + t.Fatal(e) + } + }, 0}, + } { + t.Run(tc.name, func(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC().Truncate(time.Microsecond) + s := testServer(st, &now) + operator := testIdentity("operator/alice") + enrollFleet(t, s, 8) + p := proposal(now) + if _, e := s.Propose(operator, p); e != nil { + t.Fatal(e) + } + tc.prepare(t, s, &now) + ev := proto.Clone(p.Experiment.Baseline).(*pb.Evidence) + ev.Id = "bound-1" + source := &capturingSource{value: parseEvidence(t, ev)} + s.EvidenceSource = source + // Analysis outlives a pruned population too; only the window matters here. + _, _ = s.Analyze(operator, &pb.AnalyzeRequest{ExperimentId: p.Experiment.Id, ExpectedRevision: 1}) + if len(source.windows) != 1 { + t.Fatalf("%s: expected one window, got %d", tc.description, len(source.windows)) + } + w := source.windows[0] + if len(w.Sessions) != tc.expected { + t.Fatalf("%s: window carries %d sessions, want %d: %+v", tc.description, len(w.Sessions), tc.expected, w.Sessions) + } + if err := w.Validate(); err != nil { + t.Fatalf("%s: bound window invalid: %v", tc.description, err) + } + }) + }) + } +} diff --git a/pkg/treatment/controller/discovery.go b/pkg/treatment/controller/discovery.go new file mode 100644 index 000000000..93e2543a6 --- /dev/null +++ b/pkg/treatment/controller/discovery.go @@ -0,0 +1,207 @@ +package controller + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "net/netip" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" +) + +// DiscoveryTemplate authorizes candidate discovery for one location. Templates +// only authorize discovery: every generated hypothesis and every increase in +// exposure still requires an authenticated operator review. +type DiscoveryTemplate struct { + ID string `json:"id"` + Location string `json:"location"` + CongestionControl string `json:"congestion_control"` + RtoMinMs *uint32 `json:"rto_min_ms,omitempty"` + InitialCongestionWindow *uint32 `json:"initial_congestion_window,omitempty"` + InitialReceiveWindow *uint32 `json:"initial_receive_window,omitempty"` + QuickAck *bool `json:"quick_ack,omitempty"` + MaximumRTTIncrease *float64 `json:"maximum_rtt_increase,omitempty"` + MinimumRTTMs float64 `json:"minimum_rtt_ms"` + MaximumRTTMs float64 `json:"maximum_rtt_ms"` + MinimumRetransmissionRatio float64 `json:"minimum_retransmission_ratio"` + ASNs []uint64 `json:"asns"` + Prefixes []string `json:"prefixes"` +} + +func (t DiscoveryTemplate) policy() treatment.Policy { + p := treatment.DefaultPolicy() + if t.MaximumRTTIncrease != nil { + p.MaximumRTTIncrease = *t.MaximumRTTIncrease + } + return p +} + +// inScope applies the template's ASN and prefix allow-lists; an empty list +// allows everything. +func (t DiscoveryTemplate) inScope(c evidence.Candidate, prefixes []netip.Prefix) bool { + if len(t.ASNs) > 0 { + match := false + for _, a := range t.ASNs { + match = match || a == c.ASN + } + if !match { + return false + } + } + if len(prefixes) > 0 { + match := false + for _, p := range prefixes { + match = match || p.Contains(c.Destination.Addr()) + } + if !match { + return false + } + } + return true +} + +func (t DiscoveryTemplate) settings() treatment.TCPSettings { + cc := t.CongestionControl + return treatment.TCPSettings{ + CongestionControl: &cc, + RTOMinMs: t.RtoMinMs, + InitialCongestionWindow: t.InitialCongestionWindow, + InitialReceiveWindow: t.InitialReceiveWindow, + QuickAck: t.QuickAck, + } +} + +// Discover scans each template's location for candidate destinations, takes +// a baseline for each and proposes a hypothesis. Proposals stay in +// StatusProposed until an operator reviews them. Templates are validated +// before the warehouse is touched; a busy location is skipped without a scan. +func (s *Server) Discover(ctx context.Context, w evidence.Warehouse, templates []DiscoveryTemplate) error { + window := s.DiscoveryWindow + if window == 0 { + window = time.Hour + } + if window < time.Minute || window > evidence.MaxWindow { + return errors.New("discovery window must be between one minute and seven days") + } + if w == nil { + return errors.New("candidate discovery requires a warehouse") + } + var failures []error + for i := range templates { + t := &templates[i] + if !treatment.ValidID(t.ID) || !treatment.ValidID(t.Location) || (t.CongestionControl != "cubic" && t.CongestionControl != "bbr") || t.MaximumRTTMs <= t.MinimumRTTMs || t.MinimumRTTMs < 0 || t.MinimumRetransmissionRatio < 0 || t.MinimumRetransmissionRatio > 1 { + return errors.New("invalid discovery template; initial discovery supports CUBIC/BBR only") + } + if err := treatment.ValidateTCPSettings(t.settings(), false); err != nil { + return fmt.Errorf("discovery template %s: %w", t.ID, err) + } + if err := treatment.ValidatePolicy(t.policy()); err != nil { + return fmt.Errorf("discovery template %s policy: %w", t.ID, err) + } + var prefixes []netip.Prefix + for _, v := range t.Prefixes { + p, e := netip.ParsePrefix(v) + if e != nil { + return e + } + prefixes = append(prefixes, p) + } + // Avoid warehouse aggregation while this location cannot accept a + // new experiment. The transaction below still rechecks the budget. + busy, e := s.Store.Repos().Experiments.HasActive(ctx, t.Location) + if e != nil { + failures = append(failures, e) + continue + } + if busy { + continue + } + end := s.now().Add(-evidence.SettleDelay) + start := end.Add(-window) + candidates, e := w.Candidates(ctx, evidence.CandidateQuery{Location: t.Location, Start: start, End: end, MinimumRTTMs: t.MinimumRTTMs, MaximumRTTMs: t.MaximumRTTMs, MinimumRetransmissionRatio: t.MinimumRetransmissionRatio}) + if e != nil { + failures = append(failures, e) + continue + } + enrolled, e := s.enrolled(ctx, t.Location) + if e != nil { + failures = append(failures, e) + continue + } + for _, c := range candidates { + if !t.inScope(c, prefixes) { + continue + } + stop, e := s.discoverCandidate(ctx, w, t, c, enrolled, start, end) + if e != nil { + failures = append(failures, e) + } + if stop { + break + } + } + } + return errors.Join(failures...) +} + +// discoverCandidate measures one in-scope candidate's enrolled hosts and +// proposes it. stop reports that the location took (or refused) a proposal, +// so the template's remaining candidates wait for the next pass. +func (s *Server) discoverCandidate(ctx context.Context, w evidence.Warehouse, t *DiscoveryTemplate, c evidence.Candidate, enrolled map[string]bool, start, end time.Time) (stop bool, err error) { + // Completed or held treatments and recent rejected trials suppress + // repeat proposals. Cooldown is at least a day after terminal state. + exists, err := s.Store.Repos().Experiments.DestinationBlocked(ctx, t.Location, c.Destination, s.now().Add(-24*time.Hour)) + if err != nil || exists { + return false, err + } + // Only enrolled agents report sessions, so only they can carry bound + // evidence or receive an assignment. + cohort := enrolledIn(c.Agents, enrolled) + if len(cohort) < treatment.MinimumCohort { + return false, nil + } + seed := sha256.Sum256([]byte(t.ID + "/" + c.Destination.String() + "/" + s.now().UTC().Format("2006-01-02"))) + id := "hyp-" + hex.EncodeToString(seed[:12]) + baseline, err := s.boundEvidence(ctx, w, evidence.Window{Location: t.Location, Destination: c.Destination, ExperimentID: id, Agents: cohort, Start: start, End: end}) + if err != nil { + return false, err + } + n := &treatment.Experiment{ID: id, Location: t.Location, Hypothesis: fmt.Sprintf("Template %s: test %s for %s (ASN %d), observed RTT %.3f ms and retransmission ratio %.6f; this is a hypothesis, not an efficacy claim", t.ID, t.CongestionControl, c.Destination, c.ASN, c.RTTMs, c.RetransmissionRatio), Treatment: treatment.Treatment{ID: t.ID, Revision: 1, Destination: c.Destination, Settings: t.settings()}, Policy: t.policy(), Baseline: baseline, CohortOrder: cohort} + if _, err = s.propose(ctx, &pb.ProposeRequest{Experiment: wire.Experiment(n), RequestId: id}, "candidate-discovery", true); err != nil { + if errors.Is(err, errExperimentBudget) || errors.Is(err, errDiscoverySuppressed) { + err = nil + } + return true, err + } + return false, nil +} + +// enrolled returns the IDs of the agents enrolled in location. +func (s *Server) enrolled(ctx context.Context, location string) (map[string]bool, error) { + refs, err := s.Store.Repos().Agents.List(ctx, location) + if err != nil { + return nil, err + } + out := make(map[string]bool, len(refs)) + for _, r := range refs { + out[r.ID] = true + } + return out, nil +} + +// enrolledIn keeps the candidate agents that are enrolled, in order. +func enrolledIn(agents []string, enrolled map[string]bool) []string { + out := make([]string, 0, len(agents)) + for _, a := range agents { + if enrolled[a] { + out = append(out, a) + } + } + return out +} diff --git a/pkg/treatment/controller/discovery_contracts_test.go b/pkg/treatment/controller/discovery_contracts_test.go new file mode 100644 index 000000000..6dae3e1cc --- /dev/null +++ b/pkg/treatment/controller/discovery_contracts_test.go @@ -0,0 +1,170 @@ +package controller + +import ( + "context" + "errors" + "fmt" + "net/netip" + "sync" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres" + "google.golang.org/protobuf/proto" +) + +func TestDiscoveryScopeAndCooldown(t *testing.T) { + for _, tc := range []struct { + name, description string + asns []uint64 + prefixes []string + expected int + }{ + {"unfiltered", "positive: an eligible destination creates one reviewable proposal", nil, nil, 1}, + {"asn-match", "positive: a matching ASN permits discovery", []uint64{64512}, nil, 1}, + {"asn-miss", "negative: a foreign ASN is outside scope", []uint64{64513}, nil, 0}, + {"prefix-match", "positive: a matching destination prefix permits discovery", nil, []string{"192.0.2.0/24"}, 1}, + {"prefix-miss", "negative: a foreign destination prefix is outside scope", nil, []string{"198.51.100.0/24"}, 0}, + } { + t.Run(tc.name, func(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC().Truncate(time.Microsecond) + s := testServer(st, &now) + agents := make([]string, 0, 8) + for i := range 8 { + id := fmt.Sprintf("host-%d", i) + enroll(t, s, id) + agents = append(agents, id) + } + c := &fakeWarehouse{now: s.Now, candidates: []evidence.Candidate{{Destination: netip.MustParsePrefix("192.0.2.1/32"), ASN: 64512, Agents: agents, RTTMs: 5}}} + templates := []DiscoveryTemplate{{ID: "nearby", Location: "dc1", CongestionControl: "cubic", MaximumRTTMs: 15, ASNs: tc.asns, Prefixes: tc.prefixes}} + for range 2 { + if err := s.Discover(context.Background(), c, templates); err != nil { + t.Fatal(err) + } + } + found := experimentsOf(t, st) + if len(found) != tc.expected { + t.Fatalf("%s: proposals=%d expected %d", tc.description, len(found), tc.expected) + } + if len(found) == 0 { + return + } + if found[0].Status != treatment.StatusProposed { + t.Fatal("discovery started unreviewed experiment") + } + // A terminal destination stays suppressed for 24 hours, including + // across a controller restart (new Server, same store). + if _, err := s.Control(testIdentity("operator/alice"), &pb.ControlRequest{ExperimentId: found[0].ID, Action: pb.ControlAction_CONTROL_ACTION_ROLLBACK, Reason: "test", RequestId: "rollback-1"}); err != nil { + t.Fatal(err) + } + now = now.Add(23 * time.Hour) + restarted := &Server{Store: s.Store, Now: s.Now} + if err := restarted.Discover(context.Background(), c, templates); err != nil { + t.Fatal(err) + } + if n := len(experimentsOf(t, st)); n != 1 { + t.Fatalf("cooldown lost across restart: %d", n) + } + // After the cooldown the destination is eligible again once the + // cohort has checked in within the agent window. + now = now.Add(2 * time.Hour) + for _, id := range agents { + enroll(t, restarted, id) + } + if err := restarted.Discover(context.Background(), c, templates); err != nil { + t.Fatal(err) + } + if n := len(experimentsOf(t, st)); n != 2 { + t.Fatalf("destination not rediscovered after cooldown: %d", n) + } + }) + }) + } +} + +func TestDiscoverySkipsBusyLocation(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC() + seedExperiment(t, st, "active", "dc1", "192.0.2.9/32", treatment.StatusRunning, now) + s := testServer(st, &now) + ch := &fakeWarehouse{candidateErr: errors.New("warehouse must not be queried")} + templates := []DiscoveryTemplate{{ID: "nearby", Location: "dc1", CongestionControl: "cubic", MaximumRTTMs: 15}} + if err := s.Discover(context.Background(), ch, templates); err != nil || len(ch.queries) > 0 { + t.Fatalf("busy location queried warehouse: queries=%d err=%v", len(ch.queries), err) + } + pg, ok := st.(*postgres.Store) + if !ok { + return + } + if err := pg.Close(); err != nil { + t.Fatal(err) + } + if err := s.Discover(context.Background(), ch, templates); err == nil || len(ch.queries) > 0 { + t.Fatalf("database failure must stop discovery: queries=%d err=%v", len(ch.queries), err) + } + }) +} + +func TestDiscoveryTransactionFence(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC() + s := testServer(st, &now) + enrollFleet(t, s, 8) + // A stable treatment appears after discovery's initial lookup. + seedExperiment(t, st, "stable", "dc1", "192.0.2.1/32", treatment.StatusComplete, now) + if _, err := s.propose(context.Background(), proposal(now), "candidate-discovery", true); !errors.Is(err, errDiscoverySuppressed) { + t.Fatalf("transaction did not suppress newly stable destination: %v", err) + } + // Operator-driven replacement remains possible; assignment keeps the + // stable predecessor and still requires review before applying. + if _, err := s.Propose(testIdentity("operator/alice"), proposal(now)); err != nil { + t.Fatalf("explicit replacement was blocked: %v", err) + } + }) +} + +func TestConcurrentDiscoveryProposals(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC() + s := testServer(st, &now) + enrollFleet(t, s, 8) + start := make(chan struct{}) + results := make(chan error, 2) + var wg sync.WaitGroup + for i := range 2 { + wg.Go(func() { + r := proto.Clone(proposal(now)).(*pb.ProposeRequest) + r.RequestId = fmt.Sprintf("candidate-%d", i) + r.Experiment.Id = r.RequestId + <-start + _, err := s.propose(context.Background(), r, "candidate-discovery", true) + results <- err + }) + } + close(start) + wg.Wait() + close(results) + successes, suppressed := 0, 0 + for err := range results { + switch { + case err == nil: + successes++ + case errors.Is(err, errDiscoverySuppressed): + suppressed++ + default: + t.Fatal(err) + } + } + if successes != 1 || suppressed != 1 { + t.Fatalf("want one proposal and one suppressed competitor; got %d/%d", successes, suppressed) + } + if n := len(experimentsOf(t, st)); n != 1 { + t.Fatalf("duplicate persisted proposal: count=%d", n) + } + }) +} diff --git a/pkg/treatment/controller/discovery_test.go b/pkg/treatment/controller/discovery_test.go new file mode 100644 index 000000000..2f2baf8c6 --- /dev/null +++ b/pkg/treatment/controller/discovery_test.go @@ -0,0 +1,174 @@ +package controller + +import ( + "context" + "encoding/json" + "errors" + "math" + "net/netip" + "slices" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/memory" + "google.golang.org/protobuf/proto" +) + +func TestDiscoveryWindow(t *testing.T) { + now := time.Unix(1800000000, 0) + for _, tc := range []struct { + name, description string + window, want time.Duration + invalid bool + }{ + {"production-default", "positive: an unset window scans the last hour", 0, time.Hour, false}, + {"short-window", "boundary: one minute is the shortest scan", time.Minute, time.Minute, false}, + {"maximum", "boundary: seven days is the longest scan", 7 * 24 * time.Hour, 7 * 24 * time.Hour, false}, + {"negative", "negative: a negative window never reaches the warehouse", -time.Second, 0, true}, + {"too-short", "negative: under a minute is refused", 59 * time.Second, 0, true}, + {"too-long", "negative: over seven days is refused", 7*24*time.Hour + time.Second, 0, true}, + } { + t.Run(tc.name, func(t *testing.T) { + w := &fakeWarehouse{now: func() time.Time { return now }} + s := &Server{Store: memory.New(), Now: func() time.Time { return now }, DiscoveryWindow: tc.window} + err := s.Discover(context.Background(), w, []DiscoveryTemplate{{ID: "near", Location: "test-dc", CongestionControl: "cubic", MaximumRTTMs: 15}}) + if (err != nil) != tc.invalid || (len(w.queries) > 0) == tc.invalid { + t.Fatalf("%s: err=%v queries=%d invalid=%t", tc.description, err, len(w.queries), tc.invalid) + } + if tc.invalid { + return + } + wantEnd := now.Add(-evidence.SettleDelay) + q := w.queries[0] + if !q.End.Equal(wantEnd) || !q.Start.Equal(wantEnd.Add(-tc.want)) || q.Location != "test-dc" || q.MaximumRTTMs != 15 { + t.Fatalf("%s: wrong discovery bounds: %+v", tc.description, q) + } + }) + } +} + +func TestDiscoveryWarehouseFailures(t *testing.T) { + now := time.Unix(1800000000, 0) + agents := []string{"a", "b", "c", "d", "e", "f"} + candidate := evidence.Candidate{Destination: netip.MustParsePrefix("192.0.2.1/32"), ASN: 64512, Agents: agents, RTTMs: 5} + failing := func() *fakeWarehouse { + return &fakeWarehouse{candidates: []evidence.Candidate{candidate}, evidenceErr: errors.New("baseline timeout")} + } + for _, tc := range []struct { + name, description string + warehouse *fakeWarehouse + nilWarehouse bool + enrolled []string + wantErr string + wantWindows int + wantPopulation []string + }{ + {"candidates-fail", "negative: a failed scan is reported and takes no baseline", &fakeWarehouse{candidateErr: errors.New("warehouse offline")}, false, agents, "warehouse offline", 0, nil}, + {"baseline-fails", "negative: a failed baseline is reported and proposes nothing", failing(), false, agents, "baseline timeout", 1, agents}, + {"no-warehouse", "corner: discovery without a warehouse is a configuration error", nil, true, agents, "requires a warehouse", 0, nil}, + {"no-candidates", "boundary: an empty scan is not an error", &fakeWarehouse{}, false, agents, "", 0, nil}, + {"unenrolled", "negative: candidate hosts that never checked in take no baseline and are not an error", failing(), false, nil, "", 0, nil}, + {"two-enrolled", "boundary: fewer than three enrolled candidate hosts cannot form a cohort", failing(), false, agents[:2], "", 0, nil}, + {"three-enrolled", "corner: the baseline measures only the enrolled candidates, each with its session", failing(), false, []string{"a", "c", "f"}, "baseline timeout", 1, []string{"a", "c", "f"}}, + } { + t.Run(tc.name, func(t *testing.T) { + s := &Server{Store: memory.New(), Now: func() time.Time { return now }} + for _, id := range tc.enrolled { + enroll(t, s, id) + } + var w evidence.Warehouse + if !tc.nilWarehouse { + w = tc.warehouse + } + err := s.Discover(context.Background(), w, []DiscoveryTemplate{{ID: "near", Location: "dc1", CongestionControl: "cubic", MaximumRTTMs: 15}}) + if tc.wantErr == "" && err != nil || tc.wantErr != "" && (err == nil || !strings.Contains(err.Error(), tc.wantErr)) { + t.Fatalf("%s: err=%v want %q", tc.description, err, tc.wantErr) + } + if tc.warehouse != nil && len(tc.warehouse.windows) != tc.wantWindows { + t.Fatalf("%s: baseline windows=%d want %d", tc.description, len(tc.warehouse.windows), tc.wantWindows) + } + if tc.wantWindows > 0 { + win := tc.warehouse.windows[0] + if !slices.Equal(win.Agents, tc.wantPopulation) || len(win.Sessions) != len(tc.wantPopulation) { + t.Fatalf("%s: population %v with %d sessions, want %v with one session each", tc.description, win.Agents, len(win.Sessions), tc.wantPopulation) + } + } + if n := len(experimentsOf(t, s.Store)); n != 0 { + t.Fatalf("%s: proposals=%d", tc.description, n) + } + }) + } +} + +func TestDiscoveryRTTPolicy(t *testing.T) { + for _, tc := range []struct { + name string + limit *float64 + want float64 + invalid bool + }{ + {"production-default", nil, .1, false}, + {"zero", proto.Float64(0), 0, false}, + {"soak", proto.Float64(1), 1, false}, + {"negative", proto.Float64(-.1), 0, true}, + {"over-maximum", proto.Float64(1.01), 0, true}, + {"nan", proto.Float64(math.NaN()), 0, true}, + } { + t.Run(tc.name, func(t *testing.T) { + template := DiscoveryTemplate{ID: "near", Location: "test-dc", CongestionControl: "cubic", MaximumRTTMs: 15, MaximumRTTIncrease: tc.limit} + w := &fakeWarehouse{} + err := (&Server{Store: memory.New()}).Discover(context.Background(), w, []DiscoveryTemplate{template}) + if (err != nil) != tc.invalid || (len(w.queries) > 0) == tc.invalid { + t.Fatalf("err=%v queried=%d", err, len(w.queries)) + } + if tc.invalid { + return + } + want := treatment.DefaultPolicy() + want.MaximumRTTIncrease = tc.want + if template.policy() != want { + t.Fatalf("wrong policy: %+v", template.policy()) + } + }) + } +} + +func TestDiscoveryRouteSettings(t *testing.T) { + for _, tc := range []struct { + name, fields string + want treatment.TCPSettings + invalid bool + }{ + {"algorithm-only", "", treatment.TCPSettings{CongestionControl: proto.String("cubic")}, false}, + {"nearby", `,"rto_min_ms":5,"quick_ack":true,"initial_congestion_window":100,"initial_receive_window":100`, treatment.TCPSettings{CongestionControl: proto.String("cubic"), RTOMinMs: proto.Uint32(5), QuickAck: proto.Bool(true), InitialCongestionWindow: proto.Uint32(100), InitialReceiveWindow: proto.Uint32(100)}, false}, + {"explicit-off", `,"quick_ack":false`, treatment.TCPSettings{CongestionControl: proto.String("cubic"), QuickAck: proto.Bool(false)}, false}, + {"zero-rto", `,"rto_min_ms":0`, treatment.TCPSettings{}, true}, + {"large-rto", `,"rto_min_ms":120001`, treatment.TCPSettings{}, true}, + {"zero-cwnd", `,"initial_congestion_window":0`, treatment.TCPSettings{}, true}, + {"large-rwnd", `,"initial_receive_window":1025`, treatment.TCPSettings{}, true}, + } { + t.Run(tc.name, func(t *testing.T) { + var template DiscoveryTemplate + if err := json.Unmarshal([]byte(`{"id":"near","location":"test-dc","congestion_control":"cubic","maximum_rtt_ms":15`+tc.fields+`}`), &template); err != nil { + t.Fatal(err) + } + w := &fakeWarehouse{} + err := (&Server{Store: memory.New()}).Discover(context.Background(), w, []DiscoveryTemplate{template}) + if (err != nil) != tc.invalid || (len(w.queries) > 0) == tc.invalid { + t.Fatalf("err=%v queried=%d", err, len(w.queries)) + } + if tc.invalid { + return + } + if got := template.settings(); !got.Equal(tc.want) { + t.Fatalf("got %+v, want %+v", got, tc.want) + } + if err := treatment.ValidateTreatment(&treatment.Treatment{ID: template.ID, Revision: 1, Destination: netip.MustParsePrefix("192.0.2.1/32"), Settings: template.settings()}); err != nil { + t.Fatal(err) + } + }) + } +} diff --git a/pkg/treatment/controller/evidence/clickhouse/analysis.sql b/pkg/treatment/controller/evidence/clickhouse/analysis.sql new file mode 100644 index 000000000..0a47dcee5 --- /dev/null +++ b/pkg/treatment/controller/evidence/clickhouse/analysis.sql @@ -0,0 +1,45 @@ +-- Scheduled whole-window query: an incremental MV cannot correctly compute +-- cross-insert counter deltas. Deduplicate poll timestamps before differences. +-- A socket is bound when its (agent_id, host_boot_id, collection_id) is a +-- session the agent reported at check-in; only bound sockets are measured, +-- and unbound ones are counted so a reviewer sees spoofed or stale records. +WITH sockets AS ( + SELECT agent_id, host_boot_id, collection_id, netns_inode, inet_diag_msg_socket_cookie, + min(timestamp_ns) AS first_at, max(timestamp_ns) AS last_at, + countDistinct(timestamp_ns) AS samples, + argMin(tcp_info_bytes_acked,timestamp_ns) AS first_acked, + argMax(tcp_info_bytes_acked,timestamp_ns) AS last_acked, + argMin(tcp_info_bytes_sent,timestamp_ns) AS first_sent, + argMax(tcp_info_bytes_sent,timestamp_ns) AS last_sent, + argMin(tcp_info_bytes_retrans,timestamp_ns) AS first_retrans, + argMax(tcp_info_bytes_retrans,timestamp_ns) AS last_retrans, + quantileExact(0.5)(tcp_info_rtt)/1000 AS socket_rtt, + min(treatment_algorithm_exposed AND treatment_assignment_id={assignment:String}) AS exposed, + arrayMax(arrayDifference(arraySort(groupUniqArray(20000)(toUnixTimestamp64Nano(timestamp_ns))))) AS maximum_gap_ns + FROM {{TABLE}} + WHERE timestamp_ns >= fromUnixTimestamp64Nano({start:Int64}) + AND timestamp_ns < fromUnixTimestamp64Nano({end:Int64}) + AND location={location:String} AND agent_id IN {agents:Array(String)} + AND inet_diag_msg_state=1 + AND hex(inet_diag_msg_socket_destination)={destination_hex:String} + GROUP BY agent_id,host_boot_id,collection_id,netns_inode,inet_diag_msg_socket_cookie +), classified AS ( + SELECT *, has({sessions:Array(Tuple(String,String,String))}, (agent_id, host_boot_id, collection_id)) AS bound + FROM sockets +) +SELECT agent_id, + countIf(bound AND samples>=2) AS sockets, + sumIf(if(last_acked>=first_acked,last_acked-first_acked,0), bound) AS bytes_acked, + bytes_acked*8/(({end:Int64}-{start:Int64})/1e9) AS goodput_bps, + sumIf(if(last_retrans>=first_retrans,last_retrans-first_retrans,0), bound)/greatest(1,sumIf(if(last_sent>=first_sent,last_sent-first_sent,0), bound)) AS retransmission_ratio, + ifNotFinite(quantileExactIf(0.95)(socket_rtt, bound), 0) AS rtt_p95_ms, + countIf(bound AND samples>=2 AND exposed) AS exposed_sockets, + toBool(countIf(bound)>0 + AND maxIf(last_at, bound)>=fromUnixTimestamp64Nano({end:Int64}-30000000000) + AND maxIf(maximum_gap_ns, bound)<=30000000000 + AND countIf(bound AND (last_acked=2) AS unbound_sockets +FROM classified +GROUP BY agent_id +ORDER BY agent_id +FORMAT JSONEachRow diff --git a/pkg/treatment/controller/evidence/clickhouse/clickhouse.go b/pkg/treatment/controller/evidence/clickhouse/clickhouse.go new file mode 100644 index 000000000..5428ef321 --- /dev/null +++ b/pkg/treatment/controller/evidence/clickhouse/clickhouse.go @@ -0,0 +1,239 @@ +// Package clickhouse is the warehouse adapter: it implements evidence.Source +// and evidence.CandidateSource over the ClickHouse HTTP interface with two +// embedded, parameterized queries. It is the only package that knows the +// telemetry table's columns; the controller sees evidence.Window and +// evidence.Candidate. +package clickhouse + +import ( + "bytes" + "context" + "crypto/sha256" + _ "embed" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/netip" + "net/url" + "regexp" + "strconv" + "strings" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" +) + +//go:embed analysis.sql +var analysisSQL string + +//go:embed discovery.sql +var discoverySQL string + +var tableName = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*$`) + +// QueryVersion names the analysis query so evidence records which SQL +// produced them; bump it when analysis.sql changes meaning. +const QueryVersion = "tcp-host-deltas-v2-bound" + +// EnrichmentVersion names the telemetry schema the queries assume. +const EnrichmentVersion = "xtcp-schema-2" + +// Client talks to one ClickHouse HTTP(S) endpoint and one table. +type Client struct { + URL, Username, Password, Table string + HTTP *http.Client + Now func() time.Time +} + +var _ evidence.Warehouse = (*Client)(nil) + +func (c *Client) now() time.Time { + if c.Now != nil { + return c.Now() + } + return time.Now() +} + +// query POSTs one parameterized statement and returns the raw response. +// Parameters travel as ClickHouse `param_*` query parameters, never by +// string interpolation; the table name is validated before substitution. +func (c *Client) query(ctx context.Context, query string, params map[string]string) ([]byte, error) { + if !tableName.MatchString(c.Table) { + return nil, errors.New("ClickHouse table must be database.table") + } + u, e := url.Parse(c.URL) + if e != nil { + return nil, e + } + if u.Scheme != "http" && u.Scheme != "https" { + return nil, errors.New("ClickHouse URL must be HTTP(S)") + } + v := u.Query() + for k, val := range params { + v.Set("param_"+k, val) + } + v.Set("max_execution_time", "30") + v.Set("max_result_rows", "10000") + v.Set("result_overflow_mode", "throw") + v.Set("output_format_json_quote_64bit_integers", "0") + u.RawQuery = v.Encode() + body := strings.ReplaceAll(query, "{{TABLE}}", c.Table) + r, e := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(body)) + if e != nil { + return nil, e + } + r.SetBasicAuth(c.Username, c.Password) + client := c.HTTP + if client == nil { + client = &http.Client{Timeout: 35 * time.Second} + } + response, e := client.Do(r) + if e != nil { + return nil, e + } + defer response.Body.Close() + b, e := io.ReadAll(io.LimitReader(response.Body, 8<<20)) + if e != nil { + return nil, e + } + if len(b) >= 8<<20 { + return nil, errors.New("ClickHouse result exceeds 8 MiB") + } + if response.StatusCode != http.StatusOK { + return nil, fmt.Errorf("ClickHouse status %d: %.1024s", response.StatusCode, b) + } + return b, nil +} + +// hostRow is one JSONEachRow line of analysis.sql. +type hostRow struct { + AgentID string `json:"agent_id"` + Sockets uint64 `json:"sockets"` + BytesAcked uint64 `json:"bytes_acked"` + GoodputBps float64 `json:"goodput_bps"` + RetransmissionRatio float64 `json:"retransmission_ratio"` + RttP95Ms float64 `json:"rtt_p95_ms"` + ExposedSockets uint64 `json:"exposed_sockets"` + CollectionHealthy bool `json:"collection_healthy"` + UnboundSockets uint64 `json:"unbound_sockets"` +} + +// destinationHex renders an address the way the telemetry stores it: a +// 16-byte FixedString, IPv4 left-aligned and zero padded. +func destinationHex(a netip.Addr) string { + raw := a.AsSlice() + if a.Is4() { + raw = append(raw, make([]byte, 12)...) + } + return strings.ToUpper(hex.EncodeToString(raw)) +} + +// agentsParam renders an Array(String) literal. Quoting is safe only because +// Window.Validate has checked every ID against treatment.ValidID. +func agentsParam(agents []string) string { + quoted := make([]string, len(agents)) + for i, id := range agents { + quoted[i] = "'" + id + "'" + } + return "[" + strings.Join(quoted, ",") + "]" +} + +// sessionsParam renders an Array(Tuple(String,String,String)) literal of +// (agent_id, host_boot_id, collection_id), validated like agentsParam. +func sessionsParam(sessions []treatment.Session) string { + quoted := make([]string, len(sessions)) + for i, s := range sessions { + quoted[i] = "('" + s.AgentID + "','" + s.BootID + "','" + s.CollectionID + "')" + } + return "[" + strings.Join(quoted, ",") + "]" +} + +// Evidence runs analysis.sql for the window. ArtifactSHA256 is the digest of +// the raw response bytes as received; the response itself is not archived, +// so reproducing it means re-running QueryVersion over the same window. +func (c *Client) Evidence(ctx context.Context, w evidence.Window) (*treatment.Evidence, error) { + if e := w.Validate(); e != nil { + return nil, e + } + params := map[string]string{"start": strconv.FormatInt(w.Start.UnixNano(), 10), "end": strconv.FormatInt(w.End.UnixNano(), 10), "location": w.Location, "assignment": w.ExperimentID, "agents": agentsParam(w.Agents), "sessions": sessionsParam(w.Sessions), "destination_hex": destinationHex(w.Destination.Addr())} + b, e := c.query(ctx, analysisSQL, params) + if e != nil { + return nil, e + } + digest := sha256.Sum256(b) + sha := hex.EncodeToString(digest[:]) + analyzed := c.now() + v := &treatment.Evidence{ID: "ev-" + sha[:24] + "-" + strconv.FormatInt(analyzed.UnixNano(), 10), AnalyzedAt: analyzed, WindowStart: w.Start, WindowEnd: w.End, QueryVersion: QueryVersion, EnrichmentVersion: EnrichmentVersion, ArtifactSHA256: sha} + dec := json.NewDecoder(bytes.NewReader(b)) + for { + var h hostRow + e := dec.Decode(&h) + if e == io.EOF { + break + } + if e != nil { + return nil, e + } + v.Hosts = append(v.Hosts, treatment.HostEvidence(h)) + } + if e = treatment.ValidateEvidence(v); e != nil { + return nil, e + } + return v, nil +} + +// candidateRow is one JSONEachRow line of discovery.sql. +type candidateRow struct { + DestinationHex string `json:"destination_hex"` + Family uint32 `json:"family"` + ASN uint64 `json:"asn"` + Agents []string `json:"agents"` + RTT float64 `json:"rtt_ms"` + Retransmission float64 `json:"retransmission_ratio"` +} + +// Candidates runs discovery.sql. A row whose destination does not decode is +// an error, not a skipped row: it means the table is not the schema this +// adapter was written for. +func (c *Client) Candidates(ctx context.Context, q evidence.CandidateQuery) ([]evidence.Candidate, error) { + if e := q.Validate(); e != nil { + return nil, e + } + params := map[string]string{"location": q.Location, "start": strconv.FormatInt(q.Start.UnixNano(), 10), "end": strconv.FormatInt(q.End.UnixNano(), 10), "minimum_rtt": fmt.Sprint(q.MinimumRTTMs), "maximum_rtt": fmt.Sprint(q.MaximumRTTMs), "minimum_retransmission": fmt.Sprint(q.MinimumRetransmissionRatio)} + data, e := c.query(ctx, discoverySQL, params) + if e != nil { + return nil, e + } + var out []evidence.Candidate + dec := json.NewDecoder(bytes.NewReader(data)) + for { + var row candidateRow + if e = dec.Decode(&row); e == io.EOF { + return out, nil + } + if e != nil { + return nil, e + } + raw, e := hex.DecodeString(row.DestinationHex) + if e != nil { + return nil, fmt.Errorf("candidate destination %q: %w", row.DestinationHex, e) + } + if row.Family == 2 && len(raw) >= 4 { + raw = raw[:4] + } + ip, ok := netip.AddrFromSlice(raw) + if !ok { + return nil, fmt.Errorf("candidate destination %q: not an address for family %d", row.DestinationHex, row.Family) + } + for _, id := range row.Agents { + if !treatment.ValidID(id) { + return nil, fmt.Errorf("candidate %s: invalid agent id %q", ip, id) + } + } + out = append(out, evidence.Candidate{Destination: netip.PrefixFrom(ip, ip.BitLen()), ASN: row.ASN, Agents: row.Agents, RTTMs: row.RTT, RetransmissionRatio: row.Retransmission}) + } +} diff --git a/pkg/treatment/controller/evidence/clickhouse/clickhouse_test.go b/pkg/treatment/controller/evidence/clickhouse/clickhouse_test.go new file mode 100644 index 000000000..ea8eccf6a --- /dev/null +++ b/pkg/treatment/controller/evidence/clickhouse/clickhouse_test.go @@ -0,0 +1,327 @@ +package clickhouse + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/netip" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" +) + +type roundTripper func(*http.Request) (*http.Response, error) + +func (f roundTripper) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } + +type trackedBody struct { + io.Reader + closed bool +} + +func (b *trackedBody) Close() error { b.closed = true; return nil } + +type brokenReader struct{} + +func (brokenReader) Read([]byte) (int, error) { return 0, errors.New("broken response") } + +// fixture answers every query with body and records the request it saw. +func fixture(now time.Time, body string, saw func(*http.Request)) *Client { + return &Client{URL: "http://fixture.invalid", Table: "db.rows", Now: func() time.Time { return now }, HTTP: &http.Client{Transport: roundTripper(func(r *http.Request) (*http.Response, error) { + if saw != nil { + saw(r) + } + return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader(body)), Header: make(http.Header)}, nil + })}} +} + +func TestClickHouseTransportContracts(t *testing.T) { + for _, tc := range []struct { + name, description, table, url, body, wantError string + status int + transportError, readError bool + }{ + {name: "valid", description: "positive: query is parameterized and authenticated", status: 200, body: "ok"}, + {name: "table", description: "negative: table names cannot inject SQL", table: "db.rows;DROP TABLE rows", wantError: "database.table"}, + {name: "scheme", description: "negative: only HTTP(S) transports are accepted", url: "file:///tmp/rows", wantError: "HTTP(S)"}, + {name: "http-error", description: "negative: server errors are surfaced", status: 500, body: "query failed", wantError: "status 500"}, + {name: "network", description: "negative: transport errors are surfaced", transportError: true, wantError: "offline"}, + {name: "read", description: "corner: partial response errors fail analysis", status: 200, readError: true, wantError: "broken response"}, + {name: "size-limit", description: "boundary: oversized responses fail closed", status: 200, body: strings.Repeat("x", 8<<20), wantError: "exceeds"}, + } { + t.Run(tc.name, func(t *testing.T) { + table := tc.table + if table == "" { + table = "db.rows" + } + endpoint := tc.url + if endpoint == "" { + endpoint = "https://fixture.invalid/" + } + body := &trackedBody{Reader: strings.NewReader(tc.body)} + if tc.readError { + body.Reader = brokenReader{} + } + called := false + c := &Client{URL: endpoint, Table: table, Username: "user", Password: "test-secret", HTTP: &http.Client{Transport: roundTripper(func(r *http.Request) (*http.Response, error) { + called = true + if tc.transportError { + return nil, errors.New("offline") + } + u, p, ok := r.BasicAuth() + if !ok || u != "user" || p != "test-secret" { + t.Fatal("missing authentication") + } + query, err := io.ReadAll(r.Body) + if err != nil { + t.Fatal(err) + } + if string(query) != "SELECT * FROM db.rows" || r.Method != "POST" || r.URL.Query().Get("param_location") != "dc'quote" || r.URL.Query().Get("result_overflow_mode") != "throw" { + t.Fatal("query contract changed") + } + return &http.Response{StatusCode: tc.status, Body: body, Header: make(http.Header)}, nil + })}} + got, err := c.query(context.Background(), "SELECT * FROM {{TABLE}}", map[string]string{"location": "dc'quote"}) + if tc.wantError == "" { + if err != nil || string(got) != tc.body { + t.Fatalf("%s: %q %v", tc.description, got, err) + } + } else if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("%s: want %q got %v", tc.description, tc.wantError, err) + } + if called && !tc.transportError && !body.closed { + t.Fatal("response body leaked") + } + if (tc.table != "" || tc.url != "") && called { + t.Fatal("invalid configuration reached transport") + } + }) + } +} + +func TestClickHouseEvidenceContracts(t *testing.T) { + const host = `{"agent_id":"host","sockets":30,"bytes_acked":1048576,"goodput_bps":1000,"rtt_p95_ms":5,"collection_healthy":true}` + now := time.Unix(1700000000, 0) + for _, tc := range []struct { + name, description, body string + destination netip.Prefix + agents []string + window time.Duration + invalidDestination bool + // beforeQuery says the error must come from Window.Validate, so the + // warehouse is never contacted. + beforeQuery bool + wantError string + }{ + {name: "valid", description: "positive: complete response records provenance", body: host}, + {name: "empty", description: "negative: empty response cannot renew a lease", wantError: "population"}, + {name: "malformed", description: "negative: malformed JSON is rejected", body: "{", wantError: "EOF"}, + {name: "duplicate", description: "negative: duplicate hosts cannot inflate sample size", body: host + "\n" + host, wantError: "duplicate"}, + {name: "bad-window", description: "boundary: empty analysis interval is rejected", window: -time.Second, beforeQuery: true, wantError: "window"}, + {name: "long-window", description: "boundary: analysis is limited to seven days", window: evidence.MaxWindow + time.Second, beforeQuery: true, wantError: "window"}, + {name: "bad-agent", description: "negative: agent IDs cannot inject query parameters", agents: []string{"host'"}, beforeQuery: true, wantError: "invalid agent"}, + {name: "bad-destination", description: "corner: an invalid destination fails before the query", destination: netip.Prefix{}, invalidDestination: true, beforeQuery: true, wantError: "invalid destination"}, + } { + t.Run(tc.name, func(t *testing.T) { + window := tc.window + if window == 0 { + window = time.Minute + } + agents := tc.agents + if agents == nil { + agents = []string{"host"} + } + dest := tc.destination + if !tc.invalidDestination { + dest = netip.MustParsePrefix("192.0.2.1/32") + } + called := false + c := fixture(now, tc.body, func(r *http.Request) { + called = true + q := r.URL.Query() + if q.Get("param_destination_hex") != "C0000201000000000000000000000000" || q.Get("param_assignment") != "assignment" || q.Get("param_agents") != "['host']" { + t.Fatalf("wrong query parameters: %s", r.URL.RawQuery) + } + }) + ev, err := c.Evidence(context.Background(), evidence.Window{Location: "dc", Destination: dest, ExperimentID: "assignment", Agents: agents, Start: now.Add(-window), End: now}) + if tc.wantError != "" { + if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("%s: want %q got %v", tc.description, tc.wantError, err) + } + if tc.beforeQuery && called { + t.Fatalf("%s: invalid window reached the warehouse", tc.description) + } + return + } + if err != nil { + t.Fatal(err) + } + if len(ev.Hosts) != 1 || len(ev.ArtifactSHA256) != 64 || ev.QueryVersion != QueryVersion || ev.EnrichmentVersion != EnrichmentVersion || !ev.AnalyzedAt.Equal(now) || !ev.WindowEnd.Equal(now) { + t.Fatalf("%s: bad evidence %+v", tc.description, ev) + } + }) + } +} + +func TestClickHouseCandidateContracts(t *testing.T) { + now := time.Unix(1700000000, 0) + agents := `["h1","h2","h3","h4","h5","h6"]` + v4 := `{"destination_hex":"C0000201000000000000000000000000","family":2,"asn":64512,"agents":` + agents + `,"rtt_ms":5.5,"retransmission_ratio":0.01}` + v6 := `{"destination_hex":"20010DB8000000000000000000000001","family":10,"asn":64513,"agents":` + agents + `,"rtt_ms":80,"retransmission_ratio":0}` + for _, tc := range []struct { + name, description, body string + query evidence.CandidateQuery + want []string + wantASN uint64 + wantError string + }{ + {name: "v4", description: "positive: an IPv4 row decodes to a /32 with its population", body: v4, want: []string{"192.0.2.1/32"}, wantASN: 64512}, + {name: "v6", description: "positive: an IPv6 row decodes to a /128", body: v6, want: []string{"2001:db8::1/128"}, wantASN: 64513}, + {name: "ordered", description: "positive: rows keep the warehouse's best-first order", body: v6 + "\n" + v4, want: []string{"2001:db8::1/128", "192.0.2.1/32"}, wantASN: 64513}, + {name: "empty", description: "boundary: no rows is no candidates, not an error", body: ""}, + {name: "malformed", description: "negative: malformed JSON is an error", body: "{", wantError: "EOF"}, + {name: "bad-hex", description: "negative: an undecodable destination is a schema error, not a skipped row", body: `{"destination_hex":"ZZ","family":2,"agents":` + agents + `}`, wantError: "candidate destination"}, + {name: "short", description: "corner: too few bytes for the family is a schema error", body: `{"destination_hex":"C000","family":10,"agents":` + agents + `}`, wantError: "not an address"}, + {name: "bad-agent", description: "negative: an agent id that cannot be a parameter poisons the row", body: `{"destination_hex":"C0000201000000000000000000000000","family":2,"agents":["ok","bad'"]}`, wantError: "invalid agent id"}, + {name: "bad-bounds", description: "negative: inverted RTT bounds never reach the warehouse", body: v4, query: evidence.CandidateQuery{Location: "dc", Start: now.Add(-time.Hour), End: now, MinimumRTTMs: 10, MaximumRTTMs: 5}, wantError: "discovery bounds"}, + {name: "bad-window", description: "boundary: a window over seven days never reaches the warehouse", body: v4, query: evidence.CandidateQuery{Location: "dc", Start: now.Add(-evidence.MaxWindow - time.Second), End: now, MaximumRTTMs: 15}, wantError: "discovery window"}, + } { + t.Run(tc.name, func(t *testing.T) { + q := tc.query + if q.Location == "" { + q = evidence.CandidateQuery{Location: "dc", Start: now.Add(-time.Hour), End: now, MaximumRTTMs: 15} + } + called := false + c := fixture(now, tc.body, func(r *http.Request) { + called = true + p := r.URL.Query() + if p.Get("param_location") != "dc" || p.Get("param_maximum_rtt") != "15" || p.Get("param_minimum_rtt") != "0" { + t.Fatalf("wrong query parameters: %s", r.URL.RawQuery) + } + }) + got, err := c.Candidates(context.Background(), q) + if tc.wantError != "" { + if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("%s: want %q got %v", tc.description, tc.wantError, err) + } + if tc.query.Location != "" && called { + t.Fatalf("%s: invalid query reached the warehouse", tc.description) + } + return + } + if err != nil { + t.Fatalf("%s: %v", tc.description, err) + } + if len(got) != len(tc.want) { + t.Fatalf("%s: got %d candidates, want %d", tc.description, len(got), len(tc.want)) + } + for i, want := range tc.want { + if got[i].Destination.String() != want || len(got[i].Agents) != 6 { + t.Fatalf("%s: candidate %d = %+v, want %s", tc.description, i, got[i], want) + } + } + if len(got) > 0 && (got[0].ASN != tc.wantASN || got[0].RTTMs == 0) { + t.Fatalf("%s: traffic shape lost: %+v", tc.description, got[0]) + } + }) + } +} + +// clickhouseRows inserts one socket's six polls, ten seconds apart, stamped +// with the given agent, boot and collection nonce. +func clickhouseRows(agent, boot, collection string, cookie int) string { + return fmt.Sprintf(`INSERT INTO default.sockets SELECT '%s','%s','%s',1,%d, + fromUnixTimestamp64Nano(1700000000000000000+toInt64(number)*10000000000), + 1000000+number*1000,1000000+number*1000,number*10,1000,500,true,'trial','dc1',1, + unhex('C0000201000000000000000000000000'),2,64512 FROM numbers(6); +`, agent, boot, collection, cookie) +} + +// Execute the production SQL against an isolated ClickHouse local database. +// No live service or production telemetry is accessed. +func TestClickHouseAnalysisCounterDeltas(t *testing.T) { + binary, lerr := exec.LookPath("clickhouse") + if lerr != nil { + t.Skip("clickhouse is not on PATH; the Nix quality check supplies it") + } + const nonce1, nonce2, nonceX = "00000000000000000000000000000001", "00000000000000000000000000000002", "0000000000000000000000000000000f" + // The bound socket is inserted twice to prove poll deduplication. + setup := `CREATE TABLE default.sockets ( + agent_id String,host_boot_id String,collection_id String,netns_inode UInt64,inet_diag_msg_socket_cookie UInt64, + timestamp_ns DateTime64(9),tcp_info_bytes_acked UInt64,tcp_info_bytes_sent UInt64, + tcp_info_bytes_retrans UInt64,tcp_info_rtt UInt32,tcp_info_min_rtt UInt32, + treatment_algorithm_exposed Bool,treatment_assignment_id String,location String, + inet_diag_msg_state UInt8,inet_diag_msg_socket_destination FixedString(16), + inet_diag_msg_family UInt8,enrich_socket_dest_asn UInt64) ENGINE=Memory; +` + clickhouseRows("host-1", "boot-1", nonce1, 1) + "INSERT INTO default.sockets SELECT * FROM default.sockets;\n" + query := strings.ReplaceAll(analysisSQL, "{{TABLE}}", "default.sockets") + run := func(sql, sessions string) []byte { + t.Helper() + dir := t.TempDir() + file := filepath.Join(dir, "query.sql") + if e := os.WriteFile(file, []byte(sql), 0600); e != nil { + t.Fatal(e) + } + cmd := exec.Command(binary, "local", "--path", filepath.Join(dir, "data"), "--queries-file", file, "--multiquery", + "--param_start=1700000000000000000", "--param_end=1700000060000000000", "--param_location=dc1", + "--param_agents=['host-1']", "--param_sessions="+sessions, "--param_destination_hex=C0000201000000000000000000000000", "--param_assignment=trial", + "--param_minimum_rtt=0", "--param_maximum_rtt=10", "--param_minimum_retransmission=0", + "--output_format_json_quote_64bit_integers=0") + out, e := cmd.CombinedOutput() + if e != nil { + t.Fatalf("ClickHouse SQL: %v\n%s", e, out) + } + return out + } + session1 := sessionsParam([]treatment.Session{{AgentID: "host-1", BootID: "boot-1", CollectionID: nonce1}}) + bound := hostRow{AgentID: "host-1", Sockets: 1, BytesAcked: 5000, GoodputBps: 5000 * 8 / 60.0, RetransmissionRatio: .01, RttP95Ms: 1, ExposedSockets: 1, CollectionHealthy: true} + withUnbound := func(h hostRow, n uint64) hostRow { h.UnboundSockets = n; return h } + tests := []struct { + description string + extra string + sessions string + expected hostRow + healthOnly bool // a counter reset changes the deltas; only health is pinned + }{ + {"positive: rows of a reported session are measured, with deltas over deduplicated polls", "", session1, bound, false}, + {"positive: a nonce rotated mid-window counts both sessions' sockets", clickhouseRows("host-1", "boot-1", nonce2, 2), + sessionsParam([]treatment.Session{{AgentID: "host-1", BootID: "boot-1", CollectionID: nonce1}, {AgentID: "host-1", BootID: "boot-1", CollectionID: nonce2}}), + hostRow{AgentID: "host-1", Sockets: 2, BytesAcked: 10000, GoodputBps: 10000 * 8 / 60.0, RetransmissionRatio: .01, RttP95Ms: 1, ExposedSockets: 2, CollectionHealthy: true}, false}, + {"negative: rows claiming host-1 from another boot are excluded and counted", clickhouseRows("host-1", "boot-x", nonce1, 3), session1, withUnbound(bound, 1), false}, + {"negative: rows with the right boot and an unknown nonce are excluded and counted", clickhouseRows("host-1", "boot-1", nonceX, 4), session1, withUnbound(bound, 1), false}, + {"boundary: rows with an empty nonce (a journal without one) are excluded and counted", clickhouseRows("host-1", "boot-1", "", 5), session1, withUnbound(bound, 1), false}, + {"corner: with no sessions every socket is unbound and the host is not collection-healthy", "", "[]", hostRow{AgentID: "host-1", UnboundSockets: 1}, false}, + {"negative: a counter reset inside the window is not collection-healthy", `INSERT INTO default.sockets SELECT 'host-1','boot-1','` + nonce1 + `',1,1, + fromUnixTimestamp64Nano(1700000055000000000),1,1,0,1000,500,true,'trial','dc1',1, + unhex('C0000201000000000000000000000000'),2,64512; +`, session1, hostRow{AgentID: "host-1"}, true}, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + var h hostRow + if e := json.Unmarshal(run(setup+tc.extra+query, tc.sessions), &h); e != nil { + t.Fatal(e) + } + if tc.healthOnly { + h = hostRow{AgentID: h.AgentID, CollectionHealthy: h.CollectionHealthy, UnboundSockets: h.UnboundSockets} + } + if h != tc.expected { + t.Fatalf("%s:\n got %+v\nwant %+v", tc.description, h, tc.expected) + } + }) + } + // Syntax/type-check candidate discovery too; a one-host fixture cannot meet + // its six-host eligibility threshold. + if out := run(setup+strings.ReplaceAll(discoverySQL, "{{TABLE}}", "default.sockets"), session1); len(out) != 0 { + t.Fatalf("unexpected discovery: %s", out) + } +} diff --git a/pkg/treatment/controller/evidence/clickhouse/discovery.sql b/pkg/treatment/controller/evidence/clickhouse/discovery.sql new file mode 100644 index 000000000..9436f0025 --- /dev/null +++ b/pkg/treatment/controller/evidence/clickhouse/discovery.sql @@ -0,0 +1,25 @@ +-- Candidate discovery: destinations in one location that at least six hosts +-- talked to during the window, with the median of per-socket minimum RTT and +-- the pooled retransmission ratio, best traffic first. A row is a hypothesis +-- input; the controller still filters by template scope and the operator +-- still reviews every proposal. +WITH sockets AS ( + SELECT agent_id,host_boot_id,netns_inode,inet_diag_msg_socket_cookie, + any(hex(inet_diag_msg_socket_destination)) AS destination_hex, + any(inet_diag_msg_family) AS family, + argMax(enrich_socket_dest_asn,timestamp_ns) AS asn, + min(tcp_info_min_rtt)/1000 AS min_rtt_ms, + max(tcp_info_bytes_sent)-min(tcp_info_bytes_sent) AS sent, + max(tcp_info_bytes_retrans)-min(tcp_info_bytes_retrans) AS retrans + FROM {{TABLE}} + WHERE timestamp_ns>=fromUnixTimestamp64Nano({start:Int64}) AND timestamp_ns=3 +) +SELECT destination_hex,family,any(asn) AS asn,groupUniqArray(10000)(agent_id) AS agents, + quantileExact(0.5)(min_rtt_ms) AS rtt_ms,sum(retrans)/greatest(1,sum(sent)) AS retransmission_ratio +FROM sockets GROUP BY destination_hex,family +HAVING length(agents)>=6 AND rtt_ms>={minimum_rtt:Float64} AND rtt_ms<={maximum_rtt:Float64} + AND retransmission_ratio>={minimum_retransmission:Float64} +ORDER BY sum(sent) DESC LIMIT 10 FORMAT JSONEachRow diff --git a/pkg/treatment/controller/evidence/evidence.go b/pkg/treatment/controller/evidence/evidence.go new file mode 100644 index 000000000..ebb219e3f --- /dev/null +++ b/pkg/treatment/controller/evidence/evidence.go @@ -0,0 +1,139 @@ +// Package evidence defines the controller's ports to the telemetry warehouse: +// a Source that measures a frozen population over a window and a +// CandidateSource that proposes destinations worth a hypothesis. The +// controller depends only on these interfaces; package clickhouse is the one +// adapter today, and handler tests use in-memory fakes. +package evidence + +import ( + "context" + "errors" + "net/netip" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +// Window is what a Source measures: one destination, one frozen population, +// one half-open interval [Start, End). ExperimentID is the assignment the +// exposure columns are matched against. Sessions are the (agent, boot, +// collection) triples the population reported over mTLS; records carrying a +// population agent ID under any other triple are counted as unbound and +// excluded from the measurements. +type Window struct { + Location string + Destination netip.Prefix + ExperimentID string + Agents []string + Sessions []treatment.Session + Start, End time.Time +} + +// MaxSessions bounds Window.Sessions: several restarts per host over the +// longest window. The store caps each agent at eight, so a full population +// stays within it however often any one host rotates its nonce. +const MaxSessions = 8 * treatment.MaxAgents + +// Validate applies the bounds every adapter must enforce before querying. +func (w Window) Validate() error { + if !w.End.After(w.Start) || w.End.Sub(w.Start) > MaxWindow || len(w.Agents) == 0 || len(w.Agents) > treatment.MaxAgents { + return errors.New("invalid analysis window/population") + } + population := make(map[string]bool, len(w.Agents)) + for _, id := range w.Agents { + if !treatment.ValidID(id) { + return errors.New("invalid agent") + } + population[id] = true + } + if len(w.Sessions) > MaxSessions { + return errors.New("too many sessions") + } + for _, s := range w.Sessions { + if !population[s.AgentID] || !treatment.ValidID(s.BootID) || !treatment.ValidCollectionID(s.CollectionID) { + return errors.New("invalid session") + } + } + if !w.Destination.IsValid() { + return errors.New("invalid destination") + } + if !treatment.ValidID(w.Location) || !treatment.ValidID(w.ExperimentID) { + return errors.New("invalid location or experiment") + } + return nil +} + +// MaxWindow bounds one analysis or discovery query. +const MaxWindow = 7 * 24 * time.Hour + +// SettleDelay is how far behind the clock a window ends, so the newest +// telemetry has landed in the warehouse before it is measured. +const SettleDelay = 20 * time.Second + +// Source produces immutable per-host evidence for a window. Failure never +// authorizes lease renewal or promotion; the controller treats an error as +// no evidence. +type Source interface { + Evidence(context.Context, Window) (*treatment.Evidence, error) +} + +// WindowFor is the controller's policy for which interval an experiment is +// measured over: before any phase, the hour before now; during a phase, from +// the observation start (or issue, if observation has not begun) until now. +// Both end SettleDelay behind now. +func WindowFor(e *treatment.Experiment, now time.Time) Window { + end := now.Add(-SettleDelay) + w := Window{Location: e.Location, Destination: e.Treatment.Destination, ExperimentID: e.ID, Agents: e.CohortOrder, Start: end.Add(-time.Hour), End: end} + if p := e.CurrentPhase(); p != nil { + w.Start = p.IssuedAt + if !p.ObservationStartedAt.IsZero() { + w.Start = p.ObservationStartedAt + } + } + return w +} + +// CandidateQuery bounds one discovery scan of a location. +type CandidateQuery struct { + Location string + Start, End time.Time + // Median minimum RTT band and retransmission floor a destination must + // fall in to be a candidate; the template that authorized the scan sets + // them. + MinimumRTTMs, MaximumRTTMs float64 + MinimumRetransmissionRatio float64 +} + +// Validate applies the bounds every adapter must enforce. +func (q CandidateQuery) Validate() error { + if !treatment.ValidID(q.Location) || !q.End.After(q.Start) || q.End.Sub(q.Start) > MaxWindow { + return errors.New("invalid discovery window") + } + if q.MinimumRTTMs < 0 || q.MaximumRTTMs <= q.MinimumRTTMs || q.MinimumRetransmissionRatio < 0 || q.MinimumRetransmissionRatio > 1 { + return errors.New("invalid discovery bounds") + } + return nil +} + +// Candidate is one destination a scan surfaced: the hosts that talked to it +// and the traffic shape that made it interesting. It is a hypothesis input, +// not a measurement of benefit. +type Candidate struct { + Destination netip.Prefix + ASN uint64 + Agents []string + RTTMs float64 + RetransmissionRatio float64 +} + +// CandidateSource lists destinations worth proposing, best first. +type CandidateSource interface { + Candidates(context.Context, CandidateQuery) ([]Candidate, error) +} + +// Warehouse is what candidate discovery needs: candidates and the baseline +// evidence for each. +type Warehouse interface { + Source + CandidateSource +} diff --git a/pkg/treatment/controller/evidence/evidence_test.go b/pkg/treatment/controller/evidence/evidence_test.go new file mode 100644 index 000000000..952daeb1d --- /dev/null +++ b/pkg/treatment/controller/evidence/evidence_test.go @@ -0,0 +1,143 @@ +package evidence + +import ( + "net/netip" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +func TestWindowFor(t *testing.T) { + now := time.Unix(1700000000, 0).UTC() + base := func() *treatment.Experiment { + return &treatment.Experiment{ID: "exp", Location: "dc1", Treatment: treatment.Treatment{Destination: netip.MustParsePrefix("192.0.2.1/32")}, CohortOrder: []string{"a", "b"}} + } + for _, tc := range []struct { + name, description string + experiment func() *treatment.Experiment + wantStart time.Time + }{ + {"no-phase", "positive: before review the baseline window is the hour before the settled end", base, now.Add(-SettleDelay - time.Hour)}, + {"phase-issued", "positive: a phase without observation measures from issue", func() *treatment.Experiment { + e := base() + e.Phases = []treatment.Phase{{IssuedAt: now.Add(-40 * time.Minute)}} + return e + }, now.Add(-40 * time.Minute)}, + {"phase-observing", "positive: once observation started the window begins there", func() *treatment.Experiment { + e := base() + e.Phases = []treatment.Phase{{IssuedAt: now.Add(-40 * time.Minute), ObservationStartedAt: now.Add(-35 * time.Minute)}} + return e + }, now.Add(-35 * time.Minute)}, + {"latest-phase", "boundary: only the current phase counts", func() *treatment.Experiment { + e := base() + e.Phases = []treatment.Phase{{IssuedAt: now.Add(-3 * time.Hour), ObservationStartedAt: now.Add(-3 * time.Hour)}, {IssuedAt: now.Add(-10 * time.Minute)}} + return e + }, now.Add(-10 * time.Minute)}, + } { + t.Run(tc.name, func(t *testing.T) { + e := tc.experiment() + w := WindowFor(e, now) + if !w.Start.Equal(tc.wantStart) || !w.End.Equal(now.Add(-SettleDelay)) { + t.Fatalf("%s: window %v..%v, want start %v", tc.description, w.Start, w.End, tc.wantStart) + } + if w.Location != "dc1" || w.ExperimentID != "exp" || w.Destination != e.Treatment.Destination || len(w.Agents) != 2 { + t.Fatalf("%s: identity not carried: %+v", tc.description, w) + } + if err := w.Validate(); err != nil { + t.Fatalf("%s: policy window must validate: %v", tc.description, err) + } + }) + } +} + +// session is a well-formed session of agent. +func session(agent string) treatment.Session { + return treatment.Session{AgentID: agent, BootID: "boot-1", CollectionID: fixtures.CollectionID} +} + +func TestWindowValidate(t *testing.T) { + now := time.Unix(1700000000, 0) + valid := func() Window { + return Window{Location: "dc1", Destination: netip.MustParsePrefix("192.0.2.1/32"), ExperimentID: "exp", Agents: []string{"a"}, Start: now.Add(-time.Minute), End: now} + } + many := make([]string, treatment.MaxAgents) + for i := range many { + many[i] = "h" + strings.Repeat("x", i%3) + string(rune('a'+i%26)) + string(rune('a'+(i/26)%26)) + string(rune('a'+(i/676)%26)) + } + for _, tc := range []struct { + name, description string + change func(*Window) + expected string + }{ + {"valid", "positive: a bounded window with one agent passes", func(*Window) {}, ""}, + {"max-agents", "boundary: MaxAgents hosts are accepted", func(w *Window) { w.Agents = many }, ""}, + {"too-many-agents", "boundary: one host over MaxAgents is refused", func(w *Window) { w.Agents = append(append([]string(nil), many...), "extra") }, "population"}, + {"max-window", "boundary: exactly seven days is accepted", func(w *Window) { w.Start = w.End.Add(-MaxWindow) }, ""}, + {"long-window", "boundary: a second over seven days is refused", func(w *Window) { w.Start = w.End.Add(-MaxWindow - time.Second) }, "window"}, + {"empty-window", "negative: end must follow start", func(w *Window) { w.Start = w.End }, "window"}, + {"no-agents", "negative: an empty population cannot be measured", func(w *Window) { w.Agents = nil }, "population"}, + {"bad-agent", "negative: an agent ID that could inject a parameter is refused", func(w *Window) { w.Agents = []string{"host'"} }, "invalid agent"}, + {"bad-destination", "negative: the zero prefix is refused", func(w *Window) { w.Destination = netip.Prefix{} }, "invalid destination"}, + {"bad-location", "corner: the location is an identifier too", func(w *Window) { w.Location = "dc 1" }, "location"}, + {"session", "positive: a session of a population agent passes", func(w *Window) { w.Sessions = []treatment.Session{session("a")} }, ""}, + {"session-outsider", "negative: a session for an agent outside the population is refused", func(w *Window) { w.Sessions = []treatment.Session{session("b")} }, "invalid session"}, + {"session-bad-nonce", "negative: a nonce that is not 32 lowercase hex digits could inject a parameter", func(w *Window) { + s := session("a") + s.CollectionID = strings.ToUpper(s.CollectionID) + w.Sessions = []treatment.Session{s} + }, "invalid session"}, + {"session-bad-boot", "negative: a boot ID with a quote is refused", func(w *Window) { + s := session("a") + s.BootID = "boot'" + w.Sessions = []treatment.Session{s} + }, "invalid session"}, + {"too-many-sessions", "boundary: one session over MaxSessions is refused", func(w *Window) { + w.Sessions = make([]treatment.Session, MaxSessions+1) + for i := range w.Sessions { + w.Sessions[i] = session("a") + } + }, "too many sessions"}, + } { + t.Run(tc.name, func(t *testing.T) { + w := valid() + tc.change(&w) + err := w.Validate() + if tc.expected == "" && err != nil || tc.expected != "" && (err == nil || !strings.Contains(err.Error(), tc.expected)) { + t.Fatalf("%s: got %v, want %q", tc.description, err, tc.expected) + } + }) + } +} + +func TestCandidateQueryValidate(t *testing.T) { + now := time.Unix(1700000000, 0) + valid := func() CandidateQuery { + return CandidateQuery{Location: "dc1", Start: now.Add(-time.Hour), End: now, MinimumRTTMs: 0, MaximumRTTMs: 15, MinimumRetransmissionRatio: 0} + } + for _, tc := range []struct { + name, description string + change func(*CandidateQuery) + expected string + }{ + {"valid", "positive: a template's bounds pass", func(*CandidateQuery) {}, ""}, + {"max-window", "boundary: seven days is the longest scan", func(q *CandidateQuery) { q.Start = q.End.Add(-MaxWindow) }, ""}, + {"long-window", "boundary: over seven days is refused", func(q *CandidateQuery) { q.Start = q.End.Add(-MaxWindow - time.Nanosecond) }, "window"}, + {"rtt-order", "negative: the RTT band must be non-empty", func(q *CandidateQuery) { q.MaximumRTTMs = q.MinimumRTTMs }, "bounds"}, + {"negative-rtt", "negative: a negative RTT floor is refused", func(q *CandidateQuery) { q.MinimumRTTMs = -1 }, "bounds"}, + {"retrans-over-one", "negative: a retransmission ratio above one is meaningless", func(q *CandidateQuery) { q.MinimumRetransmissionRatio = 1.01 }, "bounds"}, + {"retrans-one", "boundary: a ratio of exactly one is allowed", func(q *CandidateQuery) { q.MinimumRetransmissionRatio = 1 }, ""}, + {"bad-location", "corner: the location is an identifier", func(q *CandidateQuery) { q.Location = "" }, "window"}, + } { + t.Run(tc.name, func(t *testing.T) { + q := valid() + tc.change(&q) + err := q.Validate() + if tc.expected == "" && err != nil || tc.expected != "" && (err == nil || !strings.Contains(err.Error(), tc.expected)) { + t.Fatalf("%s: got %v, want %q", tc.description, err, tc.expected) + } + }) + } +} diff --git a/pkg/treatment/controller/helpers_test.go b/pkg/treatment/controller/helpers_test.go new file mode 100644 index 000000000..d662da77f --- /dev/null +++ b/pkg/treatment/controller/helpers_test.go @@ -0,0 +1,223 @@ +package controller + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "net/http" + "net/http/httptest" + "net/netip" + "net/url" + "strconv" + "strings" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/memory" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/pgtest" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/peer" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func testIdentity(path string) context.Context { + u, _ := url.Parse("spiffe://xtcp/" + path) + cert := &x509.Certificate{URIs: []*url.URL{u}} + return peer.NewContext(context.Background(), &peer.Peer{AuthInfo: credentials.TLSInfo{State: tls.ConnectionState{PeerCertificates: []*x509.Certificate{cert}, VerifiedChains: [][]*x509.Certificate{{cert}}}}}) +} + +// eachStore runs fn against the in-memory store always and against +// PostgreSQL when XTCP_CONTROLLER_TEST_DSN is set, so every handler test is +// a unit test by default and an integration test in the Nix harness. +func eachStore(t *testing.T, fn func(t *testing.T, s store.Store)) { + t.Helper() + t.Run("memory", func(t *testing.T) { fn(t, memory.New()) }) + t.Run("postgres", func(t *testing.T) { fn(t, pgtest.Open(t)) }) +} + +func testServer(s store.Store, now *time.Time) *Server { + return &Server{Store: s, Hub: NewNotificationHub(), Now: func() time.Time { return *now }} +} + +func capabilities() *pb.Capabilities { + return &pb.Capabilities{BootId: "boot-1", CollectionId: fixtures.CollectionID, KernelRelease: "test", CongestionAlgorithms: []string{"cubic", "bbr"}, SimpleHostRouting: true, ActuatorEnabled: true} +} + +func enroll(t *testing.T, s *Server, id string) { + t.Helper() + if _, e := s.CheckIn(testIdentity("agent/dc1/"+id), &pb.CheckInRequest{AgentId: id, Location: "dc1", Capabilities: capabilities()}); e != nil { + t.Fatal(e) + } +} + +func enrollFleet(t *testing.T, s *Server, n int) { + t.Helper() + for i := range n { + enroll(t, s, fmt.Sprintf("host-%d", i)) + } +} + +func proposal(now time.Time) *pb.ProposeRequest { + e := &pb.Experiment{Id: "experiment-1", Location: "dc1", Hypothesis: "test cubic", Policy: wire.Policy(treatment.DefaultPolicy()), Treatment: &pb.Treatment{Id: "cubic", Revision: 1, Destination: "192.0.2.1/32", Settings: &pb.TCPSettings{CongestionControl: proto.String("cubic")}}, Baseline: &pb.Evidence{Id: "baseline-1", AnalyzedAt: timestamppb.New(now), WindowStart: timestamppb.New(now.Add(-time.Hour)), WindowEnd: timestamppb.New(now.Add(-time.Second)), QueryVersion: "test", ArtifactSha256: strings.Repeat("a", 64)}} + for i := range 8 { + id := fmt.Sprintf("host-%d", i) + e.CohortOrder = append(e.CohortOrder, id) + e.Baseline.Hosts = append(e.Baseline.Hosts, &pb.HostEvidence{AgentId: id, Sockets: 100, BytesAcked: 1 << 25, GoodputBps: 1e8, RttP95Ms: 1, CollectionHealthy: true}) + } + return &pb.ProposeRequest{Experiment: e, RequestId: "proposal-1"} +} + +func desiredOf(t *testing.T, s store.Store, id string) *treatment.DesiredState { + t.Helper() + d, e := s.Repos().Agents.Desired(context.Background(), id) + if e != nil { + t.Fatal(e) + } + return d +} + +func experimentsOf(t *testing.T, s store.Store) []*treatment.Experiment { + t.Helper() + list, e := s.Repos().Experiments.List(context.Background(), "", 1000) + if e != nil { + t.Fatal(e) + } + return list +} + +func fleetAssignments(t *testing.T, s store.Store) int { + t.Helper() + agents, e := s.Repos().Agents.List(context.Background(), "") + if e != nil { + t.Fatal(e) + } + n := 0 + for _, a := range agents { + n += len(desiredOf(t, s, a.ID).Assignments) + } + return n +} + +// seedExperiment stores a bare experiment directly, standing in for history +// written by an earlier controller. +func seedExperiment(t *testing.T, s store.Store, id, location, destination string, status treatment.Status, updated time.Time) { + t.Helper() + tr := treatment.Treatment{ID: "cubic", Revision: 1, Settings: treatment.TCPSettings{CongestionControl: proto.String("cubic")}} + if destination != "" { + tr.Destination = netip.MustParsePrefix(destination) + } + e := &treatment.Experiment{ID: id, Location: location, Hypothesis: "seeded", Treatment: tr, Policy: treatment.DefaultPolicy(), Status: status, Revision: 1, ProposedAt: updated, UpdatedAt: updated} + if err := s.Repos().Experiments.Save(context.Background(), e); err != nil { + t.Fatal(err) + } +} + +// fixedEvidence is an evidence.Source that answers every window with one +// prepared measurement. +type fixedEvidence struct{ value *treatment.Evidence } + +func (f fixedEvidence) Evidence(context.Context, evidence.Window) (*treatment.Evidence, error) { + return f.value, nil +} + +// fakeWarehouse is an in-memory evidence.Warehouse for discovery tests. It +// records the queries it saw so tests can assert on bounds, and it builds +// baseline evidence for whatever population a window names. +type fakeWarehouse struct { + candidates []evidence.Candidate + candidateErr error + evidenceErr error + queries []evidence.CandidateQuery + windows []evidence.Window + now func() time.Time +} + +func (f *fakeWarehouse) Candidates(_ context.Context, q evidence.CandidateQuery) ([]evidence.Candidate, error) { + f.queries = append(f.queries, q) + if f.candidateErr != nil { + return nil, f.candidateErr + } + if err := q.Validate(); err != nil { + return nil, err + } + return f.candidates, nil +} + +func (f *fakeWarehouse) Evidence(_ context.Context, w evidence.Window) (*treatment.Evidence, error) { + f.windows = append(f.windows, w) + if f.evidenceErr != nil { + return nil, f.evidenceErr + } + if err := w.Validate(); err != nil { + return nil, err + } + now := time.Now() + if f.now != nil { + now = f.now() + } + v := &treatment.Evidence{ID: "ev-" + strconv.FormatInt(now.UnixNano(), 10), AnalyzedAt: now, WindowStart: w.Start, WindowEnd: w.End, QueryVersion: "fake-v1", ArtifactSHA256: strings.Repeat("ab", 32)} + for _, id := range w.Agents { + v.Hosts = append(v.Hosts, treatment.HostEvidence{AgentID: id, Sockets: 100, BytesAcked: 1 << 25, GoodputBps: 1e8, RttP95Ms: 5, CollectionHealthy: true}) + } + return v, nil +} + +func parseEvidence(t *testing.T, p *pb.Evidence) *treatment.Evidence { + t.Helper() + v, e := wire.ParseEvidence(p) + if e != nil { + t.Fatal(e) + } + return v +} + +// acknowledgeFleet reports every cohort host's assignments as verified at +// the latest phase's issue time. +func acknowledgeFleet(t *testing.T, s *Server, n *pb.Experiment) { + t.Helper() + for _, id := range n.CohortOrder { + d := wire.Desired(desiredOf(t, s.Store, id)) + r := &pb.CheckInRequest{AgentId: id, Location: n.Location, DesiredRevision: d.Revision, Capabilities: capabilities()} + for _, a := range d.Assignments { + r.Records = append(r.Records, &pb.ApplicationRecord{Assignment: proto.Clone(a).(*pb.Assignment), DesiredRevision: d.Revision, Status: pb.ApplyStatus_APPLY_STATUS_VERIFIED, AppliedAt: n.Phases[len(n.Phases)-1].IssuedAt}) + } + if _, e := s.CheckIn(testIdentity("agent/dc1/"+id), r); e != nil { + t.Fatal(e) + } + } +} + +func operatorHTTP(method, path, identity string) *http.Request { + r := httptest.NewRequest(method, path, nil) + if identity != "" { + u, _ := url.Parse("spiffe://xtcp/" + identity) + cert := &x509.Certificate{URIs: []*url.URL{u}} + r.TLS = &tls.ConnectionState{PeerCertificates: []*x509.Certificate{cert}, VerifiedChains: [][]*x509.Certificate{{cert}}} + } + return r +} + +type desiredTestStream struct { + grpc.ServerStream + ctx context.Context + sent chan uint64 +} + +func (s *desiredTestStream) Context() context.Context { return s.ctx } +func (s *desiredTestStream) Send(r *pb.WatchDesiredStateResponse) error { + select { + case s.sent <- r.Revision: + return nil + case <-s.ctx.Done(): + return s.ctx.Err() + } +} diff --git a/pkg/treatment/controller/housekeep_test.go b/pkg/treatment/controller/housekeep_test.go new file mode 100644 index 000000000..3b428f06c --- /dev/null +++ b/pkg/treatment/controller/housekeep_test.go @@ -0,0 +1,86 @@ +package controller + +import ( + "context" + "errors" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/memory" +) + +// TestHousekeepLease checks that maintenance and discovery run on exactly +// one replica per tick: the one holding the lease. +func TestHousekeepLease(t *testing.T) { + now := time.Unix(1800000000, 0) + templates := []DiscoveryTemplate{{ID: "near", Location: "test-dc", CongestionControl: "cubic", MaximumRTTMs: 15}} + for _, tc := range []struct { + name, description string + warehouse *fakeWarehouse + heldElsewhere bool + canceled bool + wantHeld bool + wantErr string + wantQueries int + }{ + {"free", "positive: with the lease free this replica runs maintenance and discovery", &fakeWarehouse{}, false, false, true, "", 1}, + {"held-elsewhere", "corner: while another replica holds the lease this one runs nothing and reports it", &fakeWarehouse{}, true, false, false, "", 0}, + {"no-warehouse", "boundary: without a warehouse the pass is maintenance only", nil, false, false, true, "", 0}, + {"discovery-fails", "negative: a failing pass still held the lease and names the failing stage", &fakeWarehouse{candidateErr: errors.New("warehouse offline")}, false, false, true, "candidate discovery: warehouse offline", 1}, + {"canceled", "negative: a canceled context takes no lease and runs nothing", &fakeWarehouse{}, false, true, false, "context canceled", 0}, + } { + t.Run(tc.name, func(t *testing.T) { + st := memory.New() + s := &Server{Store: st, Now: func() time.Time { return now }} + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + if tc.canceled { + cancel() + } + release := make(chan struct{}) + if tc.heldElsewhere { + entered := make(chan struct{}) + go func() { + _, _ = st.Lease(context.Background(), housekeepingLeaseCst, func() error { close(entered); <-release; return nil }) + }() + <-entered + } + var w evidence.Warehouse + if tc.warehouse != nil { + w = tc.warehouse + } + held, err := s.Housekeep(ctx, nil, w, templates) + if tc.heldElsewhere { + close(release) + } + if held != tc.wantHeld { + t.Fatalf("%s: held=%t want %t", tc.description, held, tc.wantHeld) + } + if tc.wantErr == "" && err != nil || tc.wantErr != "" && (err == nil || !strings.Contains(err.Error(), tc.wantErr)) { + t.Fatalf("%s: err=%v want %q", tc.description, err, tc.wantErr) + } + if tc.warehouse != nil && len(tc.warehouse.queries) != tc.wantQueries { + t.Fatalf("%s: discovery queries=%d want %d", tc.description, len(tc.warehouse.queries), tc.wantQueries) + } + if tc.heldElsewhere { + // Once the holder returns, this replica takes over. + deadline := time.Now().Add(2 * time.Second) + for { + held, err = s.Housekeep(ctx, nil, w, templates) + if err != nil { + t.Fatal(err) + } + if held || time.Now().After(deadline) { + break + } + time.Sleep(5 * time.Millisecond) + } + if !held || len(tc.warehouse.queries) != 1 { + t.Fatalf("%s: expected the released lease to be taken, held=%t queries=%d", tc.description, held, len(tc.warehouse.queries)) + } + } + }) + } +} diff --git a/pkg/treatment/controller/maintenance.go b/pkg/treatment/controller/maintenance.go new file mode 100644 index 000000000..951abad7b --- /dev/null +++ b/pkg/treatment/controller/maintenance.go @@ -0,0 +1,262 @@ +package controller + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/experiment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" +) + +// driftInput rewinds the current phase an hour so a completed treatment is +// re-analyzed over a rolling window rather than since its review. +func (s *Server) driftInput(n *treatment.Experiment) *treatment.Experiment { + input := n.Clone() + p := input.CurrentPhase() + p.IssuedAt = s.now().Add(-time.Hour) + p.ObservationStartedAt = p.IssuedAt + return input +} + +// housekeepingLeaseCst names the lease one replica holds while it runs +// maintenance and discovery; the others skip the tick. +const housekeepingLeaseCst = "housekeeping" + +// Housekeep runs one maintenance pass, and a discovery pass when warehouse +// is non-nil, under the housekeeping lease. It reports whether this replica +// held the lease; false means another replica did the work for this tick. +// Correctness never depended on a single runner (the mutation lock fences +// every write); the lease keeps the evidence queries from running once per +// replica. +func (s *Server) Housekeep(ctx context.Context, source evidence.Source, warehouse evidence.Warehouse, templates []DiscoveryTemplate) (bool, error) { + return s.Store.Lease(ctx, housekeepingLeaseCst, func() error { + var errs []error + if e := s.Maintain(ctx, source); e != nil { + errs = append(errs, fmt.Errorf("maintenance: %w", e)) + } + if warehouse != nil { + if e := s.Discover(ctx, warehouse, templates); e != nil { + errs = append(errs, fmt.Errorf("candidate discovery: %w", e)) + } + } + if _, e := s.Store.Repos().Agents.PruneSessions(ctx, s.now().Add(-sessionRetention)); e != nil { + errs = append(errs, fmt.Errorf("session retention: %w", e)) + } + return errors.Join(errs...) + }) +} + +// Maintain refreshes exposure, stores evidence, renews healthy leases, and +// withdraws harmful/expired trials. It NEVER promotes a phase. A fresh human +// review remains necessary for each increase in exposure. A nil source (no +// warehouse configured) still expires and withdraws; it never renews. +func (s *Server) Maintain(ctx context.Context, source evidence.Source) error { + ids, e := s.Store.Repos().Experiments.IDs(ctx, treatment.StatusRunning, treatment.StatusPaused, treatment.StatusComplete) + if e != nil { + return e + } + var failures []error + for _, id := range ids { + if e = s.maintainOne(ctx, source, id); e != nil { + failures = append(failures, e) + } + } + return errors.Join(failures...) +} + +// maintainOne is one experiment's pass: start observation, query evidence +// outside any transaction, then apply the result under the mutation lock if +// nobody changed the experiment meanwhile. +func (s *Server) maintainOne(ctx context.Context, source evidence.Source, id string) error { + snapshot, e := s.observe(ctx, id) + if e != nil || snapshot == nil || len(snapshot.Phases) == 0 { + return e + } + var errs []error + ev, e := s.fetchEvidence(ctx, source, snapshot) + if e != nil { + errs = append(errs, fmt.Errorf("%s analysis: %w", id, e)) + } + e = s.Store.Tx(ctx, func(rp store.Repos) error { + n, e := rp.Experiments.Get(ctx, id) + if e != nil { + return e + } + if n.Revision != snapshot.Revision { + return nil + } + if n.Status == treatment.StatusComplete { + return s.driftPass(ctx, rp, n, ev) + } + return s.trialPass(ctx, rp, n, ev) + }) + return errors.Join(append(errs, e)...) +} + +// observe starts observation for a running or paused experiment and returns +// the snapshot the evidence window is computed from, or nil when the +// experiment needs no pass this tick. +func (s *Server) observe(ctx context.Context, id string) (*treatment.Experiment, error) { + var snapshot *treatment.Experiment + e := s.Store.Tx(ctx, func(rp store.Repos) error { + n, e := rp.Experiments.Get(ctx, id) + if e != nil { + return e + } + if n.Status != treatment.StatusRunning && n.Status != treatment.StatusPaused && n.Status != treatment.StatusComplete { + return nil + } + if n.Status == treatment.StatusComplete { + if n.LatestEvidence != nil && s.now().Sub(n.LatestEvidence.AnalyzedAt) < time.Hour { + return nil + } + } else if e = s.startObservation(ctx, rp, n); e != nil { + return e + } + snapshot = n + return s.save(ctx, rp, n) + }) + return snapshot, e +} + +// fetchEvidence queries the warehouse for the experiment's current window. +// Without a warehouse, or while the experiment is paused, there is none. +func (s *Server) fetchEvidence(ctx context.Context, source evidence.Source, snapshot *treatment.Experiment) (*treatment.Evidence, error) { + if source == nil || snapshot.Status == treatment.StatusPaused { + return nil, nil + } + input := snapshot + if snapshot.Status == treatment.StatusComplete { + input = s.driftInput(snapshot) + } + return s.boundEvidence(ctx, source, evidence.WindowFor(input, s.now())) +} + +// driftPass records drift evidence for a completed treatment and flags a +// regression for review; it never withdraws on its own. +func (s *Server) driftPass(ctx context.Context, rp store.Repos, n *treatment.Experiment, ev *treatment.Evidence) error { + if ev != nil { + if e := saveEvidence(ctx, rp, n.ID, ev); e != nil { + return e + } + healthy, harmful := experiment.HealthyEvidence(n, ev, s.now()) + n.LatestEvidence = ev + n.LatestOutcome = treatment.OutcomeStableObserved + if !healthy { + n.LatestOutcome = treatment.OutcomeStableEvidenceIncomplete + } + if harmful { + n.LatestOutcome = treatment.OutcomeStableRegressionReviewRequired + if e := audit(ctx, rp, "drift-monitor", "", "stable_regression", wire.Evidence(ev)); e != nil { + return e + } + } + } + return s.save(ctx, rp, n) +} + +// trialPass evaluates the current phase of a running or paused experiment: +// it withdraws an expired or harmful trial and renews the leases of a healthy +// one. Only Review writes the phase's reviewer and outcome. +func (s *Server) trialPass(ctx context.Context, rp store.Repos, n *treatment.Experiment, ev *treatment.Evidence) error { + phase := n.CurrentPhase() + now := s.now() + outcome := treatment.OutcomeUnavailable + switch { + case now.Sub(phase.IssuedAt) >= n.Policy.MaximumPhase: + outcome = treatment.OutcomeExpired + case ev != nil: + if e := saveEvidence(ctx, rp, n.ID, ev); e != nil { + return e + } + v, e := experiment.Evaluate(n, ev, now) + if e != nil { + return e + } + outcome = v.Outcome + // Keep analysis visible to reviewers without marking a phase as + // approved/evaluated. + n.LatestEvidence = ev + if _, harmful := experiment.HealthyEvidence(n, ev, now); harmful { + outcome = treatment.OutcomeHarmful + } + } + n.LatestOutcome = outcome + switch { + case outcome.Withdraws(): + event := experiment.EventExpire + if outcome == treatment.OutcomeHarmful { + event = experiment.EventHarm + } + var e error + if n.Status, e = experiment.Transition(n.Status, event); e != nil { + return e + } + phase.Outcome = outcome + phase.EvaluatedAt = now + n.Revision++ + if e = s.assign(ctx, rp, n, false); e != nil { + return e + } + if e = audit(ctx, rp, "safety-controller", "", "automatic_withdrawal", wire.Experiment(n)); e != nil { + return e + } + case ev != nil && n.Status == treatment.StatusRunning: + // Before the 30-minute decision window completes, fresh health + // evidence can renew the existing phase but cannot expand it. + healthy, _ := experiment.HealthyEvidence(n, ev, now) + if healthy && outcome.RenewsLease() { + if e := s.renew(ctx, rp, n, now); e != nil { + return e + } + } + } + return s.save(ctx, rp, n) +} + +func (s *Server) renew(ctx context.Context, rp store.Repos, n *treatment.Experiment, now time.Time) error { + for _, id := range n.CohortOrder[:n.Target()] { + d, e := rp.Agents.Desired(ctx, id) + if e != nil { + return e + } + if d.Suspended { + continue + } + a, e := rp.Agents.Get(ctx, id) + if e != nil { + return e + } + if !a.Seen(now, agentWindow) || a.Report.LocallySuspended || a.Report.DesiredRevision != d.Revision { + continue + } + for i := range d.Assignments { + x := &d.Assignments[i] + if x.ExperimentID != n.ID || x.Mode != treatment.ModeTrial || x.LeaseExpiresAt.IsZero() || !x.LeaseExpiresAt.After(now) { + continue + } + verified := false + for j := range a.Report.Records { + r := &a.Report.Records[j] + if r.Assignment.ExperimentID == x.ExperimentID && r.Assignment.Generation == x.Generation && r.Status == treatment.ApplyVerified { + verified = true + } + } + if !verified || x.LeaseExpiresAt.After(now.Add(treatment.TrialLease-treatment.LeaseRenewInterval)) { + continue + } + x.LeaseExpiresAt = now.Add(treatment.TrialLease) + d.Revision++ + d.IssuedAt = now + if e = rp.Agents.SaveDesired(ctx, d); e != nil { + return e + } + } + } + return nil +} diff --git a/pkg/treatment/controller/notifications.go b/pkg/treatment/controller/notifications.go new file mode 100644 index 000000000..6515831bf --- /dev/null +++ b/pkg/treatment/controller/notifications.go @@ -0,0 +1,104 @@ +package controller + +import ( + "context" + "sync" + "time" +) + +// NotificationHub collapses fleet notification work into one indexed-table scan +// per interval, rather than one database poll per connected agent. Channels hold +// only the latest revision. Desired state remains authoritative in PostgreSQL. +type NotificationHub struct { + mu sync.Mutex + subs map[string]map[chan uint64]struct{} + last map[string]uint64 +} + +func NewNotificationHub() *NotificationHub { + return &NotificationHub{subs: map[string]map[chan uint64]struct{}{}, last: map[string]uint64{}} +} +func (h *NotificationHub) subscribe(id string) (chan uint64, func()) { + h.mu.Lock() + defer h.mu.Unlock() + ch := make(chan uint64, 1) + if h.subs[id] == nil { + h.subs[id] = map[chan uint64]struct{}{} + } + h.subs[id][ch] = struct{}{} + if v := h.last[id]; v > 0 { + ch <- v + } + return ch, func() { + h.mu.Lock() + defer h.mu.Unlock() + delete(h.subs[id], ch) + if len(h.subs[id]) == 0 { + delete(h.subs, id) + } + } +} +func (h *NotificationHub) publish(id string, revision uint64) { + h.mu.Lock() + defer h.mu.Unlock() + if h.last[id] == revision { + return + } + h.last[id] = revision + for ch := range h.subs[id] { + select { + case <-ch: + default: + } + ch <- revision + } +} + +// notificationIntervalCst is the scan period; check-ins deliver desired +// state anyway, so a missed scan costs latency, not correctness. +const notificationIntervalCst = 2 * time.Second + +// notificationLagCst is taken off the watermark between scans. Stamps and +// commits are ordered by the mutation lock, so the margin only covers a +// store clock stepping backwards; the hub drops the repeats it causes. +const notificationLagCst = time.Second + +// RunNotifications publishes desired-state changes to subscribed agents. +// The first scan reads every agent so that late subscribers learn the +// current revision; each later scan reads only rows stamped at or after the +// previous scan's newest stamp less the lag, so its cost follows the change +// rate rather than the fleet size. Watermarks are store stamps, never this +// process's clock. +func (s *Server) RunNotifications(ctx context.Context) { + t := time.NewTicker(notificationIntervalCst) + defer t.Stop() + var since time.Time + for { + since = s.notify(ctx, since) + select { + case <-ctx.Done(): + return + case <-t.C: + } + } +} + +// notify publishes every change stamped at or after since and returns the +// next watermark. A failed scan keeps the watermark so nothing is skipped. +func (s *Server) notify(ctx context.Context, since time.Time) time.Time { + changes, e := s.Store.Repos().Agents.DesiredSince(ctx, since) + if e != nil { + return since + } + newest := since + for _, c := range changes { + s.Hub.publish(c.AgentID, c.Revision) + if c.UpdatedAt.After(newest) { + newest = c.UpdatedAt + } + } + if next := newest.Add(-notificationLagCst); next.After(since) { + return next + } + return since +} diff --git a/pkg/treatment/controller/notifications_test.go b/pkg/treatment/controller/notifications_test.go new file mode 100644 index 000000000..f2baca9e2 --- /dev/null +++ b/pkg/treatment/controller/notifications_test.go @@ -0,0 +1,241 @@ +package controller + +import ( + "context" + "errors" + "fmt" + "maps" + "sync" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/memory" +) + +func TestNotificationLifecycle(t *testing.T) { + for _, tc := range []struct { + name, description string + revisions []uint64 + before bool + want uint64 + }{ + {"first", "an existing subscriber receives a new revision", []uint64{1}, false, 1}, + {"coalesce", "a slow subscriber receives only the latest revision", []uint64{1, 2, 3}, false, 3}, + {"duplicate", "duplicate publication preserves the pending revision", []uint64{2, 2}, false, 2}, + {"late", "new subscribers immediately receive the known revision", []uint64{1, 3}, true, 3}, + } { + t.Run(tc.name, func(t *testing.T) { + h := NewNotificationHub() + var ch chan uint64 + var cancel func() + if !tc.before { + ch, cancel = h.subscribe("host") + } + for _, r := range tc.revisions { + h.publish("host", r) + } + if tc.before { + ch, cancel = h.subscribe("host") + } + defer cancel() + select { + case got := <-ch: + if got != tc.want { + t.Fatalf("%s: got %d want %d", tc.description, got, tc.want) + } + default: + t.Fatalf("%s: no notification", tc.description) + } + select { + case got := <-ch: + t.Fatalf("unexpected duplicate %d", got) + default: + } + cancel() + cancel() + h.publish("host", 4) + select { + case <-ch: + t.Fatal("canceled subscription received an update") + default: + } + }) + } +} + +// Run under -race: publication competes with reconnects and cancellation. +func TestNotificationConcurrentReconnect(t *testing.T) { + h := NewNotificationHub() + var wg sync.WaitGroup + for worker := range 16 { + wg.Go(func() { + id := fmt.Sprintf("host-%d", worker%4) + for i := range 100 { + ch, cancel := h.subscribe(id) + h.publish(id, uint64(i+1)) + select { + case <-ch: + default: + } + cancel() + } + }) + } + wg.Wait() + h.mu.Lock() + defer h.mu.Unlock() + if len(h.subs) != 0 { + t.Fatalf("leaked %d subscriptions", len(h.subs)) + } +} + +func BenchmarkNotificationFleet(b *testing.B) { + for _, n := range []int{100, 1000, 10000} { + b.Run(fmt.Sprint(n), func(b *testing.B) { + h := NewNotificationHub() + ids := make([]string, n) + for i := range ids { + ids[i] = fmt.Sprintf("host-%d", i) + _, cancel := h.subscribe(ids[i]) + b.Cleanup(cancel) + } + var revision uint64 + b.ReportAllocs() + for b.Loop() { + revision++ + for _, id := range ids { + h.publish(id, revision) + } + } + }) + } +} + +// scanRecorder wraps a store to record what each notification scan asked +// for and how many rows came back, and to inject a scan failure. +type scanRecorder struct { + store.Store + since []time.Time + rows []int + err error +} + +func (r *scanRecorder) Repos() store.Repos { + rp := r.Store.Repos() + rp.Agents = &recordingAgents{Agents: rp.Agents, r: r} + return rp +} + +type recordingAgents struct { + store.Agents + r *scanRecorder +} + +func (a *recordingAgents) DesiredSince(ctx context.Context, since time.Time) ([]store.DesiredRevision, error) { + if a.r.err != nil { + return nil, a.r.err + } + out, err := a.Agents.DesiredSince(ctx, since) + a.r.since = append(a.r.since, since) + a.r.rows = append(a.r.rows, len(out)) + return out, err +} + +// TestNotifyWatermark walks one scanner through a sequence of store writes +// and checks what each scan reads, what subscribers receive and where the +// watermark lands. Steps build on each other, like the scans they model. +func TestNotifyWatermark(t *testing.T) { + ctx := context.Background() + base := time.Unix(1800000000, 0).UTC() + mem := memory.New() + clock := base + mem.Now = func() time.Time { return clock } + rec := &scanRecorder{Store: mem} + s := &Server{Store: rec, Hub: NewNotificationHub()} + agents := mem.Repos().Agents + // host-2 enrolled ten seconds before host-1, so after the first scan only + // host-1's stamp sits inside the watermark's one-second lag. + for _, e := range []struct { + id string + ago time.Duration + }{{"host-2", 10 * time.Second}, {"host-1", 0}} { + clock = base.Add(-e.ago) + if err := agents.Enroll(ctx, e.id, "dc1", &treatment.DesiredState{AgentID: e.id, Revision: 1, IssuedAt: base}); err != nil { + t.Fatal(err) + } + } + subs := map[string]chan uint64{} + for _, id := range []string{"host-1", "host-2"} { + ch, cancel := s.Hub.subscribe(id) + defer cancel() + subs[id] = ch + } + delivered := func() map[string]uint64 { + got := map[string]uint64{} + for id, ch := range subs { + select { + case v := <-ch: + got[id] = v + default: + } + } + return got + } + since := time.Time{} + for _, step := range []struct { + name, description string + clock time.Duration + write func(a store.Agents) error + scanErr error + wantRows int + wantDelivered map[string]uint64 + wantWatermark time.Duration // offset from base + }{ + {"first-scan", "positive: the first scan reads every agent, publishes the current revisions and sets the watermark one lag behind the newest stamp", 0, nil, nil, 2, map[string]uint64{"host-1": 1, "host-2": 1}, -time.Second}, + {"changed-agent", "positive: a desired state saved after the watermark is read and delivered alone", 10 * time.Second, func(a store.Agents) error { + return a.SaveDesired(ctx, &treatment.DesiredState{AgentID: "host-1", Revision: 2, IssuedAt: base}) + }, nil, 1, map[string]uint64{"host-1": 2}, 9 * time.Second}, + {"no-change", "positive: with nothing saved the scan re-reads only the newest row (inside the lag), delivers nothing and keeps the watermark", 10 * time.Second, nil, nil, 1, map[string]uint64{}, 9 * time.Second}, + {"equal-timestamp", "boundary: a row stamped exactly at the watermark is read, alongside the row inside the lag, and only the new revision is delivered", 9 * time.Second, func(a store.Agents) error { + return a.SaveDesired(ctx, &treatment.DesiredState{AgentID: "host-2", Revision: 2, IssuedAt: base}) + }, nil, 2, map[string]uint64{"host-2": 2}, 9 * time.Second}, + {"equal-timestamp-repeat", "boundary: the next scan reads the same two rows again and delivers nothing twice", 9 * time.Second, nil, nil, 2, map[string]uint64{}, 9 * time.Second}, + {"scan-error", "negative: a failed scan delivers nothing and leaves the watermark where it was", 20 * time.Second, func(a store.Agents) error { + return a.SaveDesired(ctx, &treatment.DesiredState{AgentID: "host-1", Revision: 3, IssuedAt: base}) + }, errors.New("database unavailable"), 0, map[string]uint64{}, 9 * time.Second}, + {"after-error", "positive: the scan after a failure picks the change up from the kept watermark", 20 * time.Second, nil, nil, 2, map[string]uint64{"host-1": 3}, 19 * time.Second}, + {"future-stamp", "corner: a stamp far in the future is read and the watermark follows it", time.Hour, func(a store.Agents) error { + return a.SaveDesired(ctx, &treatment.DesiredState{AgentID: "host-2", Revision: 3, IssuedAt: base}) + }, nil, 2, map[string]uint64{"host-2": 3}, time.Hour - time.Second}, + {"behind-watermark", "corner: a stamp more than the lag behind the watermark is not scanned (the agent's next check-in carries it); the future row is re-read and dropped", 30 * time.Second, func(a store.Agents) error { + return a.SaveDesired(ctx, &treatment.DesiredState{AgentID: "host-1", Revision: 4, IssuedAt: base}) + }, nil, 1, map[string]uint64{}, time.Hour - time.Second}, + } { + t.Run(step.name, func(t *testing.T) { + clock = base.Add(step.clock) + if step.write != nil { + if err := step.write(agents); err != nil { + t.Fatal(err) + } + } + rec.err = step.scanErr + rec.since, rec.rows = nil, nil + since = s.notify(ctx, since) + rows := -1 + if len(rec.rows) == 1 { + rows = rec.rows[0] + } + if step.scanErr == nil && rows != step.wantRows { + t.Fatalf("%s: scan read %d rows, want %d", step.description, rows, step.wantRows) + } + if got := delivered(); !maps.Equal(got, step.wantDelivered) { + t.Fatalf("%s: delivered %v, want %v", step.description, got, step.wantDelivered) + } + if want := base.Add(step.wantWatermark); !since.Equal(want) { + t.Fatalf("%s: watermark %v, want %v", step.description, since, want) + } + }) + } +} diff --git a/pkg/treatment/controller/rpc_contracts_test.go b/pkg/treatment/controller/rpc_contracts_test.go new file mode 100644 index 000000000..b541905d9 --- /dev/null +++ b/pkg/treatment/controller/rpc_contracts_test.go @@ -0,0 +1,162 @@ +package controller + +import ( + "context" + "errors" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// TestCheckInValidation runs without a store: every row must be rejected +// before the handler touches persistence. +func TestCheckInValidation(t *testing.T) { + for _, tc := range []struct { + name, description string + change func(*pb.CheckInRequest) + expected codes.Code + }{ + {"wrong-host", "negative: certificate identity cannot report another host", func(r *pb.CheckInRequest) { r.AgentId = "other" }, codes.PermissionDenied}, + {"wrong-location", "negative: certificate location is authoritative", func(r *pb.CheckInRequest) { r.Location = "other" }, codes.InvalidArgument}, + {"missing-capabilities", "negative: capabilities must be present", func(r *pb.CheckInRequest) { r.Capabilities = nil }, codes.InvalidArgument}, + {"invalid-boot", "negative: boot identity is required", func(r *pb.CheckInRequest) { r.Capabilities.BootId = "" }, codes.InvalidArgument}, + {"long-kernel", "boundary: kernel version is bounded at 256 bytes", func(r *pb.CheckInRequest) { r.Capabilities.KernelRelease = strings.Repeat("a", 257) }, codes.InvalidArgument}, + {"long-algorithm", "boundary: algorithm names fit the 15-byte kernel ABI", func(r *pb.CheckInRequest) { r.Capabilities.CongestionAlgorithms = []string{strings.Repeat("a", 16)} }, codes.InvalidArgument}, + {"nil-record", "corner: a nil application record fails closed", func(r *pb.CheckInRequest) { r.Records = []*pb.ApplicationRecord{nil} }, codes.InvalidArgument}, + {"kernel-bytes", "corner: kernel route bytes must remain local", func(r *pb.CheckInRequest) { + r.Records = []*pb.ApplicationRecord{{Assignment: &pb.Assignment{ExperimentId: "assignment"}, InstalledRoute: []byte{1}}} + }, codes.InvalidArgument}, + {"unknown-status", "corner: an apply status from a newer agent is rejected, not defaulted", func(r *pb.CheckInRequest) { + r.Records = []*pb.ApplicationRecord{{Assignment: &pb.Assignment{ExperimentId: "assignment", Treatment: &pb.Treatment{Id: "cubic", Revision: 1, Destination: "192.0.2.1/32", Settings: &pb.TCPSettings{}}}, Status: pb.ApplyStatus(200)}} + }, codes.InvalidArgument}, + } { + t.Run(tc.name, func(t *testing.T) { + r := &pb.CheckInRequest{AgentId: "host", Location: "dc1", Capabilities: &pb.Capabilities{BootId: "boot", CollectionId: fixtures.CollectionID, CongestionAlgorithms: []string{"cubic"}}} + tc.change(r) + _, err := (&Server{}).CheckIn(testIdentity("agent/dc1/host"), r) + if status.Code(err) != tc.expected { + t.Fatalf("%s: got %v expected %v", tc.description, err, tc.expected) + } + }) + } +} + +func TestStatusAuthorization(t *testing.T) { + for _, tc := range []struct { + description, method, path, identity string + expected int + }{ + {"negative: mTLS is mandatory", "GET", "/status", "", 401}, + {"negative: agents cannot inspect fleet status", "GET", "/status", "agent/dc1/host", 403}, + {"negative: status has no mutation endpoint", "POST", "/status", "operator/alice", 405}, + {"negative: unknown paths return not found", "GET", "/unknown", "operator/alice", 404}, + } { + t.Run(tc.description, func(t *testing.T) { + w := httptest.NewRecorder() + (&Server{}).StatusHandler().ServeHTTP(w, operatorHTTP(tc.method, tc.path, tc.identity)) + if w.Code != tc.expected { + t.Fatalf("got %d expected %d", w.Code, tc.expected) + } + }) + } +} + +func TestStatusAndDesiredAuthorization(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC() + s := testServer(st, &now) + enroll(t, s, "host") + for _, tc := range []struct { + description, identity string + expected codes.Code + }{ + {"positive: enrolled identity can fetch its desired state", "agent/dc1/host", codes.OK}, + {"negative: enrollment location cannot change", "agent/other/host", codes.PermissionDenied}, + {"negative: a different host cannot fetch desired state", "agent/dc1/other", codes.PermissionDenied}, + {"negative: operator identity is not an agent", "operator/alice", codes.PermissionDenied}, + } { + t.Run(tc.description, func(t *testing.T) { + got, err := s.GetDesiredState(testIdentity(tc.identity), &pb.GetDesiredStateRequest{AgentId: "host"}) + if status.Code(err) != tc.expected { + t.Fatalf("got %v expected %v", err, tc.expected) + } + if err == nil && (got.Desired.AgentId != "host" || got.Desired.Revision != 1) { + t.Fatal("wrong desired state") + } + }) + } + for _, path := range []string{"/status", "/metrics", "/readyz"} { + t.Run(path, func(t *testing.T) { + w := httptest.NewRecorder() + s.StatusHandler().ServeHTTP(w, operatorHTTP(http.MethodGet, path, "operator/alice")) + if w.Code != 200 || w.Body.Len() == 0 { + t.Fatalf("got %d %s", w.Code, w.Body.String()) + } + if path == "/status" && !strings.Contains(w.Body.String(), `"agents":1`) { + t.Fatal("enrolled agent missing from status") + } + if path == "/metrics" && !strings.Contains(w.Body.String(), "xtcp_controller_agents_connected 1") { + t.Fatalf("connected agent missing from metrics: %s", w.Body.String()) + } + }) + } + pg, ok := st.(*postgres.Store) + if !ok { + return + } + if err := pg.Close(); err != nil { + t.Fatal(err) + } + w := httptest.NewRecorder() + s.StatusHandler().ServeHTTP(w, operatorHTTP(http.MethodGet, "/readyz", "operator/alice")) + if w.Code != 503 { + t.Fatalf("closed database reported ready: %d", w.Code) + } + }) +} + +func TestWatchLifecycle(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC() + s := testServer(st, &now) + enroll(t, s, "host") + ctx, cancel := context.WithTimeout(testIdentity("agent/dc1/host"), 5*time.Second) + defer cancel() + stream := &desiredTestStream{ctx: ctx, sent: make(chan uint64, 4)} + done := make(chan error, 1) + go func() { done <- s.WatchDesiredState(&pb.WatchDesiredStateRequest{AgentId: "host"}, stream) }() + receive := func(want uint64) { + t.Helper() + select { + case got := <-stream.sent: + if got != want { + t.Fatalf("revision=%d want %d", got, want) + } + case <-ctx.Done(): + t.Fatal("watch timed out") + } + } + receive(1) + s.Hub.publish("host", 1) + s.Hub.publish("host", 2) + receive(2) + cancel() + if err := <-done; !errors.Is(err, context.Canceled) { + t.Fatalf("watch cancellation: %v", err) + } + s.Hub.mu.Lock() + defer s.Hub.mu.Unlock() + if len(s.Hub.subs) != 0 { + t.Fatal("watch leaked subscription") + } + }) +} diff --git a/pkg/treatment/controller/server.go b/pkg/treatment/controller/server.go new file mode 100644 index 000000000..8bcf826c1 --- /dev/null +++ b/pkg/treatment/controller/server.go @@ -0,0 +1,768 @@ +// Package controller implements the treatment control plane's gRPC services +// and its background loops over the ports in package store. Handlers decode +// wire messages into domain values at the boundary (package wire), apply the +// pure rules in package experiment, and persist through a store transaction +// that serializes every control-plane mutation. +package controller + +import ( + "context" + "crypto/sha256" + "errors" + "fmt" + "sort" + "strings" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/experiment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +// agentWindow is how recently an agent must have checked in to count as +// present for eligibility, observation and lease renewal. +const agentWindow = 2 * time.Minute + +type Server struct { + pb.UnimplementedAgentControlServiceServer + pb.UnimplementedOperatorServiceServer + Store store.Store + Hub *NotificationHub + // EvidenceSource measures experiments; nil disables Analyze and lease + // renewal. Candidate discovery takes its warehouse per call. + EvidenceSource evidence.Source + Now func() time.Time + // Zero preserves the production one-hour candidate discovery window. + DiscoveryWindow time.Duration +} + +var errExperimentBudget = errors.New("data-center experiment budget exhausted (one active experiment)") +var errDiscoverySuppressed = errors.New("destination already treated, held, proposed, or in cooldown") + +func (s *Server) now() time.Time { + if s.Now != nil { + return s.Now() + } + return time.Now() +} + +// failure maps store and domain errors onto gRPC codes. Unknown errors are +// precondition failures: the request was well formed but the state refused it. +func failure(e error) error { + if e == nil { + return nil + } + if status.Code(e) != codes.Unknown { + return e + } + if errors.Is(e, store.ErrNotFound) || errors.Is(e, store.ErrNotEnrolled) { + return status.Error(codes.NotFound, "not found") + } + if errors.Is(e, context.Canceled) { + return status.Error(codes.Canceled, "canceled") + } + return status.Error(codes.FailedPrecondition, e.Error()) +} + +func invalid(e error) error { return status.Error(codes.InvalidArgument, e.Error()) } + +func validRequest(id, reason string) error { + if !treatment.ValidID(id) || strings.HasSuffix(id, ".result") || reason == "" || len(reason) > 4096 { + return status.Error(codes.InvalidArgument, "request ID and bounded reason required") + } + return nil +} + +func jsonMessage(m proto.Message) ([]byte, error) { return protojson.Marshal(m) } + +// audit appends one event whose payload is the protojson of a wire message. +func audit(ctx context.Context, rp store.Repos, actor, requestID, kind string, m proto.Message) error { + b, e := jsonMessage(m) + if e != nil { + return e + } + return rp.Audit.Append(ctx, actor, requestID, kind, b) +} + +// replay answers a repeated request ID with the original response. The +// repeat must be the same operation with the same body; anything else is a +// conflict rather than a second mutation. +func replay(ctx context.Context, rp store.Repos, id, kind string, request, response proto.Message) (bool, error) { + ev, e := rp.Audit.Lookup(ctx, id) + if errors.Is(e, store.ErrNotFound) { + return false, nil + } + if e != nil { + return false, e + } + if ev.Kind != kind { + return false, fmt.Errorf("%w for another operation", store.ErrRequestConflict) + } + want, e := jsonMessage(request) + if e != nil { + return false, e + } + stored := request.ProtoReflect().New().Interface() + if e = protojson.Unmarshal(ev.Payload, stored); e != nil { + return false, e + } + got, e := jsonMessage(stored) + if e != nil { + return false, e + } + if string(got) != string(want) { + return false, fmt.Errorf("%w with different body", store.ErrRequestConflict) + } + result, e := rp.Audit.Lookup(ctx, id+".result") + if e != nil { + return false, fmt.Errorf("missing idempotent response: %w", e) + } + return true, protojson.Unmarshal(result.Payload, response) +} + +func holdScopes(location, agentID string) []string { + return []string{"fleet", "location:" + location, "agent:" + agentID} +} + +func (s *Server) CheckIn(ctx context.Context, r *pb.CheckInRequest) (*pb.CheckInResponse, error) { + id, e := identity.Agent(ctx, r.GetAgentId()) + if e != nil { + return nil, e + } + report, e := wire.ParseReport(r) + if e != nil { + return nil, invalid(e) + } + if id.Location != report.Location || r.Capabilities == nil { + return nil, status.Error(codes.InvalidArgument, "invalid agent report") + } + if e = treatment.ValidateReport(report); e != nil { + return nil, invalid(e) + } + now := s.now() + repos := s.Store.Repos() + // New enrollment and hold inheritance are serialized against operator + // controls. The overwhelmingly common heartbeat is one independent update. + if _, e = repos.Agents.Get(ctx, report.AgentID); errors.Is(e, store.ErrNotFound) { + e = s.Store.Tx(ctx, func(rp store.Repos) error { + held, err := rp.Holds.Held(ctx, holdScopes(report.Location, report.AgentID)...) + if err != nil { + return err + } + return rp.Agents.Enroll(ctx, report.AgentID, report.Location, &treatment.DesiredState{AgentID: report.AgentID, Revision: 1, Suspended: held, IssuedAt: now}) + }) + } + if e != nil { + return nil, failure(e) + } + if e = repos.Agents.Observe(ctx, report, now); errors.Is(e, store.ErrNotEnrolled) { + return nil, status.Error(codes.PermissionDenied, "agent location cannot change during enrollment") + } else if e != nil { + return nil, failure(e) + } + d, e := repos.Agents.Desired(ctx, report.AgentID) + if e != nil { + return nil, failure(e) + } + if d.Revision == report.DesiredRevision { + return &pb.CheckInResponse{}, nil + } + return &pb.CheckInResponse{Desired: wire.Desired(d)}, nil +} + +func (s *Server) GetDesiredState(ctx context.Context, r *pb.GetDesiredStateRequest) (*pb.GetDesiredStateResponse, error) { + if e := s.authorizeEnrolledAgent(ctx, r.GetAgentId()); e != nil { + return nil, e + } + d, e := s.Store.Repos().Agents.Desired(ctx, r.AgentId) + if e != nil { + return nil, failure(e) + } + return &pb.GetDesiredStateResponse{Desired: wire.Desired(d)}, nil +} + +func (s *Server) WatchDesiredState(r *pb.WatchDesiredStateRequest, stream grpc.ServerStreamingServer[pb.WatchDesiredStateResponse]) error { + if e := s.authorizeEnrolledAgent(stream.Context(), r.GetAgentId()); e != nil { + return e + } + if s.Hub == nil { + return status.Error(codes.Unavailable, "notification service unavailable; use check-in") + } + ch, unsubscribe := s.Hub.subscribe(r.AgentId) + defer unsubscribe() + last := r.AfterRevision + d, e := s.Store.Repos().Agents.Desired(stream.Context(), r.AgentId) + if e != nil { + return failure(e) + } + if d.Revision != last { + if e = stream.Send(&pb.WatchDesiredStateResponse{Revision: d.Revision}); e != nil { + return e + } + last = d.Revision + } + for { + select { + case <-stream.Context().Done(): + return stream.Context().Err() + case revision := <-ch: + if revision > last { + if e = stream.Send(&pb.WatchDesiredStateResponse{Revision: revision}); e != nil { + return e + } + last = revision + } + } + } +} + +func (s *Server) authorizeEnrolledAgent(ctx context.Context, want string) error { + id, e := identity.Agent(ctx, want) + if e != nil { + return e + } + a, e := s.Store.Repos().Agents.Get(ctx, want) + if e != nil { + return failure(e) + } + if a.Location != id.Location { + return status.Error(codes.PermissionDenied, "agent location differs from enrollment") + } + return nil +} + +func (s *Server) Propose(ctx context.Context, r *pb.ProposeRequest) (out *pb.ProposeResponse, err error) { + actor, e := identity.Operator(ctx) + if e != nil { + return nil, e + } + out, err = s.propose(ctx, r, actor, false) + return out, failure(err) +} + +func (s *Server) propose(ctx context.Context, r *pb.ProposeRequest, actor string, discovered bool) (out *pb.ProposeResponse, err error) { + if e := validRequest(r.GetRequestId(), "proposal"); e != nil { + return nil, e + } + proposal, e := wire.ParseExperiment(r.Experiment) + if e != nil { + return nil, invalid(e) + } + if e = treatment.ValidateProposal(proposal); e != nil { + return nil, invalid(e) + } + if proposal.Treatment.Settings.Algorithm() == "" { + return nil, status.Error(codes.InvalidArgument, "v1 experiments require congestion_control to measure actual socket exposure") + } + if len(proposal.CohortOrder) < int(proposal.Policy.MinimumTreatedHosts)+2 { + return nil, status.Error(codes.InvalidArgument, "population must leave at least two controls after minimum treated hosts") + } + out = new(pb.ProposeResponse) + err = s.Store.Tx(ctx, func(rp store.Repos) error { + // Discovery's earlier lookup is only an optimization. Recheck under + // the controller mutation lock after warehouse analysis. Explicit + // operator proposals may intentionally replace a stable predecessor. + if discovered { + blocked, err := rp.Experiments.DestinationBlocked(ctx, proposal.Location, proposal.Treatment.Destination, s.now().Add(-24*time.Hour)) + if err != nil { + return err + } + if blocked { + return errDiscoverySuppressed + } + } + if yes, e := replay(ctx, rp, r.RequestId, "propose", r, out); yes || e != nil { + return e + } + exists, e := rp.Experiments.Exists(ctx, proposal.ID) + if e != nil { + return e + } + if exists { + return errors.New("experiment already exists") + } + n := proposal.Clone() + n.Revision = 1 + n.Status = treatment.StatusProposed + n.ProposedAt = s.now() + n.Phases = nil + n.LatestEvidence = nil + n.LatestOutcome = treatment.OutcomeUnspecified + active, e := rp.Experiments.HasActive(ctx, n.Location) + if e != nil { + return e + } + if active { + return errExperimentBudget + } + // Randomized, reproducible allocation within kernel strata. The full + // returned order is reviewed and persisted before any treatment occurs. + strata := map[string][]string{} + for _, id := range n.CohortOrder { + a, e := rp.Agents.Get(ctx, id) + if e != nil { + return e + } + if a.Location != n.Location || !a.Seen(s.now(), agentWindow) || !a.Report.Capabilities.SimpleHostRouting || !a.Report.Capabilities.ActuatorEnabled { + return fmt.Errorf("agent %s is not eligible", id) + } + if algo := n.Treatment.Settings.Algorithm(); algo != "" && !a.Report.Capabilities.Supports(algo) { + return fmt.Errorf("agent %s lacks %s", id, algo) + } + strata[a.Report.Capabilities.KernelRelease] = append(strata[a.Report.Capabilities.KernelRelease], id) + } + keys := make([]string, 0, len(strata)) + for k, ids := range strata { + keys = append(keys, k) + sort.Slice(ids, func(i, j int) bool { + a := sha256.Sum256([]byte(n.ID + "/" + ids[i])) + b := sha256.Sum256([]byte(n.ID + "/" + ids[j])) + return string(a[:]) < string(b[:]) + }) + } + sort.Strings(keys) + n.CohortOrder = nil + for i := 0; ; i++ { + added := false + for _, k := range keys { + if i < len(strata[k]) { + n.CohortOrder = append(n.CohortOrder, strata[k][i]) + added = true + } + } + if !added { + break + } + } + if e := s.save(ctx, rp, n); e != nil { + return e + } + out.Experiment = wire.Experiment(n) + if e := audit(ctx, rp, actor, r.RequestId, "propose", r); e != nil { + return e + } + return audit(ctx, rp, actor, r.RequestId+".result", "result", out) + }) + return out, err +} + +func (s *Server) Review(ctx context.Context, r *pb.ReviewRequest) (out *pb.ReviewResponse, err error) { + actor, e := identity.Operator(ctx) + if e != nil { + return nil, e + } + if e = validRequest(r.GetRequestId(), r.GetReason()); e != nil { + return nil, e + } + evidence, e := wire.ParseEvidence(r.Evidence) + if e != nil { + return nil, invalid(e) + } + out = new(pb.ReviewResponse) + err = s.Store.Tx(ctx, func(rp store.Repos) error { + if yes, e := replay(ctx, rp, r.RequestId, "review", r, out); yes || e != nil { + return e + } + n, e := rp.Experiments.Get(ctx, r.ExperimentId) + if e != nil { + return e + } + if n.Revision != r.ExpectedRevision { + return errors.New("experiment revision changed; review fresh evidence") + } + if !r.Approve { + if n.Status, e = experiment.Transition(n.Status, experiment.EventReject); e != nil { + return e + } + n.Revision++ + } else { + if len(n.Phases) == 0 { + if evidence != nil { + if e = saveEvidence(ctx, rp, n.ID, evidence); e != nil { + return e + } + n.Baseline = evidence.Clone() + } + if e = treatment.ValidateProposal(n); e != nil { + return e + } + if n.Baseline.AnalyzedAt.After(s.now().Add(30*time.Second)) || s.now().Sub(n.Baseline.WindowEnd) > n.Policy.MaximumEvidenceAge { + return errors.New("baseline stale/future; supply refreshed baseline evidence with review") + } + } + if len(n.Phases) > 0 { + if e = s.startObservation(ctx, rp, n); e != nil { + return e + } + if n.LatestOutcome == treatment.OutcomeAwaitingApplication { + return errors.New("cohort is not currently verified") + } + if e = saveEvidence(ctx, rp, n.ID, evidence); e != nil { + return e + } + } + n, e = experiment.Advance(n, evidence, s.now(), actor, r.Reason) + if e != nil { + return e + } + } + if e = s.assign(ctx, rp, n, false); e != nil { + return e + } + if e = s.save(ctx, rp, n); e != nil { + return e + } + out.Experiment = wire.Experiment(n) + if e = audit(ctx, rp, actor, r.RequestId, "review", r); e != nil { + return e + } + return audit(ctx, rp, actor, r.RequestId+".result", "result", out) + }) + return out, failure(err) +} + +// save stamps the controller's clock on the experiment and persists it. +func (s *Server) save(ctx context.Context, rp store.Repos, e *treatment.Experiment) error { + e.UpdatedAt = s.now() + return rp.Experiments.Save(ctx, e) +} + +func saveEvidence(ctx context.Context, rp store.Repos, experimentID string, v *treatment.Evidence) error { + if e := treatment.ValidateEvidence(v); e != nil { + return e + } + return rp.Evidence.Put(ctx, experimentID, v) +} + +// startObservation records when the whole current cohort verifiably applied +// the treatment, or marks the experiment awaiting application. +func (s *Server) startObservation(ctx context.Context, rp store.Repos, e *treatment.Experiment) error { + p := e.CurrentPhase() + if p == nil { + return nil + } + latest := p.IssuedAt + notReady := func() error { e.LatestOutcome = treatment.OutcomeAwaitingApplication; return nil } + for _, id := range e.CohortOrder[:p.TargetHosts] { + a, err := rp.Agents.Get(ctx, id) + if err != nil { + return err + } + if !a.Seen(s.now(), agentWindow) || a.Report.LocallySuspended { + return notReady() + } + d, err := rp.Agents.Desired(ctx, id) + if err != nil { + return err + } + if d.Suspended || a.Report.DesiredRevision != d.Revision { + return notReady() + } + expected := d.Find(e.ID) + if expected == nil || expected.Mode != treatment.ModeTrial || expected.LeaseExpiresAt.IsZero() || !expected.LeaseExpiresAt.After(s.now()) { + return notReady() + } + found := false + for i := range a.Report.Records { + rec := &a.Report.Records[i] + if rec.Assignment.ExperimentID == expected.ExperimentID && rec.Assignment.Generation == expected.Generation && rec.Status == treatment.ApplyVerified && !rec.ExpiredLatched && !rec.AppliedAt.IsZero() && rec.Assignment.Treatment.Equal(expected.Treatment) { + found = true + if rec.AppliedAt.After(s.now().Add(30 * time.Second)) { + return errors.New("agent clock ahead") + } + if rec.AppliedAt.After(latest) { + latest = rec.AppliedAt + } + } + } + if !found { + return notReady() + } + } + if p.ObservationStartedAt.IsZero() { + p.ObservationStartedAt = latest + } + if e.LatestOutcome == treatment.OutcomeAwaitingApplication { + e.LatestOutcome = treatment.OutcomeObserving + } + return nil +} + +// assign writes the desired state that follows from the experiment's status +// for every cohort host that is, or becomes, part of the current phase. +func (s *Server) assign(ctx context.Context, rp store.Repos, e *treatment.Experiment, reactivate bool) error { + target := e.Target() + for i, id := range e.CohortOrder { + d, err := rp.Agents.Desired(ctx, id) + if err != nil { + return err + } + a := d.Find(e.ID) + if i >= target && a == nil { + continue + } + if a == nil { + agent, err := rp.Agents.Get(ctx, id) + if err != nil { + return err + } + caps := agent.Report.Capabilities + if d.Suspended || agent.Report.LocallySuspended || !agent.Seen(s.now(), agentWindow) || !caps.SimpleHostRouting || !caps.ActuatorEnabled { + return fmt.Errorf("agent %s no longer eligible", id) + } + if !caps.Supports(e.Treatment.Settings.Algorithm()) { + return fmt.Errorf("agent %s no longer has required algorithm", id) + } + var predecessor *treatment.Treatment + for j := range d.Assignments { + x := &d.Assignments[j] + if x.Mode != treatment.ModeRetired && x.Treatment.Destination == e.Treatment.Destination { + if x.Mode != treatment.ModeStable { + return errors.New("destination already has an active trial/hold") + } + t := x.Treatment + predecessor = &t + x.Mode = treatment.ModeRetired + } + } + d.Assignments = append(d.Assignments, treatment.Assignment{ExperimentID: e.ID, Treatment: e.Treatment, Generation: 1, Predecessor: predecessor}) + a = &d.Assignments[len(d.Assignments)-1] + } + switch e.Status { + case treatment.StatusComplete: + a.Mode = treatment.ModeStable + a.LeaseExpiresAt = time.Time{} + case treatment.StatusSuspended: + a.Mode = treatment.ModeSuspended + case treatment.StatusRetired, treatment.StatusRolledBack: + a.Mode = treatment.ModeRetired + if e.Status == treatment.StatusRolledBack && a.Predecessor != nil { + a.Treatment = *a.Predecessor + a.Mode = treatment.ModeStable + a.Generation++ + } + default: + a.Mode = treatment.ModeTrial + if a.LeaseExpiresAt.IsZero() || reactivate { + a.LeaseExpiresAt = s.now().Add(treatment.TrialLease) + } + } + if reactivate { + a.Generation++ + } + d.Revision++ + d.IssuedAt = s.now() + if err = treatment.ValidateDesired(d); err != nil { + return err + } + if err = rp.Agents.SaveDesired(ctx, d); err != nil { + return err + } + } + return nil +} + +func (s *Server) Control(ctx context.Context, r *pb.ControlRequest) (out *pb.ControlResponse, err error) { + actor, e := identity.Operator(ctx) + if e != nil { + return nil, e + } + if e = validRequest(r.GetRequestId(), r.GetReason()); e != nil { + return nil, e + } + nsel := 0 + for _, x := range []string{r.ExperimentId, r.AgentId, r.Location} { + if x != "" { + if !treatment.ValidID(x) { + return nil, status.Error(codes.InvalidArgument, "invalid selector") + } + nsel++ + } + } + if r.Fleet { + nsel++ + } + if nsel != 1 || r.Action < pb.ControlAction_CONTROL_ACTION_PAUSE || r.Action > pb.ControlAction_CONTROL_ACTION_RETIRE { + return nil, status.Error(codes.InvalidArgument, "one scope and a valid action required") + } + out = new(pb.ControlResponse) + err = s.Store.Tx(ctx, func(rp store.Repos) error { + if yes, e := replay(ctx, rp, r.RequestId, "control", r, out); yes || e != nil { + return e + } + var e error + if r.ExperimentId != "" { + e = s.controlExperiment(ctx, rp, r, actor, out) + } else { + e = s.controlHolds(ctx, rp, r, out) + } + if e != nil { + return e + } + if e = audit(ctx, rp, actor, r.RequestId, "control", r); e != nil { + return e + } + return audit(ctx, rp, actor, r.RequestId+".result", "result", out) + }) + return out, failure(err) +} + +// controlExperiment applies an operator action to one experiment through +// the state machine and reissues its assignments. +func (s *Server) controlExperiment(ctx context.Context, rp store.Repos, r *pb.ControlRequest, actor string, out *pb.ControlResponse) error { + n, e := rp.Experiments.Get(ctx, r.ExperimentId) + if e != nil { + return e + } + if n.Status.Terminal() { + return errors.New("terminal experiment cannot be reactivated") + } + event, e := controlEvent(n, r.Action) + if e != nil { + return e + } + if n.Status, e = experiment.Transition(n.Status, event); e != nil { + return e + } + if event == experiment.EventResume { + p := n.CurrentPhase() + n.Phases = append(n.Phases, treatment.Phase{TargetHosts: p.TargetHosts, IssuedAt: s.now(), Reviewer: actor, Reason: r.Reason}) + } + n.Revision++ + if e = s.assign(ctx, rp, n, r.Action == pb.ControlAction_CONTROL_ACTION_RESUME); e != nil { + return e + } + if e = s.save(ctx, rp, n); e != nil { + return e + } + out.AffectedAgents = uint32(len(n.CohortOrder)) + return nil +} + +// controlHolds sets or clears a fleet, location or agent hold and reissues +// the desired state of every agent the scope covers. +func (s *Server) controlHolds(ctx context.Context, rp store.Repos, r *pb.ControlRequest, out *pb.ControlResponse) error { + if r.Action != pb.ControlAction_CONTROL_ACTION_SUSPEND && r.Action != pb.ControlAction_CONTROL_ACTION_RESUME { + return errors.New("non-experiment controls support suspend/resume only") + } + scope := "fleet" + if r.AgentId != "" { + scope = "agent:" + r.AgentId + } + if r.Location != "" { + scope = "location:" + r.Location + } + var e error + if r.Action == pb.ControlAction_CONTROL_ACTION_SUSPEND { + e = rp.Holds.Set(ctx, scope, r.Reason) + } else { + e = rp.Holds.Clear(ctx, scope) + } + if e != nil { + return e + } + hosts, e := s.holdTargets(ctx, rp, r) + if e != nil { + return e + } + for _, h := range hosts { + d, e := rp.Agents.Desired(ctx, h.ID) + if e != nil { + return e + } + if d.Suspended, e = rp.Holds.Held(ctx, holdScopes(h.Location, h.ID)...); e != nil { + return e + } + d.Revision++ + d.IssuedAt = s.now() + if e = rp.Agents.SaveDesired(ctx, d); e != nil { + return e + } + } + out.AffectedAgents = uint32(len(hosts)) + return nil +} + +// holdTargets lists the agents a hold control covers. An unknown agent is +// not an error: the hold still applies when it enrolls. +func (s *Server) holdTargets(ctx context.Context, rp store.Repos, r *pb.ControlRequest) ([]store.AgentRef, error) { + if r.AgentId == "" { + return rp.Agents.List(ctx, r.Location) + } + a, e := rp.Agents.Get(ctx, r.AgentId) + if errors.Is(e, store.ErrNotFound) { + return nil, nil + } + if e != nil { + return nil, e + } + return []store.AgentRef{{ID: a.ID, Location: a.Location}}, nil +} + +// controlEvent maps an operator action onto a state-machine event. Resume +// needs the experiment: a held completed treatment resumes as stable, a held +// trial resumes with a fresh phase, and a held proposal cannot resume at all. +func controlEvent(n *treatment.Experiment, action pb.ControlAction) (experiment.Event, error) { + switch action { + case pb.ControlAction_CONTROL_ACTION_PAUSE: + return experiment.EventPause, nil + case pb.ControlAction_CONTROL_ACTION_SUSPEND: + return experiment.EventSuspend, nil + case pb.ControlAction_CONTROL_ACTION_RETIRE: + return experiment.EventRetire, nil + case pb.ControlAction_CONTROL_ACTION_ROLLBACK: + return experiment.EventRollback, nil + case pb.ControlAction_CONTROL_ACTION_RESUME: + p := n.CurrentPhase() + if p == nil { + return 0, errors.New("proposal requires initial review") + } + if p.Outcome == treatment.OutcomeFinalSafety { + return experiment.EventResumeStable, nil + } + return experiment.EventResume, nil + case pb.ControlAction_CONTROL_ACTION_UNSPECIFIED: + } + return 0, fmt.Errorf("unknown control action %s", action) +} + +func (s *Server) Inspect(ctx context.Context, r *pb.InspectRequest) (*pb.InspectResponse, error) { + if _, e := identity.Operator(ctx); e != nil { + return nil, e + } + repos := s.Store.Repos() + out := new(pb.InspectResponse) + list, e := repos.Experiments.List(ctx, r.ExperimentId, 1000) + if e != nil { + return nil, failure(e) + } + for _, v := range list { + out.Experiments = append(out.Experiments, wire.Experiment(v)) + } + // Host details are deliberately explicit; a dashboard must not pull the + // entire fleet's route journals on every refresh. + if r.AgentId != "" { + d, e := repos.Agents.Desired(ctx, r.AgentId) + if e != nil { + return nil, failure(e) + } + out.Desired = append(out.Desired, wire.Desired(d)) + a, e := repos.Agents.Get(ctx, r.AgentId) + if e != nil { + return nil, failure(e) + } + if !a.LastSeen.IsZero() { + out.Observed = append(out.Observed, wire.Report(&a.Report)) + } + } + return out, nil +} diff --git a/pkg/treatment/controller/server_test.go b/pkg/treatment/controller/server_test.go new file mode 100644 index 000000000..fce277a51 --- /dev/null +++ b/pkg/treatment/controller/server_test.go @@ -0,0 +1,331 @@ +package controller + +import ( + "context" + "crypto/x509" + "fmt" + "net/url" + "sync" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/pgtest" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestReviewedRolloutAndPersistentFleetHold(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC().Truncate(time.Microsecond) + s := testServer(st, &now) + operator := testIdentity("operator/alice") + enrollFleet(t, s, 8) + p, e := s.Propose(operator, proposal(now)) + if e != nil { + t.Fatal(e) + } + if len(p.Experiment.Phases) != 0 { + t.Fatal("proposal applied without approval") + } + r := &pb.ReviewRequest{ExperimentId: p.Experiment.Id, ExpectedRevision: 1, Approve: true, Reason: "reviewed", RequestId: "review-1"} + v, e := s.Review(operator, r) + if e != nil { + t.Fatal(e) + } + if len(v.Experiment.Phases) != 1 || v.Experiment.Phases[0].TargetHosts != 1 { + t.Fatal("wrong initial canary") + } + replay, e := s.Review(operator, r) + if e != nil || !proto.Equal(replay, v) { + t.Fatal("review retry was not idempotent", e) + } + bad := proto.Clone(r).(*pb.ReviewRequest) + bad.Reason = "changed" + if _, e = s.Review(operator, bad); e == nil { + t.Fatal("accepted reused request ID with changed body") + } + if n := fleetAssignments(t, st); n != 1 { + t.Fatal("incorrect fleet exposure", n) + } + if _, e = s.Control(operator, &pb.ControlRequest{Fleet: true, Action: pb.ControlAction_CONTROL_ACTION_SUSPEND, Reason: "incident", RequestId: "hold-1"}); e != nil { + t.Fatal(e) + } + enroll(t, s, "new-host") + if !desiredOf(t, st, "new-host").Suspended { + t.Fatal("new host escaped persistent fleet hold") + } + // A narrower resume cannot clear the fleet-wide hold. + if _, e = s.Control(operator, &pb.ControlRequest{AgentId: "new-host", Action: pb.ControlAction_CONTROL_ACTION_RESUME, Reason: "host resume", RequestId: "resume-1"}); e != nil { + t.Fatal(e) + } + if !desiredOf(t, st, "new-host").Suspended { + t.Fatal("narrower resume overrode fleet hold") + } + if _, e = s.Review(testIdentity("agent/dc1/host-0"), r); e == nil { + t.Fatal("agent obtained operator authority") + } + }) +} + +// TestPostgresConcurrentReviewFencesReplicas is PostgreSQL-only: the fence +// under test is the advisory lock two controller replicas share. +func TestPostgresConcurrentReviewFencesReplicas(t *testing.T) { + // Deliberately not truncated: the baseline stored with a nanosecond + // clock must still re-save after a microsecond-precision read back. + now := time.Now().UTC() + s := testServer(pgtest.Open(t), &now) + operator := testIdentity("operator/alice") + enrollFleet(t, s, 8) + if _, e := s.Propose(operator, proposal(now)); e != nil { + t.Fatal(e) + } + var wg sync.WaitGroup + errs := make(chan error, 2) + for i := range 2 { + wg.Add(1) + go func(i int) { + defer wg.Done() + replica := &Server{Store: s.Store, Now: s.Now} + _, e := replica.Review(operator, &pb.ReviewRequest{ExperimentId: "experiment-1", ExpectedRevision: 1, Approve: true, Reason: "reviewed", RequestId: fmt.Sprintf("concurrent-%d", i)}) + errs <- e + }(i) + } + wg.Wait() + close(errs) + success := 0 + for e := range errs { + if e == nil { + success++ + } else { + t.Log(e) + } + } + if success != 1 { + t.Fatal("concurrent reviewers both advanced", success) + } +} + +func TestCertificateIdentityIsolation(t *testing.T) { + if _, e := identity.Agent(testIdentity("agent/dc1/host-1"), "host-2"); e == nil { + t.Fatal("cross-agent identity accepted") + } + if _, e := identity.Operator(context.Background()); e == nil { + t.Fatal("missing TLS accepted") + } + u, _ := url.Parse("spiffe://xtcp/operator/alice") + v, _ := url.Parse("spiffe://xtcp/agent/dc1/host-1") + if _, e := identity.FromCertificate(&x509.Certificate{URIs: []*url.URL{u, v}}); e == nil { + t.Fatal("ambiguous role accepted") + } +} + +func TestNotificationFanoutTenThousandAgents(t *testing.T) { + h := NewNotificationHub() + channels := make([]chan uint64, 0, 10000) + cleanup := make([]func(), 0, 10000) + for i := range 10000 { + ch, done := h.subscribe(fmt.Sprint(i)) + channels = append(channels, ch) + cleanup = append(cleanup, done) + } + for i := range 10000 { + h.publish(fmt.Sprint(i), 1) + h.publish(fmt.Sprint(i), 2) + } + for _, ch := range channels { + select { + case v := <-ch: + if v != 2 { + t.Fatal("did not coalesce latest revision") + } + default: + t.Fatal("missing suspension notification") + } + } + for _, done := range cleanup { + done() + } +} + +func TestCompleteReviewedRolloutAndStableWithdrawal(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC().Truncate(time.Microsecond) + s := testServer(st, &now) + operator := testIdentity("operator/alice") + enrollFleet(t, s, 8) + if _, e := s.Propose(operator, proposal(now)); e != nil { + t.Fatal(e) + } + approved, e := s.Review(operator, &pb.ReviewRequest{ExperimentId: "experiment-1", ExpectedRevision: 1, Approve: true, Reason: "initial review", RequestId: "approve-initial"}) + if e != nil { + t.Fatal(e) + } + n := approved.Experiment + for phase, target := range []uint32{1, 2, 4, 6, 8} { + if n.Phases[len(n.Phases)-1].TargetHosts != target { + t.Fatal("wrong cohort", n) + } + now = now.Add(31 * time.Minute) + acknowledgeFleet(t, s, n) + ev := proto.Clone(n.Baseline).(*pb.Evidence) + ev.Id = fmt.Sprintf("phase-evidence-%d", phase) + ev.WindowStart = n.Phases[len(n.Phases)-1].IssuedAt + ev.WindowEnd = timestamppb.New(now.Add(-time.Second)) + ev.AnalyzedAt = timestamppb.New(now) + for _, h := range ev.Hosts { + for i, id := range n.CohortOrder { + if h.AgentId == id && i < int(target) { + h.GoodputBps *= 1.2 + h.ExposedSockets = h.Sockets + } + } + } + if e = s.Maintain(context.Background(), fixedEvidence{parseEvidence(t, ev)}); e != nil { + t.Fatal("maintenance", e) + } + // Maintenance may renew leases but must never expand the cohort. + inspected, e := s.Inspect(operator, &pb.InspectRequest{ExperimentId: n.Id}) + if e != nil { + t.Fatal(e) + } + if inspected.Experiments[0].Revision != n.Revision || len(inspected.Experiments[0].Phases) != len(n.Phases) { + t.Fatal("maintenance promoted without review") + } + acknowledgeFleet(t, s, n) + approved, e = s.Review(operator, &pb.ReviewRequest{ExperimentId: n.Id, ExpectedRevision: n.Revision, Approve: true, Reason: "evidence reviewed", RequestId: fmt.Sprintf("approve-phase-%d", phase), Evidence: ev}) + if e != nil { + t.Fatalf("phase %d review: %v", phase, e) + } + n = approved.Experiment + } + if n.Status != pb.ExperimentStatus_EXPERIMENT_STATUS_COMPLETE { + t.Fatal("rollout did not complete") + } + for _, id := range n.CohortOrder { + d := desiredOf(t, st, id) + if d.Assignments[0].Mode != treatment.ModeStable || !d.Assignments[0].LeaseExpiresAt.IsZero() { + t.Fatal("stable treatment still leased") + } + } + for i, action := range []pb.ControlAction{pb.ControlAction_CONTROL_ACTION_SUSPEND, pb.ControlAction_CONTROL_ACTION_RESUME} { + if _, e = s.Control(operator, &pb.ControlRequest{ExperimentId: n.Id, Action: action, Reason: "withdrawal comparison", RequestId: fmt.Sprintf("withdrawal-%d", i)}); e != nil { + t.Fatal(e) + } + } + inspected, e := s.Inspect(operator, &pb.InspectRequest{ExperimentId: n.Id}) + if e != nil { + t.Fatal(e) + } + if inspected.Experiments[0].Status != pb.ExperimentStatus_EXPERIMENT_STATUS_COMPLETE { + t.Fatal("resume did not retain stable approval") + } + }) +} + +func TestFastSafetyWithdrawalBeforePromotionWindow(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC().Truncate(time.Microsecond) + s := testServer(st, &now) + operator := testIdentity("operator/alice") + enrollFleet(t, s, 8) + if _, e := s.Propose(operator, proposal(now)); e != nil { + t.Fatal(e) + } + r, e := s.Review(operator, &pb.ReviewRequest{ExperimentId: "experiment-1", ExpectedRevision: 1, Approve: true, Reason: "initial", RequestId: "initial"}) + if e != nil { + t.Fatal(e) + } + now = now.Add(5 * time.Minute) + acknowledgeFleet(t, s, r.Experiment) + ev := proto.Clone(r.Experiment.Baseline).(*pb.Evidence) + ev.Id = "harmful" + ev.WindowStart = r.Experiment.Phases[0].IssuedAt + ev.WindowEnd = timestamppb.New(now) + ev.AnalyzedAt = ev.WindowEnd + ev.Hosts[0].RetransmissionRatio = .1 + if e = s.Maintain(context.Background(), fixedEvidence{parseEvidence(t, ev)}); e != nil { + t.Fatal(e) + } + v, e := s.Inspect(operator, &pb.InspectRequest{ExperimentId: r.Experiment.Id}) + if e != nil { + t.Fatal(e) + } + if v.Experiments[0].Status != pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK { + t.Fatal("harm was not withdrawn before thirty minutes") + } + // Withdrawal leaves a retired tombstone so the agent removes the route. + for _, id := range r.Experiment.CohortOrder[:1] { + d := desiredOf(t, st, id) + if len(d.Assignments) != 1 || d.Assignments[0].Mode != treatment.ModeRetired { + t.Fatalf("withdrawn experiment left %+v", d.Assignments) + } + } + }) +} + +func TestAnalyzeRefreshesWithoutApproval(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Now().UTC().Truncate(time.Microsecond) + s := testServer(st, &now) + operator := testIdentity("operator/alice") + enrollFleet(t, s, 8) + p := proposal(now) + if _, e := s.Propose(operator, p); e != nil { + t.Fatal(e) + } + ev := proto.Clone(p.Experiment.Baseline).(*pb.Evidence) + ev.Id = "refresh-1" + s.EvidenceSource = fixedEvidence{parseEvidence(t, ev)} + out, e := s.Analyze(operator, &pb.AnalyzeRequest{ExperimentId: p.Experiment.Id, ExpectedRevision: 1}) + if e != nil || out.Outcome != pb.Outcome_OUTCOME_BASELINE { + t.Fatal("refresh", out, e) + } + inspected, e := s.Inspect(operator, &pb.InspectRequest{ExperimentId: p.Experiment.Id}) + if e != nil { + t.Fatal(e) + } + n := inspected.Experiments[0] + if n.Status != pb.ExperimentStatus_EXPERIMENT_STATUS_PROPOSED || n.Revision != 1 || len(n.Phases) > 0 || !proto.Equal(n.LatestEvidence, ev) { + t.Fatal("analysis changed rollout authority") + } + if _, e = s.Analyze(operator, &pb.AnalyzeRequest{ExperimentId: n.Id, ExpectedRevision: 2}); e == nil { + t.Fatal("stale analysis revision accepted") + } + if _, e = s.Analyze(testIdentity("agent/dc1/host-0"), &pb.AnalyzeRequest{ExperimentId: n.Id, ExpectedRevision: 1}); e == nil { + t.Fatal("agent could analyze as operator") + } + }) +} + +// TestExperimentUpdatedAtFollowsControllerClock pins the cooldown input: +// every mutation stamps updated_at from the controller clock, not the database. +func TestExperimentUpdatedAtFollowsControllerClock(t *testing.T) { + eachStore(t, func(t *testing.T, st store.Store) { + now := time.Unix(1800000000, 0).UTC() + s := testServer(st, &now) + operator := testIdentity("operator/alice") + enrollFleet(t, s, 8) + if _, e := s.Propose(operator, proposal(now)); e != nil { + t.Fatal(e) + } + if got := experimentsOf(t, st)[0]; !got.UpdatedAt.Equal(now) || !got.ProposedAt.Equal(now) { + t.Fatalf("proposal stamped %s / %s, want %s", got.ProposedAt, got.UpdatedAt, now) + } + now = now.Add(time.Hour) + if _, e := s.Control(operator, &pb.ControlRequest{ExperimentId: "experiment-1", Action: pb.ControlAction_CONTROL_ACTION_ROLLBACK, Reason: "test", RequestId: "rollback-1"}); e != nil { + t.Fatal(e) + } + got := experimentsOf(t, st)[0] + if got.Status != treatment.StatusRolledBack || !got.UpdatedAt.Equal(now) { + t.Fatalf("rollback stamped %s status %s, want %s rolled_back", got.UpdatedAt, got.Status, now) + } + if !proto.Equal(wire.Experiment(got).Treatment, proposal(now).Experiment.Treatment) { + t.Fatal("rollback changed the treatment") + } + }) +} diff --git a/pkg/treatment/controller/status.go b/pkg/treatment/controller/status.go new file mode 100644 index 000000000..1ba19dbbf --- /dev/null +++ b/pkg/treatment/controller/status.go @@ -0,0 +1,73 @@ +package controller + +import ( + "context" + "encoding/json" + "fmt" + "log" + "net/http" + "sort" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" +) + +// StatusHandler provides an operator-authenticated JSON dashboard feed and +// Prometheus metrics. Avoid destination/agent labels on fleet metrics. +func (s *Server) StatusHandler() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.TLS == nil || len(r.TLS.VerifiedChains) == 0 || len(r.TLS.PeerCertificates) == 0 { + http.Error(w, "mTLS required", http.StatusUnauthorized) + return + } + id, e := identity.FromCertificate(r.TLS.PeerCertificates[0]) + if e != nil || id.Role != identity.RoleOperator { + http.Error(w, "operator required", http.StatusForbidden) + return + } + if r.Method != http.MethodGet { + http.Error(w, "GET required", http.StatusMethodNotAllowed) + return + } + if r.URL.Path != "/status" && r.URL.Path != "/metrics" && r.URL.Path != "/readyz" { + http.NotFound(w, r) + return + } + ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second) + defer cancel() + if r.URL.Path == "/readyz" { + if e := s.Store.Ping(ctx); e != nil { + http.Error(w, "database unavailable", http.StatusServiceUnavailable) + return + } + fmt.Fprintln(w, "ready") + return + } + values, e := s.Store.Repos().Metrics.Snapshot(ctx, s.now()) + if e != nil { + http.Error(w, "status query failed", http.StatusServiceUnavailable) + return + } + if r.URL.Path == "/status" { + b, merr := json.Marshal(values) + if merr != nil { + http.Error(w, "status encoding failed", http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + if _, werr := w.Write(append(b, '\n')); werr != nil { + log.Printf("controller status: write: %v", werr) + } + return + } + keys := make([]string, 0, len(values)) + for k := range values { + keys = append(keys, k) + } + sort.Strings(keys) + w.Header().Set("Content-Type", "text/plain; version=0.0.4") + for _, k := range keys { + fmt.Fprintf(w, "# TYPE xtcp_controller_%s gauge\nxtcp_controller_%s %g\n", k, k, values[k]) + } + }) +} diff --git a/pkg/treatment/controller/store/memory/memory.go b/pkg/treatment/controller/store/memory/memory.go new file mode 100644 index 000000000..0e3729fde --- /dev/null +++ b/pkg/treatment/controller/store/memory/memory.go @@ -0,0 +1,553 @@ +// Package memory implements the controller's store ports with maps. It is +// for handler tests: it honors every sentinel error and rolls a failed Tx +// back, but it has no durability and no concurrency beyond one mutex. +package memory + +import ( + "cmp" + "context" + "maps" + "net/netip" + "slices" + "sort" + "sync" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" +) + +type agentRow struct { + store.Agent + desired treatment.DesiredState + updatedAt time.Time + sessions []treatment.Session +} + +type evidenceRow struct { + owner string + value *treatment.Evidence +} + +type experimentRow struct{ value *treatment.Experiment } + +type state struct { + agents map[string]*agentRow + experiments map[string]*experimentRow + evidence map[string]evidenceRow + holds map[string]string + events []store.Event + sequence int64 +} + +func (s *state) clone() *state { + c := &state{agents: map[string]*agentRow{}, experiments: map[string]*experimentRow{}, evidence: map[string]evidenceRow{}, holds: maps.Clone(s.holds), events: slices.Clone(s.events), sequence: s.sequence} + for k, v := range s.agents { + c.agents[k] = cloneAgent(v) + } + for k, v := range s.experiments { + c.experiments[k] = &experimentRow{value: v.value.Clone()} + } + for k, v := range s.evidence { + c.evidence[k] = evidenceRow{owner: v.owner, value: v.value.Clone()} + } + return c +} + +func cloneDesired(d *treatment.DesiredState) treatment.DesiredState { + c := *d + c.Assignments = slices.Clone(d.Assignments) + for i := range c.Assignments { + if p := c.Assignments[i].Predecessor; p != nil { + v := *p + c.Assignments[i].Predecessor = &v + } + } + return c +} + +func cloneReport(r *treatment.AgentReport) treatment.AgentReport { + c := *r + c.Capabilities.CongestionAlgorithms = slices.Clone(r.Capabilities.CongestionAlgorithms) + c.Records = slices.Clone(r.Records) + for i := range c.Records { + if p := c.Records[i].Assignment.Predecessor; p != nil { + v := *p + c.Records[i].Assignment.Predecessor = &v + } + } + return c +} + +func cloneAgent(a *agentRow) *agentRow { + c := *a + c.Report = cloneReport(&a.Report) + c.desired = cloneDesired(&a.desired) + c.sessions = slices.Clone(a.sessions) + return &c +} + +// Store satisfies store.Store. +type Store struct { + mu sync.Mutex + st *state + leases map[string]bool + // Now stamps updated_at columns; tests may pin it. + Now func() time.Time +} + +func New() *Store { + return &Store{st: &state{agents: map[string]*agentRow{}, experiments: map[string]*experimentRow{}, evidence: map[string]evidenceRow{}, holds: map[string]string{}}, leases: map[string]bool{}} +} + +func (s *Store) now() time.Time { + if s.Now != nil { + return s.Now() + } + return time.Now() +} + +func (s *Store) Ping(context.Context) error { return nil } +func (s *Store) Close() error { return nil } + +func (s *Store) Repos() store.Repos { return s.repos(true) } + +func (s *Store) repos(lock bool) store.Repos { + r := &repo{s: s, lock: lock} + return store.Repos{Agents: agentsRepo{r}, Experiments: experimentsRepo{r}, Evidence: evidenceRepo{r}, Holds: holdsRepo{r}, Audit: auditRepo{r}, Metrics: metricsRepo{r}} +} + +// Tx serializes against every other call and restores the previous state +// when fn fails, which is what a rolled-back transaction looks like. +func (s *Store) Tx(ctx context.Context, fn func(store.Repos) error) error { + s.mu.Lock() + defer s.mu.Unlock() + if err := ctx.Err(); err != nil { + return err + } + snapshot := s.st.clone() + if err := fn(s.repos(false)); err != nil { + s.st = snapshot + return err + } + return nil +} + +// Lease is a try-lock per name. Leases are not state: a rolled-back Tx +// does not release one. +func (s *Store) Lease(ctx context.Context, name string, fn func() error) (bool, error) { + if err := ctx.Err(); err != nil { + return false, err + } + s.mu.Lock() + if s.leases[name] { + s.mu.Unlock() + return false, nil + } + s.leases[name] = true + s.mu.Unlock() + defer func() { + s.mu.Lock() + delete(s.leases, name) + s.mu.Unlock() + }() + return true, fn() +} + +type repo struct { + s *Store + lock bool +} + +// One method set per port keeps the Get/List names from colliding. +type ( + agentsRepo struct{ *repo } + experimentsRepo struct{ *repo } + evidenceRepo struct{ *repo } + holdsRepo struct{ *repo } + auditRepo struct{ *repo } + metricsRepo struct{ *repo } +) + +func (r *repo) enter() func() { + if !r.lock { + return func() {} + } + r.s.mu.Lock() + return r.s.mu.Unlock +} + +// Agents + +func (r agentsRepo) Enroll(_ context.Context, id, location string, initial *treatment.DesiredState) error { + defer r.enter()() + if _, ok := r.s.st.agents[id]; ok { + return nil + } + d := cloneDesired(initial) + d.AgentID = id + r.s.st.agents[id] = &agentRow{Agent: store.Agent{ID: id, Location: location, EnrolledAt: r.s.now()}, desired: d, updatedAt: r.s.now()} + return nil +} + +func (r agentsRepo) Get(_ context.Context, id string) (*store.Agent, error) { + defer r.enter()() + a, ok := r.s.st.agents[id] + if !ok { + return nil, store.ErrNotFound + } + c := cloneAgent(a) + c.Report.AgentID, c.Report.Location = id, a.Location + return &c.Agent, nil +} + +func (r agentsRepo) Observe(_ context.Context, report *treatment.AgentReport, seen time.Time) error { + defer r.enter()() + a, ok := r.s.st.agents[report.AgentID] + if !ok || a.Location != report.Location { + return store.ErrNotEnrolled + } + a.Report = cloneReport(report) + a.LastSeen = seen + a.observeSession(report.Capabilities, seen) + return nil +} + +// observeSession mirrors the PostgreSQL upsert: insert a new session, +// refresh a known one only when its LastSeen is SessionRefresh old. +func (a *agentRow) observeSession(c treatment.Capabilities, seen time.Time) { + for i := range a.sessions { + s := &a.sessions[i] + if s.BootID == c.BootID && s.CollectionID == c.CollectionID { + if !s.LastSeen.After(seen.Add(-store.SessionRefresh)) { + s.LastSeen = seen + } + return + } + } + a.sessions = append(a.sessions, treatment.Session{AgentID: a.ID, BootID: c.BootID, CollectionID: c.CollectionID, FirstSeen: seen, LastSeen: seen}) +} + +func (r agentsRepo) Sessions(_ context.Context, ids []string, from, to time.Time) ([]treatment.Session, error) { + defer r.enter()() + var out []treatment.Session + for _, id := range ids { + a, ok := r.s.st.agents[id] + if !ok { + continue + } + var overlap []treatment.Session + for _, s := range a.sessions { + if !s.LastSeen.Before(from) && !s.FirstSeen.After(to) { + overlap = append(overlap, s) + } + } + // Keep the most recently seen, as the PostgreSQL window does. + slices.SortFunc(overlap, func(x, y treatment.Session) int { + return cmp.Or(y.LastSeen.Compare(x.LastSeen), y.FirstSeen.Compare(x.FirstSeen), cmp.Compare(x.BootID, y.BootID), cmp.Compare(x.CollectionID, y.CollectionID)) + }) + out = append(out, overlap[:min(len(overlap), store.MaxSessionsPerAgent)]...) + } + slices.SortFunc(out, func(x, y treatment.Session) int { + return cmp.Or(cmp.Compare(x.AgentID, y.AgentID), x.FirstSeen.Compare(y.FirstSeen), cmp.Compare(x.BootID, y.BootID), cmp.Compare(x.CollectionID, y.CollectionID)) + }) + return out, nil +} + +func (r agentsRepo) PruneSessions(_ context.Context, before time.Time) (int64, error) { + defer r.enter()() + var n int64 + for _, a := range r.s.st.agents { + kept := a.sessions[:0] + for _, s := range a.sessions { + if s.LastSeen.Before(before) { + n++ + continue + } + kept = append(kept, s) + } + a.sessions = kept + } + return n, nil +} + +func (r agentsRepo) Desired(_ context.Context, id string) (*treatment.DesiredState, error) { + defer r.enter()() + a, ok := r.s.st.agents[id] + if !ok { + return nil, store.ErrNotEnrolled + } + d := cloneDesired(&a.desired) + return &d, nil +} + +func (r agentsRepo) SaveDesired(_ context.Context, d *treatment.DesiredState) error { + defer r.enter()() + a, ok := r.s.st.agents[d.AgentID] + if !ok { + return store.ErrNotEnrolled + } + a.desired = cloneDesired(d) + a.updatedAt = r.s.now() + return nil +} + +func (r agentsRepo) List(_ context.Context, location string) ([]store.AgentRef, error) { + defer r.enter()() + var out []store.AgentRef + for id, a := range r.s.st.agents { + if location == "" || a.Location == location { + out = append(out, store.AgentRef{ID: id, Location: a.Location}) + } + } + sort.Slice(out, func(i, j int) bool { return out[i].ID < out[j].ID }) + return out, nil +} + +func (r agentsRepo) DesiredSince(_ context.Context, since time.Time) ([]store.DesiredRevision, error) { + defer r.enter()() + var out []store.DesiredRevision + for id, a := range r.s.st.agents { + if !a.updatedAt.Before(since) { + out = append(out, store.DesiredRevision{AgentID: id, Revision: a.desired.Revision, UpdatedAt: a.updatedAt}) + } + } + sort.Slice(out, func(i, j int) bool { + if !out[i].UpdatedAt.Equal(out[j].UpdatedAt) { + return out[i].UpdatedAt.Before(out[j].UpdatedAt) + } + return out[i].AgentID < out[j].AgentID + }) + return out, nil +} + +// Experiments + +func (r experimentsRepo) Exists(_ context.Context, id string) (bool, error) { + defer r.enter()() + _, ok := r.s.st.experiments[id] + return ok, nil +} + +func (r *repo) getExperiment(id string) (*treatment.Experiment, error) { + e, ok := r.s.st.experiments[id] + if !ok { + return nil, store.ErrNotFound + } + return e.value.Clone(), nil +} + +func (r experimentsRepo) Get(ctx context.Context, id string) (*treatment.Experiment, error) { + defer r.enter()() + return r.getExperiment(id) +} + +func (r experimentsRepo) Save(_ context.Context, e *treatment.Experiment) error { + defer r.enter()() + for _, ev := range []*treatment.Evidence{e.Baseline, e.LatestEvidence} { + if ev != nil { + if err := r.put(e.ID, ev); err != nil { + return err + } + } + } + for i := range e.Phases { + if ev := e.Phases[i].Evidence; ev != nil { + if err := r.put(e.ID, ev); err != nil { + return err + } + } + } + n := e.Clone() + if prev, ok := r.s.st.experiments[e.ID]; ok { + // The cohort is fixed at proposal; Postgres writes it once too. + n.CohortOrder = slices.Clone(prev.value.CohortOrder) + } + r.s.st.experiments[e.ID] = &experimentRow{value: n} + return nil +} + +func (r experimentsRepo) List(_ context.Context, id string, limit int) ([]*treatment.Experiment, error) { + defer r.enter()() + ids := make([]string, 0, len(r.s.st.experiments)) + for k := range r.s.st.experiments { + if id == "" || k == id { + ids = append(ids, k) + } + } + sort.Strings(ids) + if len(ids) > limit { + ids = ids[:limit] + } + out := make([]*treatment.Experiment, 0, len(ids)) + for _, k := range ids { + out = append(out, r.s.st.experiments[k].value.Clone()) + } + return out, nil +} + +func (r experimentsRepo) IDs(_ context.Context, statuses ...treatment.Status) ([]string, error) { + defer r.enter()() + var out []string + for id, e := range r.s.st.experiments { + if slices.Contains(statuses, e.value.Status) { + out = append(out, id) + } + } + sort.Strings(out) + return out, nil +} + +func (r experimentsRepo) HasActive(_ context.Context, location string) (bool, error) { + defer r.enter()() + for _, e := range r.s.st.experiments { + if e.value.Location == location && e.value.Status.Active() { + return true, nil + } + } + return false, nil +} + +func (r experimentsRepo) DestinationBlocked(_ context.Context, location string, destination netip.Prefix, since time.Time) (bool, error) { + defer r.enter()() + for _, e := range r.s.st.experiments { + if e.value.Location == location && e.value.Treatment.Destination == destination && (!e.value.Status.Terminal() || e.value.UpdatedAt.After(since)) { + return true, nil + } + } + return false, nil +} + +// Evidence + +func (r evidenceRepo) Get(_ context.Context, id string) (*treatment.Evidence, error) { + defer r.enter()() + v, ok := r.s.st.evidence[id] + if !ok { + return nil, store.ErrNotFound + } + return v.value.Clone(), nil +} + +func (r *repo) put(owner string, e *treatment.Evidence) error { + if have, ok := r.s.st.evidence[e.ID]; ok { + if have.owner != owner || !have.value.Equal(e) { + return store.ErrEvidenceConflict + } + return nil + } + r.s.st.evidence[e.ID] = evidenceRow{owner: owner, value: e.Clone()} + return nil +} + +func (r evidenceRepo) Put(_ context.Context, experimentID string, e *treatment.Evidence) error { + defer r.enter()() + return r.put(experimentID, e) +} + +// Holds + +func (r holdsRepo) Set(_ context.Context, scope, reason string) error { + defer r.enter()() + r.s.st.holds[scope] = reason + return nil +} + +func (r holdsRepo) Clear(_ context.Context, scope string) error { + defer r.enter()() + delete(r.s.st.holds, scope) + return nil +} + +func (r holdsRepo) Held(_ context.Context, scopes ...string) (bool, error) { + defer r.enter()() + for _, s := range scopes { + if _, ok := r.s.st.holds[s]; ok { + return true, nil + } + } + return false, nil +} + +// Audit + +func (r auditRepo) Append(_ context.Context, actor, requestID, kind string, payload []byte) error { + defer r.enter()() + if requestID != "" { + for i := range r.s.st.events { + if r.s.st.events[i].RequestID == requestID { + return store.ErrExists + } + } + } + r.s.st.sequence++ + r.s.st.events = append(r.s.st.events, store.Event{Sequence: r.s.st.sequence, OccurredAt: r.s.now(), Actor: actor, RequestID: requestID, Kind: kind, Payload: slices.Clone(payload)}) + return nil +} + +func (r auditRepo) Lookup(_ context.Context, requestID string) (*store.Event, error) { + defer r.enter()() + if requestID == "" { + return nil, store.ErrNotFound + } + for i := range r.s.st.events { + if r.s.st.events[i].RequestID == requestID { + e := r.s.st.events[i] + e.Payload = slices.Clone(e.Payload) + return &e, nil + } + } + return nil, store.ErrNotFound +} + +func (r auditRepo) Count(context.Context) (int64, error) { + defer r.enter()() + return int64(len(r.s.st.events)), nil +} + +// Events returns a copy of the whole log, for assertions. +func (s *Store) Events() []store.Event { + s.mu.Lock() + defer s.mu.Unlock() + return slices.Clone(s.st.events) +} + +// Metrics + +func (r metricsRepo) Snapshot(_ context.Context, now time.Time) (map[string]float64, error) { + defer r.enter()() + m := map[string]float64{"agents": 0, "agents_connected": 0, "agents_suspended": 0, "assignments": 0, "routes_verified": 0, "routes_failed": 0, "routes_expired": 0, "experiments_pending": 0, "experiments_running": 0, "experiments_complete": 0, "audit_events": float64(len(r.s.st.events))} + for _, a := range r.s.st.agents { + m["agents"]++ + if a.Seen(now, 2*time.Minute) { + m["agents_connected"]++ + } + if a.desired.Suspended || a.Report.LocallySuspended { + m["agents_suspended"]++ + } + m["assignments"] += float64(len(a.desired.Assignments)) + for i := range a.Report.Records { + switch a.Report.Records[i].Status { + case treatment.ApplyVerified: + m["routes_verified"]++ + case treatment.ApplyFailed: + m["routes_failed"]++ + case treatment.ApplyExpired: + m["routes_expired"]++ + default: + } + } + } + for _, e := range r.s.st.experiments { + switch e.value.Status { + case treatment.StatusProposed: + m["experiments_pending"]++ + case treatment.StatusRunning: + m["experiments_running"]++ + case treatment.StatusComplete: + m["experiments_complete"]++ + default: + } + } + return m, nil +} diff --git a/pkg/treatment/controller/store/memory/memory_test.go b/pkg/treatment/controller/store/memory/memory_test.go new file mode 100644 index 000000000..f4ed8d9ca --- /dev/null +++ b/pkg/treatment/controller/store/memory/memory_test.go @@ -0,0 +1,13 @@ +package memory_test + +import ( + "testing" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/memory" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/storetest" +) + +func TestMemoryConformance(t *testing.T) { + storetest.Run(t, func(*testing.T) store.Store { return memory.New() }) +} diff --git a/pkg/treatment/controller/store/pgtest/pgtest.go b/pkg/treatment/controller/store/pgtest/pgtest.go new file mode 100644 index 000000000..93eb54103 --- /dev/null +++ b/pkg/treatment/controller/store/pgtest/pgtest.go @@ -0,0 +1,130 @@ +// Package pgtest opens an isolated PostgreSQL store for tests. Each call +// creates a fresh schema on the database named by XTCP_CONTROLLER_TEST_DSN, +// points the connection's search_path at it and drops it on cleanup, so +// tests share one server without sharing rows. +package pgtest + +import ( + "context" + "database/sql" + "errors" + "fmt" + "net/url" + "os" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/stdlib" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres" +) + +// EnvDSN names the environment variable that enables PostgreSQL tests. +const EnvDSN = "XTCP_CONTROLLER_TEST_DSN" + +var sequence atomic.Int64 + +// Available reports whether a PostgreSQL DSN is configured. +func Available() bool { return os.Getenv(EnvDSN) != "" } + +// Open returns a migrated store on a private schema, or skips the test. +func Open(t testing.TB) *postgres.Store { + t.Helper() + return open(t, postgres.Open) +} + +// Counter counts the statements a store sends to PostgreSQL. +type Counter struct{ n atomic.Int64 } + +// Statements returns the number of statements sent so far. +func (c *Counter) Statements() int64 { return c.n.Load() } + +// Reset sets the count back to zero. +func (c *Counter) Reset() { c.n.Store(0) } + +func (c *Counter) TraceQueryStart(ctx context.Context, _ *pgx.Conn, _ pgx.TraceQueryStartData) context.Context { + c.n.Add(1) + return ctx +} + +func (*Counter) TraceQueryEnd(context.Context, *pgx.Conn, pgx.TraceQueryEndData) {} + +// OpenCounting is Open with every statement counted, so tests can pin how +// many round trips a repository method makes. +func OpenCounting(t testing.TB) (*postgres.Store, *Counter) { + t.Helper() + c := new(Counter) + s := open(t, func(ctx context.Context, dsn string) (*postgres.Store, error) { + cfg, err := pgx.ParseConfig(dsn) + if err != nil { + return nil, err + } + cfg.Tracer = c + db := stdlib.OpenDB(*cfg) + if err = db.PingContext(ctx); err != nil { + return nil, errors.Join(err, db.Close()) + } + return postgres.New(db), nil + }) + return s, c +} + +func open(t testing.TB, connect func(context.Context, string) (*postgres.Store, error)) *postgres.Store { + t.Helper() + dsn := os.Getenv(EnvDSN) + if dsn == "" { + t.Skipf("set %s for PostgreSQL integration tests", EnvDSN) + } + admin, err := sql.Open("pgx", dsn) + if err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithTimeout(t.Context(), 30*time.Second) + defer cancel() + schema := fmt.Sprintf("xtcp_test_%d_%d", time.Now().UnixNano(), sequence.Add(1)) + if _, err = admin.ExecContext(ctx, "CREATE SCHEMA "+schema); err != nil { + t.Fatal(errors.Join(err, admin.Close())) + } + scoped, err := withSearchPath(dsn, schema) + if err != nil { + t.Fatal(errors.Join(err, admin.Close())) + } + s, err := connect(ctx, scoped) + if err != nil { + t.Fatal(errors.Join(err, admin.Close())) + } + t.Cleanup(func() { + // The test's context is already canceled when cleanups run. + cctx, ccancel := context.WithTimeout(context.WithoutCancel(ctx), 30*time.Second) + defer ccancel() + if cerr := s.Close(); cerr != nil { + t.Error(cerr) + } + if _, derr := admin.ExecContext(cctx, "DROP SCHEMA "+schema+" CASCADE"); derr != nil { + t.Errorf("drop schema %s: %v", schema, derr) + } + if cerr := admin.Close(); cerr != nil { + t.Error(cerr) + } + }) + if err = s.Migrate(ctx); err != nil { + t.Fatal(err) + } + return s +} + +func withSearchPath(dsn, schema string) (string, error) { + if strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") { + u, err := url.Parse(dsn) + if err != nil { + return "", err + } + q := u.Query() + q.Set("search_path", schema) + u.RawQuery = q.Encode() + return u.String(), nil + } + return dsn + " search_path=" + schema, nil +} diff --git a/pkg/treatment/controller/store/postgres/agents.go b/pkg/treatment/controller/store/postgres/agents.go new file mode 100644 index 000000000..71070c0a0 --- /dev/null +++ b/pkg/treatment/controller/store/postgres/agents.go @@ -0,0 +1,281 @@ +package postgres + +import ( + "context" + "crypto/sha256" + "database/sql" + "encoding/hex" + "errors" + "fmt" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" +) + +type agents struct{ *runner } + +func (a *agents) Enroll(ctx context.Context, id, location string, initial *treatment.DesiredState) error { + return a.atomic(ctx, func(q querier) error { + res, err := q.ExecContext(ctx, `INSERT INTO xtcp_treatment_agents(id,location,desired_revision,desired_suspended,desired_issued_at,desired_updated_at) + VALUES($1,$2,$3,$4,$5,clock_timestamp()) ON CONFLICT(id) DO NOTHING`, id, location, int64(initial.Revision), initial.Suspended, initial.IssuedAt) + if err != nil { + return err + } + n, err := res.RowsAffected() + if err != nil || n == 0 { + return err + } + return insertAssignments(ctx, q, id, initial.Assignments) + }) +} + +func (a *agents) Get(ctx context.Context, id string) (*store.Agent, error) { + q := a.q() + out := &store.Agent{ID: id} + var seen sql.NullTime + var reported int64 + err := q.QueryRowContext(ctx, `SELECT location,enrolled_at,last_seen,boot_id,collection_id,kernel_release,simple_host_routing,actuator_enabled,locally_suspended,reported_revision + FROM xtcp_treatment_agents WHERE id=$1`, id).Scan(&out.Location, &out.EnrolledAt, &seen, &out.Report.Capabilities.BootID, &out.Report.Capabilities.CollectionID, &out.Report.Capabilities.KernelRelease, &out.Report.Capabilities.SimpleHostRouting, &out.Report.Capabilities.ActuatorEnabled, &out.Report.LocallySuspended, &reported) + if err != nil { + return nil, notFound(err) + } + out.LastSeen = fromNullTime(seen) + out.Report.AgentID, out.Report.Location, out.Report.DesiredRevision = id, out.Location, uint64(reported) + rows, err := q.QueryContext(ctx, "SELECT name FROM xtcp_treatment_agent_algorithms WHERE agent_id=$1 ORDER BY position", id) + if err != nil { + return nil, err + } + for rows.Next() { + var name string + if err = rows.Scan(&name); err != nil { + return nil, errors.Join(err, rows.Close()) + } + out.Report.Capabilities.CongestionAlgorithms = append(out.Report.Capabilities.CongestionAlgorithms, name) + } + if err = errors.Join(rows.Err(), rows.Close()); err != nil { + return nil, err + } + rows, err = q.QueryContext(ctx, "SELECT "+selectList(recordColumns)+" FROM xtcp_treatment_records WHERE agent_id=$1 ORDER BY position", id) + if err != nil { + return nil, err + } + for rows.Next() { + var r recordRow + if err = rows.Scan(r.targets()...); err != nil { + return nil, errors.Join(err, rows.Close()) + } + rec, err := r.value() + if err != nil { + return nil, errors.Join(err, rows.Close()) + } + out.Report.Records = append(out.Report.Records, rec) + } + if err = errors.Join(rows.Err(), rows.Close()); err != nil { + return nil, err + } + return out, nil +} + +// Observe always stamps the heartbeat columns on the agents row and records +// the reported session. The algorithm and record rows are rewritten only +// when their digest differs from the one stored with the previous report, +// and a known session's last_seen only every SessionRefresh, so a steady +// fleet costs one single-row update and one no-op upsert per check-in. +func (a *agents) Observe(ctx context.Context, report *treatment.AgentReport, seen time.Time) error { + digest := reportDigest(report) + return a.atomic(ctx, func(q querier) error { + c := report.Capabilities + var previous string + // The subquery's report_digest is the value before this update. + err := q.QueryRowContext(ctx, `UPDATE xtcp_treatment_agents AS a + SET last_seen=$3,boot_id=$4,kernel_release=$5,simple_host_routing=$6,actuator_enabled=$7, + locally_suspended=$8,reported_revision=$9,report_digest=$10,collection_id=$11 + FROM (SELECT id,report_digest FROM xtcp_treatment_agents WHERE id=$1 AND location=$2 FOR UPDATE) AS o + WHERE a.id=o.id RETURNING o.report_digest`, + report.AgentID, report.Location, seen, c.BootID, c.KernelRelease, c.SimpleHostRouting, c.ActuatorEnabled, + report.LocallySuspended, int64(report.DesiredRevision), digest, c.CollectionID).Scan(&previous) + if errors.Is(err, sql.ErrNoRows) { + return store.ErrNotEnrolled + } + if err != nil { + return err + } + if _, err = q.ExecContext(ctx, upsertSessionSQL, report.AgentID, c.BootID, c.CollectionID, seen, store.SessionRefresh.Seconds()); err != nil { + return err + } + if previous == digest { + return nil + } + if _, err = q.ExecContext(ctx, "DELETE FROM xtcp_treatment_agent_algorithms WHERE agent_id=$1", report.AgentID); err != nil { + return err + } + algos := make([][]any, len(c.CongestionAlgorithms)) + for i, name := range c.CongestionAlgorithms { + algos[i] = []any{report.AgentID, i, name} + } + if err = batchInsert(ctx, q, "xtcp_treatment_agent_algorithms", []string{agentIDColumnCst, positionColumnCst, "name"}, algos); err != nil { + return err + } + if _, err = q.ExecContext(ctx, "DELETE FROM xtcp_treatment_records WHERE agent_id=$1", report.AgentID); err != nil { + return err + } + recs := make([][]any, len(report.Records)) + for i := range report.Records { + recs[i] = recordArgs(report.AgentID, i, &report.Records[i]) + } + return batchInsert(ctx, q, "xtcp_treatment_records", recordColumns, recs) + }) +} + +// reportDigest covers exactly what Observe writes outside the agents row: +// the algorithm list and every record in the column form it would be +// inserted with. Reports with equal digests produce identical rows. +func reportDigest(report *treatment.AgentReport) string { + h := sha256.New() + for _, name := range report.Capabilities.CongestionAlgorithms { + fmt.Fprintf(h, "%s\x00", name) + } + h.Write([]byte{0xff}) + for i := range report.Records { + for _, v := range recordArgs(report.AgentID, i, &report.Records[i]) { + if t, ok := v.(time.Time); ok { + v = t.UnixNano() + } + fmt.Fprintf(h, "%v\x00", v) + } + h.Write([]byte{0xfe}) + } + return hex.EncodeToString(h.Sum(nil)) +} + +func (a *agents) Desired(ctx context.Context, id string) (*treatment.DesiredState, error) { + q := a.q() + d := &treatment.DesiredState{AgentID: id} + var revision int64 + err := q.QueryRowContext(ctx, "SELECT desired_revision,desired_suspended,desired_issued_at FROM xtcp_treatment_agents WHERE id=$1", id).Scan(&revision, &d.Suspended, &d.IssuedAt) + if errors.Is(err, sql.ErrNoRows) { + return nil, store.ErrNotEnrolled + } + if err != nil { + return nil, err + } + d.Revision = uint64(revision) + rows, err := q.QueryContext(ctx, "SELECT "+selectList(assignmentColumns)+" FROM xtcp_treatment_assignments WHERE agent_id=$1 ORDER BY position", id) + if err != nil { + return nil, err + } + for rows.Next() { + var r assignmentRow + if err = rows.Scan(r.targets()...); err != nil { + return nil, errors.Join(err, rows.Close()) + } + v, err := r.value() + if err != nil { + return nil, errors.Join(err, rows.Close()) + } + d.Assignments = append(d.Assignments, v) + } + if err = errors.Join(rows.Err(), rows.Close()); err != nil { + return nil, err + } + return d, nil +} + +func (a *agents) SaveDesired(ctx context.Context, d *treatment.DesiredState) error { + return a.atomic(ctx, func(q querier) error { + res, err := q.ExecContext(ctx, "UPDATE xtcp_treatment_agents SET desired_revision=$2,desired_suspended=$3,desired_issued_at=$4,desired_updated_at=clock_timestamp() WHERE id=$1", d.AgentID, int64(d.Revision), d.Suspended, d.IssuedAt) + if err != nil { + return err + } + if n, err := res.RowsAffected(); err != nil || n == 0 { + if err != nil { + return err + } + return store.ErrNotEnrolled + } + if _, err = q.ExecContext(ctx, "DELETE FROM xtcp_treatment_assignments WHERE agent_id=$1", d.AgentID); err != nil { + return err + } + return insertAssignments(ctx, q, d.AgentID, d.Assignments) + }) +} + +func insertAssignments(ctx context.Context, q querier, agentID string, assignments []treatment.Assignment) error { + rows := make([][]any, len(assignments)) + for i := range assignments { + rows[i] = assignmentArgs(agentID, i, &assignments[i]) + } + return batchInsert(ctx, q, "xtcp_treatment_assignments", assignmentColumns, rows) +} + +func (a *agents) List(ctx context.Context, location string) ([]store.AgentRef, error) { + rows, err := a.q().QueryContext(ctx, "SELECT id,location FROM xtcp_treatment_agents WHERE ($1='' OR location=$1) ORDER BY id", location) + if err != nil { + return nil, err + } + var out []store.AgentRef + for rows.Next() { + var r store.AgentRef + if err = rows.Scan(&r.ID, &r.Location); err != nil { + return nil, errors.Join(err, rows.Close()) + } + out = append(out, r) + } + return out, errors.Join(rows.Err(), rows.Close()) +} + +func (a *agents) DesiredSince(ctx context.Context, since time.Time) ([]store.DesiredRevision, error) { + rows, err := a.q().QueryContext(ctx, `SELECT id,desired_revision,desired_updated_at FROM xtcp_treatment_agents + WHERE desired_updated_at>=$1 ORDER BY desired_updated_at,id`, since) + if err != nil { + return nil, err + } + var out []store.DesiredRevision + for rows.Next() { + var r store.DesiredRevision + var rev int64 + if err = rows.Scan(&r.AgentID, &rev, &r.UpdatedAt); err != nil { + return nil, errors.Join(err, rows.Close()) + } + r.Revision = uint64(rev) + out = append(out, r) + } + return out, errors.Join(rows.Err(), rows.Close()) +} + +// upsertSessionSQL records a session, refreshing last_seen only when it is +// at least SessionRefresh old so heartbeats do not rewrite the row. +const upsertSessionSQL = `INSERT INTO xtcp_treatment_agent_sessions(agent_id,boot_id,collection_id,first_seen,last_seen) + VALUES($1,$2,$3,$4,$4) ON CONFLICT(agent_id,boot_id,collection_id) DO UPDATE SET last_seen=EXCLUDED.last_seen + WHERE xtcp_treatment_agent_sessions.last_seen <= EXCLUDED.last_seen - make_interval(secs => $5)` + +func (a *agents) Sessions(ctx context.Context, ids []string, from, to time.Time) ([]treatment.Session, error) { + if len(ids) == 0 { + return nil, nil + } + rows, err := a.q().QueryContext(ctx, `SELECT agent_id,boot_id,collection_id,first_seen,last_seen FROM ( + SELECT *, row_number() OVER (PARTITION BY agent_id ORDER BY last_seen DESC, first_seen DESC, boot_id, collection_id) AS recency + FROM xtcp_treatment_agent_sessions WHERE agent_id = ANY($1) AND last_seen >= $2 AND first_seen <= $3) AS s + WHERE recency <= $4 ORDER BY agent_id,first_seen,boot_id,collection_id`, ids, from, to, store.MaxSessionsPerAgent) + if err != nil { + return nil, err + } + var out []treatment.Session + for rows.Next() { + var s treatment.Session + if err = rows.Scan(&s.AgentID, &s.BootID, &s.CollectionID, &s.FirstSeen, &s.LastSeen); err != nil { + return nil, errors.Join(err, rows.Close()) + } + out = append(out, s) + } + return out, errors.Join(rows.Err(), rows.Close()) +} + +func (a *agents) PruneSessions(ctx context.Context, before time.Time) (int64, error) { + r, err := a.q().ExecContext(ctx, "DELETE FROM xtcp_treatment_agent_sessions WHERE last_seen < $1", before) + if err != nil { + return 0, err + } + return r.RowsAffected() +} diff --git a/pkg/treatment/controller/store/postgres/columns.go b/pkg/treatment/controller/store/postgres/columns.go new file mode 100644 index 000000000..4b940c542 --- /dev/null +++ b/pkg/treatment/controller/store/postgres/columns.go @@ -0,0 +1,161 @@ +package postgres + +import ( + "database/sql" + "fmt" + "net/netip" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +// treatmentColumns are stored, with a prefix, wherever a treatment is +// embedded: experiments, assignments, records and their predecessors. +var treatmentColumns = []string{"id", "revision", "destination", "congestion_control", "congestion_lock", "rto_min_ms", "initial_congestion_window", "initial_receive_window", "quick_ack", "ecn", "ecn_fabric_verified"} + +func prefixed(prefix string, columns []string) []string { + out := make([]string, len(columns)) + for i, c := range columns { + out[i] = prefix + c + } + return out +} + +// treatmentArgs renders a treatment as insert arguments in treatmentColumns +// order; a nil treatment renders as all NULLs (an absent predecessor). +func treatmentArgs(t *treatment.Treatment) []any { + if t == nil { + return make([]any, len(treatmentColumns)) + } + s := t.Settings + return []any{t.ID, int64(t.Revision), t.Destination.String(), nullString(s.CongestionControl), s.CongestionLock, nullUint32(s.RTOMinMs), nullUint32(s.InitialCongestionWindow), nullUint32(s.InitialReceiveWindow), nullBool(s.QuickAck), nullBool(s.ECN), t.ECNFabricVerified} +} + +// treatmentRow receives treatmentColumns from a scan; every column is +// nullable so the same type reads predecessors. +type treatmentRow struct { + id, destination, cc sql.NullString + revision, rto, cwnd, rwnd sql.NullInt64 + lock, quickAck, ecn, fabric sql.NullBool +} + +func (r *treatmentRow) targets() []any { + return []any{&r.id, &r.revision, &r.destination, &r.cc, &r.lock, &r.rto, &r.cwnd, &r.rwnd, &r.quickAck, &r.ecn, &r.fabric} +} + +// value rebuilds the treatment, or nil when the id column was NULL. +func (r *treatmentRow) value() (*treatment.Treatment, error) { + if !r.id.Valid { + return nil, nil + } + dest, err := netip.ParsePrefix(r.destination.String) + if err != nil { + return nil, fmt.Errorf("stored destination %q: %w", r.destination.String, err) + } + t := &treatment.Treatment{ID: r.id.String, Revision: uint64(r.revision.Int64), Destination: dest, ECNFabricVerified: r.fabric.Bool} + t.Settings = treatment.TCPSettings{CongestionLock: r.lock.Bool, CongestionControl: optString(r.cc), RTOMinMs: optUint32(r.rto), InitialCongestionWindow: optUint32(r.cwnd), InitialReceiveWindow: optUint32(r.rwnd), QuickAck: optBool(r.quickAck), ECN: optBool(r.ecn)} + return t, nil +} + +func optString(v sql.NullString) *string { + if !v.Valid { + return nil + } + s := v.String + return &s +} + +func optUint32(v sql.NullInt64) *uint32 { + if !v.Valid { + return nil + } + u := uint32(v.Int64) + return &u +} + +func optBool(v sql.NullBool) *bool { + if !v.Valid { + return nil + } + b := v.Bool + return &b +} + +// assignmentColumns are shared by assignments and the assignment half of +// records: identity, mode, lease, treatment and predecessor. +// agentIDColumnCst is the agent foreign-key column every child table shares. +const agentIDColumnCst = "agent_id" + +// positionColumnCst orders the rows of every child list. +const positionColumnCst = "position" + +var assignmentColumns = append(append([]string{agentIDColumnCst, "experiment_id", positionColumnCst, "mode", "generation", "lease_expires_at"}, prefixed("treatment_", treatmentColumns)...), prefixed("predecessor_", treatmentColumns)...) + +func assignmentArgs(agentID string, position int, a *treatment.Assignment) []any { + args := []any{agentID, a.ExperimentID, position, a.Mode.String(), int64(a.Generation), nullTime(a.LeaseExpiresAt)} + args = append(args, treatmentArgs(&a.Treatment)...) + return append(args, treatmentArgs(a.Predecessor)...) +} + +type assignmentRow struct { + agentID, experimentID, mode string + position int + generation int64 + lease sql.NullTime + treatment, predecessor treatmentRow +} + +func (r *assignmentRow) targets() []any { + t := []any{&r.agentID, &r.experimentID, &r.position, &r.mode, &r.generation, &r.lease} + t = append(t, r.treatment.targets()...) + return append(t, r.predecessor.targets()...) +} + +func (r *assignmentRow) value() (treatment.Assignment, error) { + mode, err := treatment.ParseAssignmentMode(r.mode) + if err != nil { + return treatment.Assignment{}, err + } + t, err := r.treatment.value() + if err != nil { + return treatment.Assignment{}, err + } + if t == nil { + return treatment.Assignment{}, fmt.Errorf("assignment %s/%s has no treatment", r.agentID, r.experimentID) + } + pred, err := r.predecessor.value() + if err != nil { + return treatment.Assignment{}, err + } + return treatment.Assignment{ExperimentID: r.experimentID, Treatment: *t, Mode: mode, LeaseExpiresAt: fromNullTime(r.lease), Predecessor: pred, Generation: uint64(r.generation)}, nil +} + +var recordColumns = append(append([]string{}, assignmentColumns...), "desired_revision", "status", "received_at", "attempted_at", "applied_at", "verified_at", "removed_at", "error", "expired_latched") + +func recordArgs(agentID string, position int, rec *treatment.ApplicationRecord) []any { + args := assignmentArgs(agentID, position, &rec.Assignment) + return append(args, int64(rec.DesiredRevision), rec.Status.String(), nullTime(rec.ReceivedAt), nullTime(rec.AttemptedAt), nullTime(rec.AppliedAt), nullTime(rec.VerifiedAt), nullTime(rec.RemovedAt), rec.Error, rec.ExpiredLatched) +} + +type recordRow struct { + assignmentRow + desiredRevision int64 + status, errText string + received, attempted, applied, verified, removed sql.NullTime + expiredLatched bool +} + +func (r *recordRow) targets() []any { + return append(r.assignmentRow.targets(), &r.desiredRevision, &r.status, &r.received, &r.attempted, &r.applied, &r.verified, &r.removed, &r.errText, &r.expiredLatched) +} + +func (r *recordRow) value() (treatment.ApplicationRecord, error) { + a, err := r.assignmentRow.value() + if err != nil { + return treatment.ApplicationRecord{}, err + } + st, err := treatment.ParseApplyStatus(r.status) + if err != nil { + return treatment.ApplicationRecord{}, err + } + return treatment.ApplicationRecord{Assignment: a, DesiredRevision: uint64(r.desiredRevision), Status: st, ReceivedAt: fromNullTime(r.received), AttemptedAt: fromNullTime(r.attempted), AppliedAt: fromNullTime(r.applied), VerifiedAt: fromNullTime(r.verified), RemovedAt: fromNullTime(r.removed), Error: r.errText, ExpiredLatched: r.expiredLatched}, nil +} diff --git a/pkg/treatment/controller/store/postgres/evidence.go b/pkg/treatment/controller/store/postgres/evidence.go new file mode 100644 index 000000000..01a897f7d --- /dev/null +++ b/pkg/treatment/controller/store/postgres/evidence.go @@ -0,0 +1,135 @@ +package postgres + +import ( + "context" + "crypto/sha256" + "database/sql" + "encoding/hex" + "errors" + "fmt" + "math" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" +) + +type evidence struct{ *runner } + +var hostColumns = []string{"evidence_id", positionColumnCst, agentIDColumnCst, "sockets", "bytes_acked", "goodput_bps", "retransmission_ratio", "rtt_p95_ms", "exposed_sockets", "collection_healthy", "unbound_sockets"} + +// digest is a content hash over the domain value so Put can detect reuse of +// an evidence ID for different content without reloading every host row. +// Timestamps hash at microsecond precision because that is what timestamptz +// keeps: evidence read back from the database must digest to the same value +// it was stored with. +func digest(e *treatment.Evidence) string { + h := sha256.New() + fmt.Fprintf(h, "%s\x00%d\x00%d\x00%d\x00%s\x00%s\x00%s\x00%d\x00", e.ID, e.AnalyzedAt.UnixMicro(), e.WindowStart.UnixMicro(), e.WindowEnd.UnixMicro(), e.QueryVersion, e.EnrichmentVersion, e.ArtifactSHA256, len(e.Hosts)) + for i := range e.Hosts { + v := &e.Hosts[i] + fmt.Fprintf(h, "%s\x00%d\x00%d\x00%d\x00%d\x00%d\x00%d\x00%t\x00", v.AgentID, v.Sockets, v.BytesAcked, math.Float64bits(v.GoodputBps), math.Float64bits(v.RetransmissionRatio), math.Float64bits(v.RttP95Ms), v.ExposedSockets, v.CollectionHealthy) + // Hashed only when set, so evidence stored before the column + // existed keeps the digest it was stored with. + if v.UnboundSockets != 0 { + fmt.Fprintf(h, "u%d\x00", v.UnboundSockets) + } + } + return hex.EncodeToString(h.Sum(nil)) +} + +func (v *evidence) Get(ctx context.Context, id string) (*treatment.Evidence, error) { + return getEvidence(ctx, v.q(), id) +} + +func getEvidence(ctx context.Context, q querier, id string) (*treatment.Evidence, error) { + loaded, err := getEvidenceMany(ctx, q, []string{id}) + if err != nil { + return nil, err + } + e, ok := loaded[id] + if !ok { + return nil, store.ErrNotFound + } + return e, nil +} + +// getEvidenceMany reads the named evidence documents and their host rows in +// two statements. IDs that do not exist are absent from the result. +func getEvidenceMany(ctx context.Context, q querier, ids []string) (map[string]*treatment.Evidence, error) { + out := make(map[string]*treatment.Evidence, len(ids)) + if len(ids) == 0 { + return out, nil + } + rows, err := q.QueryContext(ctx, "SELECT id,analyzed_at,window_start,window_end,query_version,enrichment_version,artifact_sha256 FROM xtcp_treatment_evidence WHERE id = ANY($1)", ids) + if err != nil { + return nil, err + } + for rows.Next() { + e := new(treatment.Evidence) + if err = rows.Scan(&e.ID, &e.AnalyzedAt, &e.WindowStart, &e.WindowEnd, &e.QueryVersion, &e.EnrichmentVersion, &e.ArtifactSHA256); err != nil { + return nil, errors.Join(err, rows.Close()) + } + out[e.ID] = e + } + if err = errors.Join(rows.Err(), rows.Close()); err != nil { + return nil, err + } + return out, loadEvidenceHosts(ctx, q, ids, out) +} + +// loadEvidenceHosts appends each evidence document's host rows in position +// order. +func loadEvidenceHosts(ctx context.Context, q querier, ids []string, into map[string]*treatment.Evidence) error { + rows, err := q.QueryContext(ctx, "SELECT evidence_id,agent_id,sockets,bytes_acked,goodput_bps,retransmission_ratio,rtt_p95_ms,exposed_sockets,collection_healthy,unbound_sockets FROM xtcp_treatment_evidence_hosts WHERE evidence_id = ANY($1) ORDER BY evidence_id,position", ids) + if err != nil { + return err + } + for rows.Next() { + var id string + var h treatment.HostEvidence + var sockets, bytes, exposed, unbound int64 + if err = rows.Scan(&id, &h.AgentID, &sockets, &bytes, &h.GoodputBps, &h.RetransmissionRatio, &h.RttP95Ms, &exposed, &h.CollectionHealthy, &unbound); err != nil { + return errors.Join(err, rows.Close()) + } + h.Sockets, h.BytesAcked, h.ExposedSockets, h.UnboundSockets = uint64(sockets), uint64(bytes), uint64(exposed), uint64(unbound) + if e, ok := into[id]; ok { + e.Hosts = append(e.Hosts, h) + } + } + return errors.Join(rows.Err(), rows.Close()) +} + +func (v *evidence) Put(ctx context.Context, experimentID string, e *treatment.Evidence) error { + return v.atomic(ctx, func(q querier) error { return putEvidence(ctx, q, experimentID, e) }) +} + +func putEvidence(ctx context.Context, q querier, experimentID string, e *treatment.Evidence) error { + if e == nil { + return errors.New("nil evidence") + } + want := digest(e) + var owner, have string + err := q.QueryRowContext(ctx, "SELECT experiment_id,digest FROM xtcp_treatment_evidence WHERE id=$1", e.ID).Scan(&owner, &have) + if err == nil { + if owner != experimentID || have != want { + return store.ErrEvidenceConflict + } + return nil + } + if !errors.Is(err, sql.ErrNoRows) { + return err + } + if _, err = q.ExecContext(ctx, `INSERT INTO xtcp_treatment_evidence(id,experiment_id,analyzed_at,window_start,window_end,query_version,enrichment_version,artifact_sha256,digest) + VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9)`, e.ID, experimentID, e.AnalyzedAt, e.WindowStart, e.WindowEnd, e.QueryVersion, e.EnrichmentVersion, e.ArtifactSHA256, want); err != nil { + if isUniqueViolation(err) { + return store.ErrEvidenceConflict + } + return err + } + rows := make([][]any, len(e.Hosts)) + for i := range e.Hosts { + h := &e.Hosts[i] + rows[i] = []any{e.ID, i, h.AgentID, int64(h.Sockets), int64(h.BytesAcked), h.GoodputBps, h.RetransmissionRatio, h.RttP95Ms, int64(h.ExposedSockets), h.CollectionHealthy, int64(h.UnboundSockets)} + } + return batchInsert(ctx, q, "xtcp_treatment_evidence_hosts", hostColumns, rows) +} diff --git a/pkg/treatment/controller/store/postgres/experiments.go b/pkg/treatment/controller/store/postgres/experiments.go new file mode 100644 index 000000000..6167f25d4 --- /dev/null +++ b/pkg/treatment/controller/store/postgres/experiments.go @@ -0,0 +1,387 @@ +package postgres + +import ( + "context" + "database/sql" + "errors" + "fmt" + "net/netip" + "slices" + "strings" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" +) + +type experiments struct{ *runner } + +var experimentColumns = append(append([]string{"id", "location", "hypothesis"}, prefixed("treatment_", treatmentColumns)...), + "minimum_observation_ns", "maximum_phase_ns", "maximum_evidence_age_ns", "minimum_sockets_per_host", "minimum_bytes_per_host", "minimum_treated_hosts", "minimum_improvement", "maximum_retransmission_increase", "maximum_rtt_increase", + "baseline_evidence_id", "status", "revision", "proposed_at", "latest_evidence_id", "latest_outcome", "updated_at") + +func evidenceID(e *treatment.Evidence) any { + if e == nil { + return nil + } + return e.ID +} + +func experimentArgs(e *treatment.Experiment) []any { + p := e.Policy + args := []any{e.ID, e.Location, e.Hypothesis} + args = append(args, treatmentArgs(&e.Treatment)...) + return append(args, int64(p.MinimumObservation), int64(p.MaximumPhase), int64(p.MaximumEvidenceAge), int64(p.MinimumSocketsPerHost), int64(p.MinimumBytesPerHost), int64(p.MinimumTreatedHosts), p.MinimumImprovement, p.MaximumRetransmissionIncrease, p.MaximumRTTIncrease, + evidenceID(e.Baseline), e.Status.String(), int64(e.Revision), nullTime(e.ProposedAt), evidenceID(e.LatestEvidence), e.LatestOutcome.String(), e.UpdatedAt) +} + +// upsertExperimentSQL updates every column but id on conflict. updated_at +// comes from the controller's clock so the discovery cooldown is testable. +var upsertExperimentSQL = func() string { + sets := make([]string, 0, len(experimentColumns)) + for _, c := range experimentColumns[1:] { + sets = append(sets, c+"=EXCLUDED."+c) + } + return insertSQL("xtcp_treatment_experiments", experimentColumns) + " ON CONFLICT(id) DO UPDATE SET " + strings.Join(sets, ",") +}() + +func (x *experiments) Exists(ctx context.Context, id string) (bool, error) { + var exists bool + err := x.q().QueryRowContext(ctx, "SELECT EXISTS(SELECT 1 FROM xtcp_treatment_experiments WHERE id=$1)", id).Scan(&exists) + return exists, err +} + +func (x *experiments) Get(ctx context.Context, id string) (*treatment.Experiment, error) { + es, err := loadMany(ctx, x.q(), x.locked(), []string{id}) + if err != nil { + return nil, err + } + if len(es) == 0 { + return nil, store.ErrNotFound + } + return es[0], nil +} + +// evidenceRefs are the evidence IDs an experiment row and its phases point +// at, resolved after every row is read. +type evidenceRefs struct { + baseline, latest sql.NullString + phases []sql.NullString +} + +// loadMany reads the experiments named by ids, in ids order, skipping IDs +// that do not exist. It runs a fixed number of statements whatever len(ids) +// is: the experiment rows, the cohorts, the phases, then every referenced +// evidence document at once. Inside Store.Tx the experiment rows are locked. +func loadMany(ctx context.Context, q querier, locked bool, ids []string) ([]*treatment.Experiment, error) { + if len(ids) == 0 { + return nil, nil + } + byID, refs, err := loadExperimentRows(ctx, q, locked, ids) + if err != nil || len(byID) == 0 { + return nil, err + } + if err = loadCohorts(ctx, q, ids, byID); err != nil { + return nil, err + } + if err = loadPhases(ctx, q, ids, byID, refs); err != nil { + return nil, err + } + if err = attachEvidence(ctx, q, byID, refs); err != nil { + return nil, err + } + out := make([]*treatment.Experiment, 0, len(byID)) + for _, id := range ids { + if e, ok := byID[id]; ok { + out = append(out, e) + } + } + return out, nil +} + +// loadExperimentRows reads the experiment rows and the evidence IDs they +// reference. +func loadExperimentRows(ctx context.Context, q querier, locked bool, ids []string) (map[string]*treatment.Experiment, map[string]*evidenceRefs, error) { + suffix := "" + if locked { + suffix = " FOR UPDATE" + } + rows, err := q.QueryContext(ctx, "SELECT "+selectList(experimentColumns)+" FROM xtcp_treatment_experiments WHERE id = ANY($1)"+suffix, ids) + if err != nil { + return nil, nil, err + } + byID := make(map[string]*treatment.Experiment, len(ids)) + refs := make(map[string]*evidenceRefs, len(ids)) + for rows.Next() { + e, r, err := scanExperiment(rows) + if err != nil { + return nil, nil, errors.Join(err, rows.Close()) + } + byID[e.ID], refs[e.ID] = e, r + } + if err = errors.Join(rows.Err(), rows.Close()); err != nil { + return nil, nil, err + } + return byID, refs, nil +} + +// scanExperiment reads one row of experimentColumns. +func scanExperiment(rows *sql.Rows) (*treatment.Experiment, *evidenceRefs, error) { + e := new(treatment.Experiment) + r := new(evidenceRefs) + var tr treatmentRow + var minObs, maxPhase, maxAge, minSockets, minBytes, minTreated, revision int64 + var status, outcome string + var proposed sql.NullTime + var updated time.Time + targets := slices.Concat([]any{&e.ID, &e.Location, &e.Hypothesis}, tr.targets(), + []any{&minObs, &maxPhase, &maxAge, &minSockets, &minBytes, &minTreated, &e.Policy.MinimumImprovement, &e.Policy.MaximumRetransmissionIncrease, &e.Policy.MaximumRTTIncrease, &r.baseline, &status, &revision, &proposed, &r.latest, &outcome, &updated}) + if err := rows.Scan(targets...); err != nil { + return nil, nil, err + } + t, err := tr.value() + if err != nil { + return nil, nil, err + } + e.Treatment = *t + e.Policy.MinimumObservation, e.Policy.MaximumPhase, e.Policy.MaximumEvidenceAge = time.Duration(minObs), time.Duration(maxPhase), time.Duration(maxAge) + e.Policy.MinimumSocketsPerHost, e.Policy.MinimumBytesPerHost, e.Policy.MinimumTreatedHosts = uint64(minSockets), uint64(minBytes), uint32(minTreated) + if e.Status, err = treatment.ParseStatus(status); err != nil { + return nil, nil, err + } + if e.LatestOutcome, err = treatment.ParseOutcome(outcome); err != nil { + return nil, nil, err + } + e.Revision, e.ProposedAt, e.UpdatedAt = uint64(revision), fromNullTime(proposed), updated + return e, r, nil +} + +// loadCohorts reads every experiment's cohort in allocation order. +func loadCohorts(ctx context.Context, q querier, ids []string, byID map[string]*treatment.Experiment) error { + rows, err := q.QueryContext(ctx, "SELECT experiment_id,agent_id FROM xtcp_treatment_cohort WHERE experiment_id = ANY($1) ORDER BY experiment_id,position", ids) + if err != nil { + return err + } + for rows.Next() { + var id, a string + if err = rows.Scan(&id, &a); err != nil { + return errors.Join(err, rows.Close()) + } + if e, ok := byID[id]; ok { + e.CohortOrder = append(e.CohortOrder, a) + } + } + return errors.Join(rows.Err(), rows.Close()) +} + +// loadPhases reads every experiment's phases in order and records each +// phase's evidence ID for attachEvidence. +func loadPhases(ctx context.Context, q querier, ids []string, byID map[string]*treatment.Experiment, refs map[string]*evidenceRefs) error { + rows, err := q.QueryContext(ctx, "SELECT experiment_id,target_hosts,issued_at,observation_started_at,evaluated_at,evidence_id,outcome,reviewer,reason FROM xtcp_treatment_phases WHERE experiment_id = ANY($1) ORDER BY experiment_id,position", ids) + if err != nil { + return err + } + for rows.Next() { + var id string + var p treatment.Phase + var ev sql.NullString + var target int64 + var issued, started, evaluated sql.NullTime + var out string + if err = rows.Scan(&id, &target, &issued, &started, &evaluated, &ev, &out, &p.Reviewer, &p.Reason); err != nil { + return errors.Join(err, rows.Close()) + } + p.TargetHosts = uint32(target) + p.IssuedAt, p.ObservationStartedAt, p.EvaluatedAt = fromNullTime(issued), fromNullTime(started), fromNullTime(evaluated) + if p.Outcome, err = treatment.ParseOutcome(out); err != nil { + return errors.Join(err, rows.Close()) + } + if e, ok := byID[id]; ok { + e.Phases = append(e.Phases, p) + refs[id].phases = append(refs[id].phases, ev) + } + } + return errors.Join(rows.Err(), rows.Close()) +} + +// attachEvidence loads every referenced evidence document once and gives +// each reference its own copy, so callers can mutate one experiment's +// evidence without touching another's. +func attachEvidence(ctx context.Context, q querier, byID map[string]*treatment.Experiment, refs map[string]*evidenceRefs) error { + seen := map[string]bool{} + var wanted []string + want := func(id sql.NullString) { + if id.Valid && !seen[id.String] { + seen[id.String] = true + wanted = append(wanted, id.String) + } + } + for _, r := range refs { + want(r.baseline) + want(r.latest) + for _, p := range r.phases { + want(p) + } + } + loaded, err := getEvidenceMany(ctx, q, wanted) + if err != nil { + return err + } + resolve := func(id sql.NullString) (*treatment.Evidence, error) { + if !id.Valid { + return nil, nil + } + v, ok := loaded[id.String] + if !ok { + return nil, fmt.Errorf("evidence %s: %w", id.String, store.ErrNotFound) + } + return v.Clone(), nil + } + for id, e := range byID { + r := refs[id] + if e.Baseline, err = resolve(r.baseline); err != nil { + return err + } + if e.LatestEvidence, err = resolve(r.latest); err != nil { + return err + } + for i := range e.Phases { + if e.Phases[i].Evidence, err = resolve(r.phases[i]); err != nil { + return err + } + } + } + return nil +} + +// Save stores the evidence the experiment carries, upserts the row, writes +// the cohort on first insert (it is immutable afterwards) and upserts phases. +func (x *experiments) Save(ctx context.Context, e *treatment.Experiment) error { + return x.atomic(ctx, func(q querier) error { + for _, ev := range []*treatment.Evidence{e.Baseline, e.LatestEvidence} { + if ev != nil { + if err := putEvidence(ctx, q, e.ID, ev); err != nil { + return err + } + } + } + for i := range e.Phases { + if ev := e.Phases[i].Evidence; ev != nil { + if err := putEvidence(ctx, q, e.ID, ev); err != nil { + return err + } + } + } + var exists bool + if err := q.QueryRowContext(ctx, "SELECT EXISTS(SELECT 1 FROM xtcp_treatment_experiments WHERE id=$1)", e.ID).Scan(&exists); err != nil { + return err + } + if _, err := q.ExecContext(ctx, upsertExperimentSQL, experimentArgs(e)...); err != nil { + return err + } + if !exists { + rows := make([][]any, len(e.CohortOrder)) + for i, a := range e.CohortOrder { + rows[i] = []any{e.ID, i, a} + } + if err := batchInsert(ctx, q, "xtcp_treatment_cohort", []string{"experiment_id", positionColumnCst, agentIDColumnCst}, rows); err != nil { + return err + } + } + for i := range e.Phases { + p := &e.Phases[i] + if _, err := q.ExecContext(ctx, `INSERT INTO xtcp_treatment_phases(experiment_id,position,target_hosts,issued_at,observation_started_at,evaluated_at,evidence_id,outcome,reviewer,reason) + VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) ON CONFLICT(experiment_id,position) DO UPDATE SET target_hosts=EXCLUDED.target_hosts,issued_at=EXCLUDED.issued_at,observation_started_at=EXCLUDED.observation_started_at,evaluated_at=EXCLUDED.evaluated_at,evidence_id=EXCLUDED.evidence_id,outcome=EXCLUDED.outcome,reviewer=EXCLUDED.reviewer,reason=EXCLUDED.reason`, + e.ID, i, int64(p.TargetHosts), nullTime(p.IssuedAt), nullTime(p.ObservationStartedAt), nullTime(p.EvaluatedAt), evidenceID(p.Evidence), p.Outcome.String(), p.Reviewer, p.Reason); err != nil { + return err + } + } + _, err := q.ExecContext(ctx, "DELETE FROM xtcp_treatment_phases WHERE experiment_id=$1 AND position>=$2", e.ID, len(e.Phases)) + return err + }) +} + +// List returns the experiment named id, or up to limit experiments ordered +// by ID when id is empty, in a fixed number of statements. +func (x *experiments) List(ctx context.Context, id string, limit int) ([]*treatment.Experiment, error) { + q := x.q() + rows, err := q.QueryContext(ctx, "SELECT id FROM xtcp_treatment_experiments WHERE ($1='' OR id=$1) ORDER BY id LIMIT $2", id, limit) + if err != nil { + return nil, err + } + var ids []string + for rows.Next() { + var v string + if err = rows.Scan(&v); err != nil { + return nil, errors.Join(err, rows.Close()) + } + ids = append(ids, v) + } + if err = errors.Join(rows.Err(), rows.Close()); err != nil { + return nil, err + } + return loadMany(ctx, q, x.locked(), ids) +} + +func statusList(statuses []treatment.Status) (string, []any) { + args := make([]any, len(statuses)) + for i, s := range statuses { + args[i] = s.String() + } + return placeholders(1, len(statuses)), args +} + +func (x *experiments) IDs(ctx context.Context, statuses ...treatment.Status) ([]string, error) { + if len(statuses) == 0 { + return nil, nil + } + in, args := statusList(statuses) + rows, err := x.q().QueryContext(ctx, "SELECT id FROM xtcp_treatment_experiments WHERE status IN ("+in+") ORDER BY id", args...) + if err != nil { + return nil, err + } + var out []string + for rows.Next() { + var id string + if err = rows.Scan(&id); err != nil { + return nil, errors.Join(err, rows.Close()) + } + out = append(out, id) + } + return out, errors.Join(rows.Err(), rows.Close()) +} + +func activeStatuses() []treatment.Status { + var out []treatment.Status + for _, s := range treatment.Statuses() { + if s.Active() { + out = append(out, s) + } + } + return out +} + +// hasActiveSQL and destinationBlockedSQL are the two hot discovery lookups; +// TestPostgresExperimentQueryIndexes pins the indexes that serve them. +var hasActiveSQL = func() string { + names := make([]string, 0, 4) + for _, s := range activeStatuses() { + names = append(names, "'"+s.String()+"'") + } + return "SELECT EXISTS(SELECT 1 FROM xtcp_treatment_experiments WHERE location=$1 AND status IN (" + strings.Join(names, ",") + "))" +}() + +const destinationBlockedSQL = `SELECT EXISTS(SELECT 1 FROM xtcp_treatment_experiments + WHERE location=$1 AND treatment_destination=$2::cidr AND (status NOT IN ('retired','rolled_back') OR updated_at > $3))` + +func (x *experiments) HasActive(ctx context.Context, location string) (bool, error) { + var exists bool + err := x.q().QueryRowContext(ctx, hasActiveSQL, location).Scan(&exists) + return exists, err +} + +func (x *experiments) DestinationBlocked(ctx context.Context, location string, destination netip.Prefix, since time.Time) (bool, error) { + var exists bool + err := x.q().QueryRowContext(ctx, destinationBlockedSQL, location, destination.String(), since).Scan(&exists) + return exists, err +} diff --git a/pkg/treatment/controller/store/postgres/export_test.go b/pkg/treatment/controller/store/postgres/export_test.go new file mode 100644 index 000000000..4864943e8 --- /dev/null +++ b/pkg/treatment/controller/store/postgres/export_test.go @@ -0,0 +1,7 @@ +package postgres + +// Query strings the index test pins to their indexes. +var ( + HasActiveSQL = hasActiveSQL + DestinationBlockedSQL = destinationBlockedSQL +) diff --git a/pkg/treatment/controller/store/postgres/heartbeat_test.go b/pkg/treatment/controller/store/postgres/heartbeat_test.go new file mode 100644 index 000000000..9c6d025ae --- /dev/null +++ b/pkg/treatment/controller/store/postgres/heartbeat_test.go @@ -0,0 +1,113 @@ +package postgres_test + +import ( + "slices" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/pgtest" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +// rowVersions returns the xmin of each child row for the agent, in position +// order. PostgreSQL assigns a new xmin whenever a row is written, so equal +// slices across two Observe calls prove the second call did not rewrite. +func rowVersions(t *testing.T, s *postgres.Store, table, agent string) []string { + t.Helper() + rows, err := s.DB().Query("SELECT xmin::text FROM "+table+" WHERE agent_id=$1 ORDER BY position", agent) + if err != nil { + t.Fatal(err) + } + defer rows.Close() + var out []string + for rows.Next() { + var v string + if err := rows.Scan(&v); err != nil { + t.Fatal(err) + } + out = append(out, v) + } + if err := rows.Err(); err != nil { + t.Fatal(err) + } + return out +} + +func sampleReport() *treatment.AgentReport { + now := time.Unix(1700000000, 0).UTC() + d := fixtures.Desired(now) + return &treatment.AgentReport{ + AgentID: "host-1", Location: "dc1", + Capabilities: treatment.Capabilities{BootID: "boot-1", CollectionID: fixtures.CollectionID, KernelRelease: "6.12.0", CongestionAlgorithms: []string{"cubic", "bbr"}, ActuatorEnabled: true}, + DesiredRevision: 3, + Records: []treatment.ApplicationRecord{ + {Assignment: d.Assignments[0], DesiredRevision: 3, Status: treatment.ApplyVerified, ReceivedAt: now, AppliedAt: now.Add(time.Second), VerifiedAt: now.Add(2 * time.Second)}, + {Assignment: treatment.Assignment{ExperimentID: "old", Generation: 2, Mode: treatment.ModeRetired, Treatment: fixtures.Treatment()}, DesiredRevision: 2, Status: treatment.ApplyFailed, Error: "ENETUNREACH"}, + }, + } +} + +// TestPostgresObserveRewritesOnlyChangedReports checks the heartbeat split: +// every check-in stamps the agents row, but the algorithm and record rows +// are written only when the report content behind them changed. +func TestPostgresObserveRewritesOnlyChangedReports(t *testing.T) { + for _, tc := range []struct { + name, description string + mutate func(r *treatment.AgentReport) + expectRewrite bool + }{ + {"identical", "positive: an identical report leaves every record and algorithm row untouched", func(*treatment.AgentReport) {}, false}, + {"heartbeat-only", "positive: boot ID, kernel, local suspension and reported revision live on the agents row and do not rewrite records", func(r *treatment.AgentReport) { + r.Capabilities.BootID, r.Capabilities.KernelRelease, r.LocallySuspended, r.DesiredRevision = "boot-2", "6.13.0", true, 4 + }, false}, + {"record-status", "negative: a record status change rewrites the record rows", func(r *treatment.AgentReport) { r.Records[1].Status = treatment.ApplyRemoved }, true}, + {"record-timestamp", "boundary: a one-nanosecond timestamp change is a change", func(r *treatment.AgentReport) { r.Records[0].VerifiedAt = r.Records[0].VerifiedAt.Add(time.Nanosecond) }, true}, + {"record-order", "corner: the same records in a different order are a different report", func(r *treatment.AgentReport) { + r.Records[0], r.Records[1] = r.Records[1], r.Records[0] + }, true}, + {"algorithm-list", "negative: a changed algorithm list rewrites the algorithm rows", func(r *treatment.AgentReport) { + r.Capabilities.CongestionAlgorithms = []string{"bbr", "cubic"} + }, true}, + {"records-dropped", "boundary: a report with no records removes the rows", func(r *treatment.AgentReport) { r.Records = nil }, true}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Log(tc.description) + s := pgtest.Open(t) + ctx := t.Context() + a := s.Repos().Agents + first := sampleReport() + if err := a.Enroll(ctx, "host-1", "dc1", &treatment.DesiredState{AgentID: "host-1", Revision: 1, IssuedAt: time.Unix(1700000000, 0)}); err != nil { + t.Fatal(err) + } + seen := time.Unix(1700000100, 0).UTC() + if err := a.Observe(ctx, first, seen); err != nil { + t.Fatal(err) + } + records, algorithms := rowVersions(t, s, "xtcp_treatment_records", "host-1"), rowVersions(t, s, "xtcp_treatment_agent_algorithms", "host-1") + if len(records) != 2 || len(algorithms) != 2 { + t.Fatalf("expected two records and two algorithms after the first report, got %d and %d", len(records), len(algorithms)) + } + second := sampleReport() + tc.mutate(second) + if err := a.Observe(ctx, second, seen.Add(30*time.Second)); err != nil { + t.Fatal(err) + } + got, err := a.Get(ctx, "host-1") + if err != nil { + t.Fatal(err) + } + if !got.LastSeen.Equal(seen.Add(30*time.Second)) || got.Report.Capabilities.BootID != second.Capabilities.BootID || got.Report.DesiredRevision != second.DesiredRevision { + t.Fatalf("expected the heartbeat columns from the second report, got %+v", got) + } + if len(got.Report.Records) != len(second.Records) { + t.Fatalf("expected %d records read back, got %d", len(second.Records), len(got.Report.Records)) + } + rewritten := !slices.Equal(records, rowVersions(t, s, "xtcp_treatment_records", "host-1")) || !slices.Equal(algorithms, rowVersions(t, s, "xtcp_treatment_agent_algorithms", "host-1")) + if rewritten != tc.expectRewrite { + t.Fatalf("expected rewrite=%t, got %t", tc.expectRewrite, rewritten) + } + }) + } +} diff --git a/pkg/treatment/controller/store/postgres/holds.go b/pkg/treatment/controller/store/postgres/holds.go new file mode 100644 index 000000000..9cac6aa7d --- /dev/null +++ b/pkg/treatment/controller/store/postgres/holds.go @@ -0,0 +1,87 @@ +package postgres + +import ( + "context" + "database/sql" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" +) + +type holds struct{ *runner } + +func (h *holds) Set(ctx context.Context, scope, reason string) error { + _, err := h.q().ExecContext(ctx, "INSERT INTO xtcp_treatment_holds(scope,reason) VALUES($1,$2) ON CONFLICT(scope) DO UPDATE SET reason=EXCLUDED.reason", scope, reason) + return err +} + +func (h *holds) Clear(ctx context.Context, scope string) error { + _, err := h.q().ExecContext(ctx, "DELETE FROM xtcp_treatment_holds WHERE scope=$1", scope) + return err +} + +func (h *holds) Held(ctx context.Context, scopes ...string) (bool, error) { + if len(scopes) == 0 { + return false, nil + } + args := make([]any, len(scopes)) + for i, s := range scopes { + args[i] = s + } + var held bool + err := h.q().QueryRowContext(ctx, "SELECT EXISTS(SELECT 1 FROM xtcp_treatment_holds WHERE scope IN ("+placeholders(1, len(scopes))+"))", args...).Scan(&held) + return held, err +} + +type audit struct{ *runner } + +func (a *audit) Append(ctx context.Context, actor, requestID, kind string, payload []byte) error { + if len(payload) == 0 { + payload = []byte("{}") + } + _, err := a.q().ExecContext(ctx, "INSERT INTO xtcp_treatment_events(actor,request_id,kind,payload) VALUES($1,NULLIF($2,''),$3,$4::jsonb)", actor, requestID, kind, string(payload)) + if isUniqueViolation(err) { + return store.ErrExists + } + return err +} + +func (a *audit) Lookup(ctx context.Context, requestID string) (*store.Event, error) { + e := &store.Event{} + var rid sql.NullString + err := a.q().QueryRowContext(ctx, "SELECT sequence,occurred_at,actor,request_id,kind,payload FROM xtcp_treatment_events WHERE request_id=$1", requestID).Scan(&e.Sequence, &e.OccurredAt, &e.Actor, &rid, &e.Kind, &e.Payload) + if err != nil { + return nil, notFound(err) + } + e.RequestID = rid.String + return e, nil +} + +func (a *audit) Count(ctx context.Context) (int64, error) { + var n int64 + err := a.q().QueryRowContext(ctx, "SELECT count(*) FROM xtcp_treatment_events").Scan(&n) + return n, err +} + +type metrics struct{ *runner } + +// Snapshot answers the status page in one round trip. +func (m *metrics) Snapshot(ctx context.Context, now time.Time) (map[string]float64, error) { + var agents, connected, suspended, assignments, verified, failed, expired, pending, running, complete, events float64 + err := m.q().QueryRowContext(ctx, `SELECT + (SELECT count(*) FROM xtcp_treatment_agents), + (SELECT count(*) FROM xtcp_treatment_agents WHERE last_seen > $1), + (SELECT count(*) FROM xtcp_treatment_agents WHERE desired_suspended OR locally_suspended), + (SELECT count(*) FROM xtcp_treatment_assignments), + (SELECT count(*) FROM xtcp_treatment_records WHERE status='verified'), + (SELECT count(*) FROM xtcp_treatment_records WHERE status='failed'), + (SELECT count(*) FROM xtcp_treatment_records WHERE status='expired'), + (SELECT count(*) FROM xtcp_treatment_experiments WHERE status='proposed'), + (SELECT count(*) FROM xtcp_treatment_experiments WHERE status='running'), + (SELECT count(*) FROM xtcp_treatment_experiments WHERE status='complete'), + (SELECT count(*) FROM xtcp_treatment_events)`, now.Add(-2*time.Minute)).Scan(&agents, &connected, &suspended, &assignments, &verified, &failed, &expired, &pending, &running, &complete, &events) + if err != nil { + return nil, err + } + return map[string]float64{"agents": agents, "agents_connected": connected, "agents_suspended": suspended, "assignments": assignments, "routes_verified": verified, "routes_failed": failed, "routes_expired": expired, "experiments_pending": pending, "experiments_running": running, "experiments_complete": complete, "audit_events": events}, nil +} diff --git a/pkg/treatment/controller/store/postgres/postgres.go b/pkg/treatment/controller/store/postgres/postgres.go new file mode 100644 index 000000000..28567ea53 --- /dev/null +++ b/pkg/treatment/controller/store/postgres/postgres.go @@ -0,0 +1,304 @@ +// Package postgres implements the controller's store ports on PostgreSQL +// through database/sql with the pgx driver. Every SQL string in the +// controller lives in this package. +package postgres + +import ( + "context" + "database/sql" + "database/sql/driver" + _ "embed" + "errors" + "fmt" + "strings" + "time" + + "github.com/jackc/pgx/v5/pgconn" + _ "github.com/jackc/pgx/v5/stdlib" // registers the "pgx" database/sql driver + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" +) + +//go:embed schema.sql +var schema string + +// mutationLock is the transaction-level advisory lock every Store.Tx takes. +// It fences controller replicas without electing a leader. +const mutationLock = 867530902 + +// Store is a connection pool. It satisfies store.Store. +type Store struct{ db *sql.DB } + +// Open connects, pings and returns the store. The DSN is anything pgx +// accepts (a URL or key=value pairs). +func Open(ctx context.Context, dsn string) (*Store, error) { + db, err := sql.Open("pgx", dsn) + if err != nil { + return nil, err + } + db.SetMaxOpenConns(32) + db.SetMaxIdleConns(8) + db.SetConnMaxLifetime(30 * time.Minute) + if err = db.PingContext(ctx); err != nil { + return nil, errors.Join(err, db.Close()) + } + return &Store{db: db}, nil +} + +// New wraps an existing pool; tests use it with a per-test search_path. +func New(db *sql.DB) *Store { return &Store{db: db} } + +// Migrate creates every table and index that does not exist yet. +func (s *Store) Migrate(ctx context.Context) error { + _, err := s.db.ExecContext(ctx, schema) + return err +} + +func (s *Store) Ping(ctx context.Context) error { return s.db.PingContext(ctx) } +func (s *Store) Close() error { return s.db.Close() } + +// DB exposes the pool for tests that inspect query plans. +func (s *Store) DB() *sql.DB { return s.db } + +func (s *Store) Repos() store.Repos { return repos(&runner{db: s.db}) } + +// Tx runs fn in one transaction holding the mutation lock. Agent heartbeats +// go through Repos and never take it. +func (s *Store) Tx(ctx context.Context, fn func(store.Repos) error) (err error) { + tx, err := s.db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer rollback(tx, &err) + if _, err = tx.ExecContext(ctx, "SELECT pg_advisory_xact_lock($1)", mutationLock); err != nil { + return err + } + if err = fn(repos(&runner{tx: tx})); err != nil { + return err + } + return tx.Commit() +} + +// Lease takes a session-level advisory lock on a dedicated connection, so +// it outlives any transaction and ends when fn returns or the connection +// drops. Names hash into the same key space as mutationLock; the lock a +// name maps to is stable across replicas because the hash is. +func (s *Store) Lease(ctx context.Context, name string, fn func() error) (held bool, err error) { + conn, err := s.db.Conn(ctx) + if err != nil { + return false, err + } + defer func() { + // A connection discarded after a failed unlock reports ErrConnDone. + if cerr := conn.Close(); cerr != nil && !errors.Is(cerr, sql.ErrConnDone) && err == nil { + err = cerr + } + }() + key := leaseKey(name) + if err = conn.QueryRowContext(ctx, "SELECT pg_try_advisory_lock($1)", key).Scan(&held); err != nil { + return false, err + } + if !held { + return false, nil + } + defer func() { + unlockCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), leaseUnlockTimeoutCst) + defer cancel() + if _, e := conn.ExecContext(unlockCtx, "SELECT pg_advisory_unlock($1)", key); e != nil { + // A pooled connection must never carry the lock into its next + // use; discarding it releases the session lock server-side, so + // the expected ErrBadConn is the success case here. + err = errors.Join(err, fmt.Errorf("lease %s unlock: %w", name, e)) + if derr := conn.Raw(func(any) error { return driver.ErrBadConn }); !errors.Is(derr, driver.ErrBadConn) { + err = errors.Join(err, derr) + } + } + }() + return true, fn() +} + +// leaseUnlockTimeoutCst bounds the unlock that runs after the caller's +// context may already be canceled. +const leaseUnlockTimeoutCst = 5 * time.Second + +// leaseKey is the 64-bit FNV-1a hash of name, so every replica maps a name +// to the same advisory lock. +func leaseKey(name string) int64 { + h := uint64(14695981039346656037) + for i := 0; i < len(name); i++ { + h ^= uint64(name[i]) + h *= 1099511628211 + } + return int64(h) +} + +// rollback ends a transaction that did not commit. After Commit it reports +// ErrTxDone, which is expected; any other failure is kept when the +// transaction's own result was success. +func rollback(tx *sql.Tx, err *error) { + if rerr := tx.Rollback(); rerr != nil && !errors.Is(rerr, sql.ErrTxDone) && *err == nil { + *err = rerr + } +} + +func repos(r *runner) store.Repos { + return store.Repos{Agents: &agents{r}, Experiments: &experiments{r}, Evidence: &evidence{r}, Holds: &holds{r}, Audit: &audit{r}, Metrics: &metrics{r}} +} + +// querier is what *sql.DB and *sql.Tx have in common. +type querier interface { + ExecContext(context.Context, string, ...any) (sql.Result, error) + QueryContext(context.Context, string, ...any) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...any) *sql.Row +} + +// runner binds a repository to either the pool or an open transaction. +type runner struct { + db *sql.DB + tx *sql.Tx +} + +func (r *runner) q() querier { + if r.tx != nil { + return r.tx + } + return r.db +} + +// locked reports whether the caller is inside Store.Tx, in which case reads +// that precede writes lock their rows. +func (r *runner) locked() bool { return r.tx != nil } + +// atomic runs fn in the open transaction, or in a short private one when the +// repository is bound to the pool, so multi-statement writes stay consistent +// without the mutation lock. +func (r *runner) atomic(ctx context.Context, fn func(querier) error) (err error) { + if r.tx != nil { + return fn(r.tx) + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return err + } + defer rollback(tx, &err) + if err = fn(tx); err != nil { + return err + } + return tx.Commit() +} + +func isUniqueViolation(err error) bool { + var pg *pgconn.PgError + return errors.As(err, &pg) && pg.Code == "23505" +} + +func notFound(err error) error { + if errors.Is(err, sql.ErrNoRows) { + return store.ErrNotFound + } + return err +} + +// placeholders returns "$start,$start+1,...". +func placeholders(start, n int) string { + parts := make([]string, n) + for i := range n { + parts[i] = fmt.Sprintf("$%d", start+i) + } + return strings.Join(parts, ",") +} + +// insertSQL builds INSERT INTO table(columns) VALUES($1,...). Columns named +// *_destination are cast to cidr. +func insertSQL(table string, columns []string) string { + vals := make([]string, len(columns)) + for i, c := range columns { + vals[i] = fmt.Sprintf("$%d", i+1) + if strings.HasSuffix(c, "destination") { + vals[i] += "::cidr" + } + } + return "INSERT INTO " + table + "(" + strings.Join(columns, ",") + ") VALUES(" + strings.Join(vals, ",") + ")" +} + +// selectList renders columns for SELECT, reading cidr columns as text. +func selectList(columns []string) string { + out := make([]string, len(columns)) + for i, c := range columns { + out[i] = c + if strings.HasSuffix(c, "destination") { + out[i] = c + "::text" + } + } + return strings.Join(out, ",") +} + +// batchInsert inserts rows in chunks that stay under PostgreSQL's parameter +// limit. rows must all have len(columns) values. +func batchInsert(ctx context.Context, q querier, table string, columns []string, rows [][]any) error { + if len(rows) == 0 { + return nil + } + chunk := max(1, 60000/len(columns)) + for start := 0; start < len(rows); start += chunk { + end := min(start+chunk, len(rows)) + var sb strings.Builder + sb.WriteString("INSERT INTO " + table + "(" + strings.Join(columns, ",") + ") VALUES") + args := make([]any, 0, (end-start)*len(columns)) + for i, row := range rows[start:end] { + if i > 0 { + sb.WriteByte(',') + } + sb.WriteByte('(') + for j, c := range columns { + if j > 0 { + sb.WriteByte(',') + } + fmt.Fprintf(&sb, "$%d", len(args)+1) + if strings.HasSuffix(c, "destination") { + sb.WriteString("::cidr") + } + args = append(args, row[j]) + } + sb.WriteByte(')') + } + if _, err := q.ExecContext(ctx, sb.String(), args...); err != nil { + return err + } + } + return nil +} + +func nullTime(t time.Time) any { + if t.IsZero() { + return nil + } + return t +} + +func fromNullTime(t sql.NullTime) time.Time { + if !t.Valid { + return time.Time{} + } + return t.Time +} + +func nullString(p *string) any { + if p == nil { + return nil + } + return *p +} + +func nullUint32(p *uint32) any { + if p == nil { + return nil + } + return int64(*p) +} + +func nullBool(p *bool) any { + if p == nil { + return nil + } + return *p +} diff --git a/pkg/treatment/controller/store/postgres/postgres_test.go b/pkg/treatment/controller/store/postgres/postgres_test.go new file mode 100644 index 000000000..0d1e8429a --- /dev/null +++ b/pkg/treatment/controller/store/postgres/postgres_test.go @@ -0,0 +1,177 @@ +package postgres_test + +import ( + "context" + "database/sql" + "encoding/json" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/pgtest" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/storetest" +) + +func TestPostgresConformance(t *testing.T) { + storetest.Run(t, func(t *testing.T) store.Store { return pgtest.Open(t) }) +} + +// TestPostgresListStatements pins List and Get to a fixed number of +// statements, whatever the number of experiments and evidence documents. +func TestPostgresListStatements(t *testing.T) { + ctx := context.Background() + s, counter := pgtest.OpenCounting(t) + rp := s.Repos() + for i := range 200 { + if err := rp.Experiments.Save(ctx, storetest.Numbered(i)); err != nil { + t.Fatal(err) + } + } + tests := []struct { + description string + run func() error + expected int64 + }{ + {"positive: List of 200 experiments with cohorts, phases and evidence", func() error { + _, err := rp.Experiments.List(ctx, "", 1000) + return err + }, 6}, + {"boundary: List of one experiment", func() error { + _, err := rp.Experiments.List(ctx, "exp-007", 1000) + return err + }, 6}, + {"positive: Get reads one experiment through the same loader", func() error { + _, err := rp.Experiments.Get(ctx, "exp-007") + return err + }, 5}, + {"negative: List of an unknown ID stops after the ID lookup", func() error { + _, err := rp.Experiments.List(ctx, "ghost", 1000) + return err + }, 1}, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + counter.Reset() + if err := tc.run(); err != nil { + t.Fatal(err) + } + if got := counter.Statements(); got > tc.expected { + t.Fatalf("expected at most %d statements, got %d", tc.expected, got) + } + }) + } +} + +func TestPostgresMigrateIdempotent(t *testing.T) { + s := pgtest.Open(t) + ctx := context.Background() + for i := range 2 { + if err := s.Migrate(ctx); err != nil { + t.Fatalf("migration %d: %v", i+2, err) + } + } + var indexes int + if err := s.DB().QueryRow("SELECT count(*) FROM pg_indexes WHERE schemaname=current_schema() AND indexname LIKE 'xtcp_treatment_%'").Scan(&indexes); err != nil { + t.Fatal(err) + } + if indexes < 6 { + t.Fatalf("expected the six named indexes to exist, found %d", indexes) + } +} + +func TestPostgresClosedStore(t *testing.T) { + s := pgtest.Open(t) + if err := s.Close(); err != nil { + t.Fatal(err) + } + ctx := context.Background() + if err := s.Ping(ctx); err == nil { + t.Fatal("expected Ping to fail on a closed store") + } + if _, err := s.Repos().Experiments.HasActive(ctx, "dc1"); err == nil { + t.Fatal("expected repository calls to fail on a closed store") + } + if err := s.Tx(ctx, func(store.Repos) error { return nil }); err == nil { + t.Fatal("expected Tx to fail on a closed store") + } +} + +type rowQuerier interface { + QueryRowContext(context.Context, string, ...any) *sql.Row +} + +// TestPostgresExperimentQueryIndexes seeds a 100k-row history and checks the +// planner picks the discovery indexes without forced settings. +func TestPostgresExperimentQueryIndexes(t *testing.T) { + s := pgtest.Open(t) + db := s.DB() + const seed = `INSERT INTO xtcp_treatment_experiments(id,location,hypothesis,treatment_id,treatment_revision,treatment_destination,treatment_congestion_lock,treatment_ecn_fabric_verified, + minimum_observation_ns,maximum_phase_ns,maximum_evidence_age_ns,minimum_sockets_per_host,minimum_bytes_per_host,minimum_treated_hosts, + minimum_improvement,maximum_retransmission_increase,maximum_rtt_increase,status,revision,proposed_at,latest_outcome,updated_at) + SELECT 'history-'||i,'dc1','h','cubic',1,('10.'||(i/65536)||'.'||((i/256)%256)||'.'||(i%256)||'/32')::cidr,false,false, + 1,1,1,1,1,1,0,0,0,'retired',1,now(),'unspecified',now()-interval '48 hours' FROM generate_series(1,100000) i; + INSERT INTO xtcp_treatment_experiments(id,location,hypothesis,treatment_id,treatment_revision,treatment_destination,treatment_congestion_lock,treatment_ecn_fabric_verified, + minimum_observation_ns,maximum_phase_ns,maximum_evidence_age_ns,minimum_sockets_per_host,minimum_bytes_per_host,minimum_treated_hosts, + minimum_improvement,maximum_retransmission_increase,maximum_rtt_increase,status,revision,proposed_at,latest_outcome,updated_at) + SELECT 'active-'||i,'active-dc-'||i,'h','cubic',1,'192.0.2.1/32'::cidr,false,false, + 1,1,1,1,1,1,0,0,0,'running',1,now(),'unspecified',now() FROM generate_series(1,5) i; + ANALYZE xtcp_treatment_experiments;` + if _, err := db.Exec(seed); err != nil { + t.Fatal(err) + } + const destinationIndex, statusIndex = "xtcp_treatment_experiments_destination", "xtcp_treatment_experiments_location_status" + since := time.Now().Add(-24 * time.Hour) + for _, tc := range []struct { + name, description, query, index string + args []any + }{ + {"old-destination", "positive: history lookup is selective by location and destination", postgres.DestinationBlockedSQL, destinationIndex, []any{"dc1", "10.0.0.1/32", since}}, + {"absent-destination", "negative: a missing destination does not scan historical experiments", postgres.DestinationBlockedSQL, destinationIndex, []any{"dc1", "203.0.113.1/32", since}}, + {"active-budget", "positive: the budget lookup uses location and status", postgres.HasActiveSQL, statusIndex, []any{"active-dc-1"}}, + {"idle-budget", "boundary: an idle location does not scan retired history", postgres.HasActiveSQL, statusIndex, []any{"dc1"}}, + } { + t.Run(tc.name, func(t *testing.T) { + explain := func(q rowQuerier) ([]byte, float64) { + t.Helper() + var raw []byte + if err := q.QueryRowContext(context.Background(), "EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) "+tc.query, tc.args...).Scan(&raw); err != nil { + t.Fatal(err) + } + var plan []struct { + Milliseconds float64 `json:"Execution Time"` + } + if err := json.Unmarshal(raw, &plan); err != nil { + t.Fatal(err) + } + return raw, plan[0].Milliseconds + } + indexed, after := explain(db) + used := tc.index + // For a location holding one row the destination index's location + // prefix is also an efficient budget lookup; either plan is valid. + if tc.query == postgres.HasActiveSQL && strings.Contains(string(indexed), `"Index Name": "`+destinationIndex+`"`) { + used = destinationIndex + } + if !strings.Contains(string(indexed), `"Index Name": "`+used+`"`) { + t.Fatalf("%s: expected the planner to choose %s: %s", tc.description, tc.index, indexed) + } + // Transactional DDL gives a real no-index comparison; rollback restores + // the schema. Timings are evidence, never a speed assertion. + tx, err := db.BeginTx(context.Background(), &sql.TxOptions{}) + if err != nil { + t.Fatal(err) + } + defer tx.Rollback() + if _, err = tx.Exec("DROP INDEX " + destinationIndex + "; DROP INDEX " + statusIndex); err != nil { + t.Fatal(err) + } + _, before := explain(tx) + if err = tx.Rollback(); err != nil { + t.Fatal(err) + } + t.Logf("100005 experiments: unindexed %.3f ms, indexed %.3f ms (%s)", before, after, used) + }) + } +} diff --git a/pkg/treatment/controller/store/postgres/schema.sql b/pkg/treatment/controller/store/postgres/schema.sql new file mode 100644 index 000000000..61f6f1b1f --- /dev/null +++ b/pkg/treatment/controller/store/postgres/schema.sql @@ -0,0 +1,231 @@ +-- Relational schema for the treatment controller. Every table is a storage +-- format for the domain types in pkg/treatment; nothing here is a protobuf +-- document. Enumerations are stored as their snake_case domain names so the +-- rows read in psql and so a renamed wire enum cannot break a query. + +CREATE TABLE IF NOT EXISTS xtcp_treatment_agents ( + id text PRIMARY KEY, + location text NOT NULL, + enrolled_at timestamptz NOT NULL DEFAULT now(), + last_seen timestamptz, + boot_id text NOT NULL DEFAULT '', + collection_id text NOT NULL DEFAULT '', + kernel_release text NOT NULL DEFAULT '', + simple_host_routing boolean NOT NULL DEFAULT false, + actuator_enabled boolean NOT NULL DEFAULT false, + locally_suspended boolean NOT NULL DEFAULT false, + reported_revision bigint NOT NULL DEFAULT 0, + -- Digest of the algorithm and record rows last written for this agent; + -- a heartbeat with an equal digest updates this row only. + report_digest text NOT NULL DEFAULT '', + desired_revision bigint NOT NULL, + desired_suspended boolean NOT NULL DEFAULT false, + desired_issued_at timestamptz NOT NULL, + desired_updated_at timestamptz NOT NULL DEFAULT now() +); +CREATE INDEX IF NOT EXISTS xtcp_treatment_agents_location ON xtcp_treatment_agents(location); +CREATE INDEX IF NOT EXISTS xtcp_treatment_agents_desired_updated ON xtcp_treatment_agents(desired_updated_at); + +-- Every (boot, collection nonce) an agent has reported, so evidence over a +-- window that spans a restart still binds the records stamped before it. +-- last_seen is refreshed at most every few minutes; Agents.PruneSessions +-- drops rows older than the longest analysis window. +CREATE TABLE IF NOT EXISTS xtcp_treatment_agent_sessions ( + agent_id text NOT NULL REFERENCES xtcp_treatment_agents(id) ON DELETE CASCADE, + boot_id text NOT NULL, + collection_id text NOT NULL, + first_seen timestamptz NOT NULL, + last_seen timestamptz NOT NULL, + PRIMARY KEY (agent_id, boot_id, collection_id) +); +CREATE INDEX IF NOT EXISTS xtcp_treatment_agent_sessions_last_seen ON xtcp_treatment_agent_sessions(last_seen); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_agent_algorithms ( + agent_id text NOT NULL REFERENCES xtcp_treatment_agents(id) ON DELETE CASCADE, + position integer NOT NULL, + name text NOT NULL, + PRIMARY KEY (agent_id, position) +); + +-- Assignments are the controller's desired state per agent; records are the +-- agent's report of what it did with them. Both carry the treatment inline +-- because a record may describe an assignment that no longer exists. +CREATE TABLE IF NOT EXISTS xtcp_treatment_assignments ( + agent_id text NOT NULL REFERENCES xtcp_treatment_agents(id) ON DELETE CASCADE, + experiment_id text NOT NULL, + position integer NOT NULL, + mode text NOT NULL, + generation bigint NOT NULL, + lease_expires_at timestamptz, + treatment_id text NOT NULL, + treatment_revision bigint NOT NULL, + treatment_destination cidr NOT NULL, + treatment_congestion_control text, + treatment_congestion_lock boolean NOT NULL, + treatment_rto_min_ms integer, + treatment_initial_congestion_window integer, + treatment_initial_receive_window integer, + treatment_quick_ack boolean, + treatment_ecn boolean, + treatment_ecn_fabric_verified boolean NOT NULL, + predecessor_id text, + predecessor_revision bigint, + predecessor_destination cidr, + predecessor_congestion_control text, + predecessor_congestion_lock boolean, + predecessor_rto_min_ms integer, + predecessor_initial_congestion_window integer, + predecessor_initial_receive_window integer, + predecessor_quick_ack boolean, + predecessor_ecn boolean, + predecessor_ecn_fabric_verified boolean, + PRIMARY KEY (agent_id, experiment_id) +); +CREATE INDEX IF NOT EXISTS xtcp_treatment_assignments_experiment ON xtcp_treatment_assignments(experiment_id); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_records ( + agent_id text NOT NULL REFERENCES xtcp_treatment_agents(id) ON DELETE CASCADE, + experiment_id text NOT NULL, + position integer NOT NULL, + mode text NOT NULL, + generation bigint NOT NULL, + lease_expires_at timestamptz, + treatment_id text NOT NULL, + treatment_revision bigint NOT NULL, + treatment_destination cidr NOT NULL, + treatment_congestion_control text, + treatment_congestion_lock boolean NOT NULL, + treatment_rto_min_ms integer, + treatment_initial_congestion_window integer, + treatment_initial_receive_window integer, + treatment_quick_ack boolean, + treatment_ecn boolean, + treatment_ecn_fabric_verified boolean NOT NULL, + predecessor_id text, + predecessor_revision bigint, + predecessor_destination cidr, + predecessor_congestion_control text, + predecessor_congestion_lock boolean, + predecessor_rto_min_ms integer, + predecessor_initial_congestion_window integer, + predecessor_initial_receive_window integer, + predecessor_quick_ack boolean, + predecessor_ecn boolean, + predecessor_ecn_fabric_verified boolean, + desired_revision bigint NOT NULL, + status text NOT NULL, + received_at timestamptz, + attempted_at timestamptz, + applied_at timestamptz, + verified_at timestamptz, + removed_at timestamptz, + error text NOT NULL DEFAULT '', + expired_latched boolean NOT NULL DEFAULT false, + PRIMARY KEY (agent_id, experiment_id) +); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_evidence ( + id text PRIMARY KEY, + experiment_id text NOT NULL, + analyzed_at timestamptz NOT NULL, + window_start timestamptz NOT NULL, + window_end timestamptz NOT NULL, + query_version text NOT NULL, + enrichment_version text NOT NULL DEFAULT '', + artifact_sha256 text NOT NULL, + digest text NOT NULL, + received_at timestamptz NOT NULL DEFAULT now() +); +CREATE INDEX IF NOT EXISTS xtcp_treatment_evidence_experiment ON xtcp_treatment_evidence(experiment_id); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_evidence_hosts ( + evidence_id text NOT NULL REFERENCES xtcp_treatment_evidence(id) ON DELETE CASCADE, + position integer NOT NULL, + agent_id text NOT NULL, + sockets bigint NOT NULL, + bytes_acked bigint NOT NULL, + goodput_bps double precision NOT NULL, + retransmission_ratio double precision NOT NULL, + rtt_p95_ms double precision NOT NULL, + exposed_sockets bigint NOT NULL, + collection_healthy boolean NOT NULL, + unbound_sockets bigint NOT NULL DEFAULT 0, + PRIMARY KEY (evidence_id, position) +); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_experiments ( + id text PRIMARY KEY, + location text NOT NULL, + hypothesis text NOT NULL, + treatment_id text NOT NULL, + treatment_revision bigint NOT NULL, + treatment_destination cidr NOT NULL, + treatment_congestion_control text, + treatment_congestion_lock boolean NOT NULL, + treatment_rto_min_ms integer, + treatment_initial_congestion_window integer, + treatment_initial_receive_window integer, + treatment_quick_ack boolean, + treatment_ecn boolean, + treatment_ecn_fabric_verified boolean NOT NULL, + minimum_observation_ns bigint NOT NULL, + maximum_phase_ns bigint NOT NULL, + maximum_evidence_age_ns bigint NOT NULL, + minimum_sockets_per_host bigint NOT NULL, + minimum_bytes_per_host bigint NOT NULL, + minimum_treated_hosts integer NOT NULL, + minimum_improvement double precision NOT NULL, + maximum_retransmission_increase double precision NOT NULL, + maximum_rtt_increase double precision NOT NULL, + baseline_evidence_id text REFERENCES xtcp_treatment_evidence(id), + status text NOT NULL, + revision bigint NOT NULL, + proposed_at timestamptz, + latest_evidence_id text REFERENCES xtcp_treatment_evidence(id), + latest_outcome text NOT NULL, + updated_at timestamptz NOT NULL +); +CREATE INDEX IF NOT EXISTS xtcp_treatment_experiments_location_status ON xtcp_treatment_experiments(location, status); +CREATE INDEX IF NOT EXISTS xtcp_treatment_experiments_destination ON xtcp_treatment_experiments(location, treatment_destination, updated_at); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_cohort ( + experiment_id text NOT NULL REFERENCES xtcp_treatment_experiments(id) ON DELETE CASCADE, + position integer NOT NULL, + agent_id text NOT NULL, + PRIMARY KEY (experiment_id, position) +); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_phases ( + experiment_id text NOT NULL REFERENCES xtcp_treatment_experiments(id) ON DELETE CASCADE, + position integer NOT NULL, + target_hosts integer NOT NULL, + issued_at timestamptz, + observation_started_at timestamptz, + evaluated_at timestamptz, + evidence_id text REFERENCES xtcp_treatment_evidence(id), + outcome text NOT NULL, + reviewer text NOT NULL DEFAULT '', + reason text NOT NULL DEFAULT '', + PRIMARY KEY (experiment_id, position) +); + +CREATE TABLE IF NOT EXISTS xtcp_treatment_holds ( + scope text PRIMARY KEY, + reason text NOT NULL +); + +-- The audit log is append-only and never queried by payload field, so the +-- payload stays a JSON document (protojson of the wire request or response). +CREATE TABLE IF NOT EXISTS xtcp_treatment_events ( + sequence bigserial PRIMARY KEY, + occurred_at timestamptz NOT NULL DEFAULT now(), + actor text NOT NULL, + request_id text UNIQUE, + kind text NOT NULL, + payload jsonb NOT NULL +); + +-- Columns added after the first pre-release schema. CREATE TABLE IF NOT +-- EXISTS leaves an existing table alone, so these bring it forward. +ALTER TABLE xtcp_treatment_agents ADD COLUMN IF NOT EXISTS collection_id text NOT NULL DEFAULT ''; +ALTER TABLE xtcp_treatment_evidence_hosts ADD COLUMN IF NOT EXISTS unbound_sockets bigint NOT NULL DEFAULT 0; diff --git a/pkg/treatment/controller/store/store.go b/pkg/treatment/controller/store/store.go new file mode 100644 index 000000000..380afbb02 --- /dev/null +++ b/pkg/treatment/controller/store/store.go @@ -0,0 +1,206 @@ +// Package store defines the controller's persistence ports. The handlers in +// package controller work only through these interfaces; package postgres +// implements them with hand-written SQL and package memory implements them +// with maps for handler tests. +// +// Every method takes a context and returns the sentinel errors below (wrapped +// or bare) for the conditions a handler must distinguish. Anything else is an +// infrastructure failure. +package store + +import ( + "context" + "errors" + "net/netip" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +var ( + // ErrNotFound: the row does not exist. + ErrNotFound = errors.New("not found") + // ErrNotEnrolled: the agent has no row; desired state cannot be stored. + ErrNotEnrolled = errors.New("agent not enrolled") + // ErrExists: an insert-only operation found the key already present. + ErrExists = errors.New("already exists") + // ErrEvidenceConflict: an evidence ID was reused for different content + // or another experiment. + ErrEvidenceConflict = errors.New("evidence IDs are immutable and experiment-specific") + // ErrRequestConflict: a request ID was reused for a different operation + // or a different body. + ErrRequestConflict = errors.New("request_id reused") +) + +// Agent is an enrolled host: its certificate-bound location, when it last +// reported and what it reported. Report is zero until the first check-in +// completes. +type Agent struct { + ID string + Location string + EnrolledAt time.Time + LastSeen time.Time + Report treatment.AgentReport +} + +// Seen reports whether the agent checked in within window of now. +func (a *Agent) Seen(now time.Time, window time.Duration) bool { + return !a.LastSeen.IsZero() && now.Sub(a.LastSeen) <= window +} + +// AgentRef is the identity pair used by fleet-wide controls. +type AgentRef struct{ ID, Location string } + +// Agents stores enrollment, the latest report and the desired state per host. +type Agents interface { + // Enroll inserts the agent with its initial desired state. It is a + // no-op when the agent already exists, so concurrent first check-ins + // are safe. Enrollment never changes an existing location. + Enroll(ctx context.Context, id, location string, initial *treatment.DesiredState) error + // Get returns the agent or ErrNotFound. + Get(ctx context.Context, id string) (*Agent, error) + // Observe replaces the agent's capabilities and records and stamps + // last_seen. It returns ErrNotEnrolled when no agent has that ID and + // location: a host cannot move location by reporting a new one. + Observe(ctx context.Context, report *treatment.AgentReport, seen time.Time) error + // Desired returns the agent's desired state or ErrNotEnrolled. + Desired(ctx context.Context, id string) (*treatment.DesiredState, error) + // SaveDesired replaces the desired state, including every assignment, + // or returns ErrNotEnrolled. + SaveDesired(ctx context.Context, d *treatment.DesiredState) error + // List returns agents in the location, or every agent when location is + // empty, ordered by ID. + List(ctx context.Context, location string) ([]AgentRef, error) + // DesiredSince returns the desired revision of every agent whose + // desired state was stamped at or after since, ordered by stamp then + // ID. A zero since returns every agent. Stamps come from the store's + // own clock, so callers carry the newest stamp returned forward as the + // next since rather than comparing it with their clock. + DesiredSince(ctx context.Context, since time.Time) ([]DesiredRevision, error) + // Sessions returns the (boot, collection) sessions of the named agents + // that overlap [from, to]: first seen no later than to and last seen no + // earlier than from, at most MaxSessionsPerAgent per agent (the most + // recently seen). Observe records sessions and refreshes a known + // session's LastSeen at most every SessionRefresh, so callers widen from + // by at least that much. + Sessions(ctx context.Context, ids []string, from, to time.Time) ([]treatment.Session, error) + // PruneSessions deletes sessions last seen before the cutoff and + // returns how many it deleted. + PruneSessions(ctx context.Context, before time.Time) (int64, error) +} + +// SessionRefresh is how stale a session's LastSeen may become before a +// check-in rewrites it. +const SessionRefresh = 5 * time.Minute + +// MaxSessionsPerAgent caps the sessions one agent contributes to a window. +// An agent that rotates its nonce on every check-in then loses binding for +// its own older records instead of growing the window past +// evidence.MaxSessions and failing evidence for its whole cohort. +const MaxSessionsPerAgent = 8 + +// DesiredRevision is one agent's desired revision and the store's stamp of +// when it last changed. +type DesiredRevision struct { + AgentID string + Revision uint64 + UpdatedAt time.Time +} + +// Experiments stores experiments with their cohort, phases and evidence +// references. Evidence content lives once, in the Evidence repository; Save +// stores whatever evidence the experiment carries through it. +type Experiments interface { + // Get returns the experiment, with evidence loaded, or ErrNotFound. + // Inside Store.Tx the row is locked for update. + Get(ctx context.Context, id string) (*treatment.Experiment, error) + Exists(ctx context.Context, id string) (bool, error) + // Save inserts or replaces the experiment. CohortOrder is written on + // first insert and immutable afterwards; evidence the experiment + // carries is stored through the Evidence repository and conflicts + // surface as ErrEvidenceConflict. + Save(ctx context.Context, e *treatment.Experiment) error + // List returns the experiment with the ID, or up to limit experiments + // ordered by ID when id is empty. + List(ctx context.Context, id string, limit int) ([]*treatment.Experiment, error) + // IDs returns the IDs of experiments in any of the statuses. + IDs(ctx context.Context, statuses ...treatment.Status) ([]string, error) + // HasActive reports whether the location has an experiment that still + // consumes its budget (treatment.Status.Active). + HasActive(ctx context.Context, location string) (bool, error) + // DestinationBlocked reports whether the destination in the location + // has an experiment that is not terminal, or a terminal one updated + // after since. + DestinationBlocked(ctx context.Context, location string, destination netip.Prefix, since time.Time) (bool, error) +} + +// Evidence is the single copy of every evidence set. +type Evidence interface { + // Get returns the evidence or ErrNotFound. + Get(ctx context.Context, id string) (*treatment.Evidence, error) + // Put stores evidence for the experiment. Storing the same ID again is + // a no-op when the content and owner match and ErrEvidenceConflict + // otherwise. + Put(ctx context.Context, experimentID string, e *treatment.Evidence) error +} + +// Holds are operator suspensions by scope ("fleet", "location:", "agent:"). +type Holds interface { + Set(ctx context.Context, scope, reason string) error + Clear(ctx context.Context, scope string) error + // Held reports whether any of the scopes is held. + Held(ctx context.Context, scopes ...string) (bool, error) +} + +// Event is one audit row. +type Event struct { + Sequence int64 + OccurredAt time.Time + Actor string + RequestID string + Kind string + Payload []byte +} + +// Audit is the append-only event log. Payloads are opaque JSON documents. +type Audit interface { + // Append records an event. requestID may be empty; non-empty IDs are + // unique and a duplicate returns ErrExists. + Append(ctx context.Context, actor, requestID, kind string, payload []byte) error + // Lookup returns the event with the request ID or ErrNotFound. + Lookup(ctx context.Context, requestID string) (*Event, error) + // Count returns the number of events. + Count(ctx context.Context) (int64, error) +} + +// Metrics are the fleet gauges the status page serves. +type Metrics interface { + Snapshot(ctx context.Context, now time.Time) (map[string]float64, error) +} + +// Repos bundles the repositories bound to one connection or transaction. +type Repos struct { + Agents Agents + Experiments Experiments + Evidence Evidence + Holds Holds + Audit Audit + Metrics Metrics +} + +// Store is the root. Repos performs each call in its own implicit +// transaction. Tx runs fn inside one transaction that holds the controller's +// mutation lock, so every control-plane change is serialized across replicas; +// agent heartbeats never take it. Lease elects which replica does periodic +// work without making any replica special. +type Store interface { + Repos() Repos + Tx(ctx context.Context, fn func(Repos) error) error + // Lease runs fn while holding the named lease, which at most one caller + // across every replica holds at a time. When another caller holds it, + // Lease returns false without calling fn. The lease is released when fn + // returns, whatever it returns. + Lease(ctx context.Context, name string, fn func() error) (bool, error) + Ping(ctx context.Context) error + Close() error +} diff --git a/pkg/treatment/controller/store/storetest/storetest.go b/pkg/treatment/controller/store/storetest/storetest.go new file mode 100644 index 000000000..080cadc54 --- /dev/null +++ b/pkg/treatment/controller/store/storetest/storetest.go @@ -0,0 +1,1144 @@ +// Package storetest is the conformance suite every store.Store implementation +// must pass. The memory and postgres packages both run it, so a handler +// tested against the memory store sees the same contract production sees. +package storetest + +import ( + "context" + "errors" + "fmt" + "net/netip" + "slices" + "strings" + "sync" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/protobuf/proto" +) + +// Fixture values shared by many rows. +const ( + locationCst = "dc1" + host1Cst = "host-1" + host2Cst = "host-2" + destinationCst = "192.0.2.1/32" + agentScopeCst = "agent:h" + missingCst = "missing" + fleetScopeCst = "fleet" + locationScopeCst = "location:" + locationCst +) + +// Opener returns a fresh, empty store for one test. +type Opener func(t *testing.T) store.Store + +// now is microsecond-aligned and in UTC, the precision timestamptz keeps. +var now = time.Unix(1700000000, 0).UTC() + +func ptr[T any](v T) *T { return &v } + +// Run executes the suite against stores from open. +func Run(t *testing.T, open Opener) { + t.Run("Agents", func(t *testing.T) { agents(t, open) }) + t.Run("Experiments", func(t *testing.T) { experiments(t, open) }) + t.Run("Eligibility", func(t *testing.T) { eligibility(t, open) }) + t.Run("Evidence", func(t *testing.T) { evidence(t, open) }) + t.Run("Holds", func(t *testing.T) { holds(t, open) }) + t.Run("Audit", func(t *testing.T) { audit(t, open) }) + t.Run("Tx", func(t *testing.T) { tx(t, open) }) + t.Run("Lease", func(t *testing.T) { lease(t, open) }) + t.Run("Metrics", func(t *testing.T) { metrics(t, open) }) +} + +func report(id, location string) *treatment.AgentReport { + d := fixtures.Desired(now) + return &treatment.AgentReport{ + AgentID: id, + Location: location, + Capabilities: treatment.Capabilities{BootID: "boot-1", CollectionID: fixtures.CollectionID, KernelRelease: "6.12.0", CongestionAlgorithms: []string{"cubic", "bbr", "dctcp"}, SimpleHostRouting: true, ActuatorEnabled: true}, + DesiredRevision: 3, + LocallySuspended: true, + Records: []treatment.ApplicationRecord{{ + Assignment: d.Assignments[0], DesiredRevision: 3, Status: treatment.ApplyVerified, + ReceivedAt: now, AttemptedAt: now.Add(time.Second), AppliedAt: now.Add(2 * time.Second), VerifiedAt: now.Add(3 * time.Second), + }, { + Assignment: treatment.Assignment{ExperimentID: "old", Generation: 2, Mode: treatment.ModeRetired, Treatment: fixtures.Treatment()}, + DesiredRevision: 2, Status: treatment.ApplyFailed, Error: "ENETUNREACH", ExpiredLatched: true, RemovedAt: now, + }}, + } +} + +func sameDesired(t *testing.T, description string, got, want *treatment.DesiredState) { + t.Helper() + if !proto.Equal(wire.Desired(got), wire.Desired(want)) { + t.Fatalf("%s:\n got %+v\nwant %+v", description, got, want) + } +} + +func sameReport(t *testing.T, description string, got, want *treatment.AgentReport) { + t.Helper() + if !proto.Equal(wire.Report(got), wire.Report(want)) { + t.Fatalf("%s:\n got %+v\nwant %+v", description, got, want) + } +} + +func sameExperiment(t *testing.T, description string, got, want *treatment.Experiment) { + t.Helper() + if !proto.Equal(wire.Experiment(got), wire.Experiment(want)) { + t.Fatalf("%s:\n got %+v\nwant %+v", description, got, want) + } +} + +func sameEvidence(t *testing.T, description string, got, want *treatment.Evidence) { + t.Helper() + if !proto.Equal(wire.Evidence(got), wire.Evidence(want)) { + t.Fatalf("%s:\n got %+v\nwant %+v", description, got, want) + } +} + +// agentCase is one Agents contract row. +type agentCase struct { + name, description string + run func(t *testing.T, a store.Agents) +} + +func agents(t *testing.T, open Opener) { + ctx := context.Background() + initial := &treatment.DesiredState{AgentID: host1Cst, Revision: 1, Suspended: true, IssuedAt: now} + for _, tc := range slices.Concat(agentEnrollCases(ctx, initial), agentDesiredSinceCases(ctx, initial), agentLookupCases(ctx, initial), agentSessionCases(ctx, initial)) { + t.Run(tc.name, func(t *testing.T) { + t.Log(tc.description) + tc.run(t, open(t).Repos().Agents) + }) + } +} + +// observeSession checks host-1 in with the given boot and nonce at seen. +func observeSession(ctx context.Context, t *testing.T, a store.Agents, boot, collection string, seen time.Time) { + t.Helper() + r := report(host1Cst, locationCst) + r.Capabilities.BootID, r.Capabilities.CollectionID = boot, collection + must(t, a.Observe(ctx, r, seen)) +} + +// sessionKeys renders sessions as boot/nonce@first..last for comparison. +func sessionKeys(sessions []treatment.Session) []string { + out := make([]string, len(sessions)) + for i, s := range sessions { + out[i] = fmt.Sprintf("%s/%s/%s@%d..%d", s.AgentID, s.BootID, s.CollectionID[len(s.CollectionID)-1:], s.FirstSeen.Unix()-now.Unix(), s.LastSeen.Unix()-now.Unix()) + } + return out +} + +// agentSessionCases covers the (boot, collection) history evidence binds to. +func agentSessionCases(ctx context.Context, initial *treatment.DesiredState) []agentCase { + const nonce1, nonce2 = "00000000000000000000000000000001", "00000000000000000000000000000002" + sessions := func(t *testing.T, a store.Agents, from, to time.Time, expected ...string) { + t.Helper() + got, err := a.Sessions(ctx, []string{host1Cst, "ghost"}, from, to) + must(t, err) + if keys := sessionKeys(got); !slices.Equal(keys, expected) { + t.Fatalf("expected sessions %v, got %v", expected, keys) + } + } + return []agentCase{ + {"session-recorded", "positive: a check-in records its session and the agent's current nonce", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + observeSession(ctx, t, a, "boot-1", nonce1, now) + sessions(t, a, now.Add(-time.Hour), now.Add(time.Hour), "host-1/boot-1/1@0..0") + got, err := a.Get(ctx, host1Cst) + must(t, err) + if got.Report.Capabilities.CollectionID != nonce1 { + t.Fatalf("expected the reported nonce on the agent, got %q", got.Report.Capabilities.CollectionID) + } + }}, + {"rotation", "positive: a restarted agent adds a session and both overlap a window spanning the restart", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + observeSession(ctx, t, a, "boot-1", nonce1, now) + observeSession(ctx, t, a, "boot-1", nonce2, now.Add(10*time.Minute)) + sessions(t, a, now.Add(-time.Minute), now.Add(time.Hour), "host-1/boot-1/1@0..0", "host-1/boot-1/2@600..600") + }}, + {"outside-window", "negative: sessions last seen before the window or first seen after it are not returned", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + observeSession(ctx, t, a, "boot-1", nonce1, now) + observeSession(ctx, t, a, "boot-2", nonce2, now.Add(2*time.Hour)) + sessions(t, a, now.Add(time.Minute), now.Add(time.Hour)) + sessions(t, a, now, now, "host-1/boot-1/1@0..0") + }}, + {"heartbeat-throttle", "boundary: last_seen moves only once it is SessionRefresh old", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + observeSession(ctx, t, a, "boot-1", nonce1, now) + observeSession(ctx, t, a, "boot-1", nonce1, now.Add(store.SessionRefresh-time.Second)) + sessions(t, a, now.Add(-time.Hour), now.Add(time.Hour), "host-1/boot-1/1@0..0") + observeSession(ctx, t, a, "boot-1", nonce1, now.Add(store.SessionRefresh)) + sessions(t, a, now.Add(-time.Hour), now.Add(time.Hour), "host-1/boot-1/1@0..300") + }}, + {"retention", "corner: pruning deletes only sessions last seen before the cutoff", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + observeSession(ctx, t, a, "boot-1", nonce1, now) + observeSession(ctx, t, a, "boot-1", nonce2, now.Add(time.Hour)) + n, err := a.PruneSessions(ctx, now.Add(time.Minute)) + must(t, err) + if n != 1 { + t.Fatalf("expected one pruned session, got %d", n) + } + sessions(t, a, now.Add(-time.Hour), now.Add(2*time.Hour), "host-1/boot-1/2@3600..3600") + }}, + {"session-cap", "boundary: an agent rotating its nonce contributes only its most recent sessions", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + for i := range store.MaxSessionsPerAgent + 3 { + observeSession(ctx, t, a, "boot-1", fmt.Sprintf("%032x", i+1), now.Add(time.Duration(i)*time.Minute)) + } + got, err := a.Sessions(ctx, []string{host1Cst}, now.Add(-time.Hour), now.Add(time.Hour)) + must(t, err) + if len(got) != store.MaxSessionsPerAgent || got[0].FirstSeen.Before(now.Add(3*time.Minute)) { + t.Fatalf("expected the %d most recent sessions, got %v", store.MaxSessionsPerAgent, sessionKeys(got)) + } + }}, + {"sessions-unenrolled", "negative: an unknown agent has no sessions and a report for it records none", func(t *testing.T, a store.Agents) { + r := report(host1Cst, locationCst) + if err := a.Observe(ctx, r, now); !errors.Is(err, store.ErrNotEnrolled) { + t.Fatalf("expected ErrNotEnrolled, got %v", err) + } + got, err := a.Sessions(ctx, []string{host1Cst}, now.Add(-time.Hour), now.Add(time.Hour)) + must(t, err) + if len(got) != 0 { + t.Fatalf("expected no sessions, got %d", len(got)) + } + }}, + } +} + +// agentEnrollCases covers enrollment, reports and the desired-state round trip. +func agentEnrollCases(ctx context.Context, initial *treatment.DesiredState) []agentCase { + return []agentCase{ + {"enroll-roundtrip", "positive: enrollment stores location and the initial desired state", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + got, err := a.Get(ctx, host1Cst) + must(t, err) + if got.ID != host1Cst || got.Location != locationCst || got.EnrolledAt.IsZero() || !got.LastSeen.IsZero() || got.Report.AgentID != host1Cst || got.Report.Location != locationCst { + t.Fatalf("expected an enrolled agent without a report, got %+v", got) + } + d, err := a.Desired(ctx, host1Cst) + must(t, err) + sameDesired(t, "expected the initial desired state", d, initial) + }}, + {"observe-roundtrip", "positive: a report is stored with every capability and record column", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + r := report(host1Cst, locationCst) + must(t, a.Observe(ctx, r, now.Add(time.Minute))) + got, err := a.Get(ctx, host1Cst) + must(t, err) + if !got.LastSeen.Equal(now.Add(time.Minute)) || !got.Seen(now.Add(2*time.Minute), 2*time.Minute) || got.Seen(now.Add(4*time.Minute), 2*time.Minute) { + t.Fatalf("expected last_seen %s, got %s", now.Add(time.Minute), got.LastSeen) + } + sameReport(t, "expected the observed report", &got.Report, r) + }}, + {"desired-roundtrip", "positive: every assignment column, predecessor and lease survives", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + d := fixtures.Desired(now) + d.Revision = 7 + pred := fixtures.Treatment() + pred.Revision = 2 + pred.Settings = treatment.TCPSettings{CongestionControl: ptr("bbr"), CongestionLock: true, RTOMinMs: ptr(uint32(5)), InitialCongestionWindow: ptr(uint32(100)), InitialReceiveWindow: ptr(uint32(0)), QuickAck: ptr(false), ECN: ptr(true)} + d.Assignments = append(d.Assignments, treatment.Assignment{ExperimentID: "stable-1", Generation: 4, Mode: treatment.ModeStable, Treatment: treatment.Treatment{ID: "v6", Revision: 3, Destination: netip.MustParsePrefix("2001:db8::1/128"), Settings: pred.Settings, ECNFabricVerified: true}, Predecessor: &pred}) + must(t, a.SaveDesired(ctx, d)) + got, err := a.Desired(ctx, host1Cst) + must(t, err) + sameDesired(t, "expected the saved desired state", got, d) + revs, err := a.DesiredSince(ctx, time.Time{}) + must(t, err) + if len(revs) != 1 || revs[0].AgentID != host1Cst || revs[0].Revision != 7 || revs[0].UpdatedAt.IsZero() { + t.Fatalf("expected a stamped revision 7 for host-1, got %+v", revs) + } + }}, + } +} + +// agentDesiredSinceCases covers the notification watermark query. +func agentDesiredSinceCases(ctx context.Context, initial *treatment.DesiredState) []agentCase { + return []agentCase{ + {"desired-since-all", "positive: a zero watermark returns every agent, enrolled or saved, ordered by stamp then ID", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host2Cst, locationCst, &treatment.DesiredState{AgentID: host2Cst, Revision: 1, IssuedAt: now})) + settle() + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + settle() + must(t, a.SaveDesired(ctx, &treatment.DesiredState{AgentID: host2Cst, Revision: 2, IssuedAt: now})) + got, err := a.DesiredSince(ctx, time.Time{}) + must(t, err) + if len(got) != 2 || got[0].AgentID != host1Cst || got[0].Revision != 1 || got[1].AgentID != host2Cst || got[1].Revision != 2 || !got[0].UpdatedAt.Before(got[1].UpdatedAt) { + t.Fatalf("expected host-1 rev 1 then host-2 rev 2 in stamp order, got %+v", got) + } + }}, + {"desired-since-changed", "positive: a watermark after the older stamp returns only the agent saved since", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + must(t, a.Enroll(ctx, host2Cst, locationCst, initial)) + all, err := a.DesiredSince(ctx, time.Time{}) + must(t, err) + newest := all[len(all)-1].UpdatedAt + settle() + must(t, a.SaveDesired(ctx, &treatment.DesiredState{AgentID: host1Cst, Revision: 5, IssuedAt: now})) + got, err := a.DesiredSince(ctx, newest.Add(time.Microsecond)) + must(t, err) + if len(got) != 1 || got[0].AgentID != host1Cst || got[0].Revision != 5 || !got[0].UpdatedAt.After(newest) { + t.Fatalf("expected only host-1 at revision 5, got %+v", got) + } + }}, + {"desired-since-equal", "boundary: a row stamped exactly at the watermark is included", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + settle() + must(t, a.Enroll(ctx, host2Cst, locationCst, initial)) + all, err := a.DesiredSince(ctx, time.Time{}) + must(t, err) + got, err := a.DesiredSince(ctx, all[1].UpdatedAt) + must(t, err) + if len(got) != 1 || got[0].AgentID != all[1].AgentID || !got[0].UpdatedAt.Equal(all[1].UpdatedAt) { + t.Fatalf("expected exactly the row stamped at the watermark, got %+v", got) + } + }}, + {"desired-since-none", "boundary: a watermark past the newest stamp returns nothing without error", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + all, err := a.DesiredSince(ctx, time.Time{}) + must(t, err) + got, err := a.DesiredSince(ctx, all[0].UpdatedAt.Add(time.Microsecond)) + must(t, err) + if len(got) != 0 { + t.Fatalf("expected no rows, got %+v", got) + } + }}, + {"desired-since-stamp-is-store-clock", "corner: the stamp is the store's clock, not the desired state's issued_at", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + must(t, a.SaveDesired(ctx, &treatment.DesiredState{AgentID: host1Cst, Revision: 2, IssuedAt: now.Add(-24 * time.Hour)})) + got, err := a.DesiredSince(ctx, now) + must(t, err) + if len(got) != 1 || got[0].UpdatedAt.Before(now) { + t.Fatalf("expected a current stamp despite an old issued_at, got %+v", got) + } + }}, + } +} + +// agentLookupCases covers idempotence, identity fences, bounds and listing. +func agentLookupCases(ctx context.Context, initial *treatment.DesiredState) []agentCase { + return []agentCase{ + {"enroll-idempotent", "corner: a second enrollment never changes location or desired state", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + must(t, a.Enroll(ctx, host1Cst, "dc2", &treatment.DesiredState{AgentID: host1Cst, Revision: 9, IssuedAt: now})) + got, err := a.Get(ctx, host1Cst) + must(t, err) + d, err := a.Desired(ctx, host1Cst) + must(t, err) + if got.Location != locationCst || d.Revision != 1 || !d.Suspended { + t.Fatalf("expected the first enrollment to win, got %s revision %d", got.Location, d.Revision) + } + }}, + {"observe-location-change", "negative: a host cannot move location by reporting a new one", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + if err := a.Observe(ctx, report(host1Cst, "dc2"), now); !errors.Is(err, store.ErrNotEnrolled) { + t.Fatalf("expected ErrNotEnrolled, got %v", err) + } + got, err := a.Get(ctx, host1Cst) + must(t, err) + if !got.LastSeen.IsZero() || len(got.Report.Records) != 0 { + t.Fatal("expected the rejected report to leave no trace") + } + }}, + {"unknown-agent", "negative: lookups of an unenrolled agent return the documented sentinels", func(t *testing.T, a store.Agents) { + if _, err := a.Get(ctx, "ghost"); !errors.Is(err, store.ErrNotFound) { + t.Fatalf("expected ErrNotFound from Get, got %v", err) + } + if _, err := a.Desired(ctx, "ghost"); !errors.Is(err, store.ErrNotEnrolled) { + t.Fatalf("expected ErrNotEnrolled from Desired, got %v", err) + } + if err := a.SaveDesired(ctx, &treatment.DesiredState{AgentID: "ghost", Revision: 1, IssuedAt: now}); !errors.Is(err, store.ErrNotEnrolled) { + t.Fatalf("expected ErrNotEnrolled from SaveDesired, got %v", err) + } + if err := a.Observe(ctx, report("ghost", locationCst), now); !errors.Is(err, store.ErrNotEnrolled) { + t.Fatalf("expected ErrNotEnrolled from Observe, got %v", err) + } + }}, + {"empty-desired", "boundary: a desired state with no assignments replaces a populated one", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, fixtures.Desired(now))) + empty := &treatment.DesiredState{AgentID: host1Cst, Revision: 2, IssuedAt: now.Add(time.Minute)} + must(t, a.SaveDesired(ctx, empty)) + got, err := a.Desired(ctx, host1Cst) + must(t, err) + sameDesired(t, "expected no assignments", got, empty) + }}, + {"max-assignments", "boundary: MaxAssignments assignments are stored in order", func(t *testing.T, a store.Agents) { + must(t, a.Enroll(ctx, host1Cst, locationCst, initial)) + d := &treatment.DesiredState{AgentID: host1Cst, Revision: 2, IssuedAt: now} + for i := range treatment.MaxAssignments { + d.Assignments = append(d.Assignments, treatment.Assignment{ExperimentID: fmt.Sprintf("exp-%05d", i), Generation: uint64(i), Mode: treatment.ModeTrial, LeaseExpiresAt: now.Add(time.Hour), Treatment: fixtures.Treatment()}) + } + must(t, a.SaveDesired(ctx, d)) + got, err := a.Desired(ctx, host1Cst) + must(t, err) + if len(got.Assignments) != treatment.MaxAssignments { + t.Fatalf("expected %d assignments, got %d", treatment.MaxAssignments, len(got.Assignments)) + } + for i := range got.Assignments { + if got.Assignments[i].ExperimentID != d.Assignments[i].ExperimentID { + t.Fatalf("expected position %d to hold %s, got %s", i, d.Assignments[i].ExperimentID, got.Assignments[i].ExperimentID) + } + } + }}, + {"list-by-location", "positive: List filters by location and orders by ID; empty location lists everyone", func(t *testing.T, a store.Agents) { + for _, h := range []struct{ id, loc string }{{"c", "dc2"}, {"a", locationCst}, {"b", locationCst}} { + must(t, a.Enroll(ctx, h.id, h.loc, &treatment.DesiredState{AgentID: h.id, Revision: 1, IssuedAt: now})) + } + dc1, err := a.List(ctx, locationCst) + must(t, err) + all, err := a.List(ctx, "") + must(t, err) + none, err := a.List(ctx, "dc3") + must(t, err) + want := []store.AgentRef{{ID: "a", Location: locationCst}, {ID: "b", Location: locationCst}} + if !slices.Equal(dc1, want) || len(all) != 3 || all[2].ID != "c" || len(none) != 0 { + t.Fatalf("expected %v / 3 / 0, got %v / %d / %d", want, dc1, len(all), len(none)) + } + }}, + } +} + +func populated() *treatment.Experiment { + e, after := fixtures.Experiment(now, treatment.DefaultPolicy()) + e.ProposedAt = now.Add(-2 * time.Hour) + e.UpdatedAt = now + e.LatestEvidence = after + e.LatestOutcome = treatment.OutcomeBeneficial + e.Phases[0].EvaluatedAt = now + e.Phases[0].Evidence = after + e.Phases[0].Outcome = treatment.OutcomeBeneficial + e.Phases[0].Reviewer = "operator/alice" + e.Phases[0].Reason = "reviewed" + e.Phases = append(e.Phases, treatment.Phase{TargetHosts: 8, IssuedAt: now}) + return e +} + +// repoCase is one Experiments contract row. +type repoCase struct { + name, description string + run func(t *testing.T, rp store.Repos) +} + +func experiments(t *testing.T, open Opener) { + ctx := context.Background() + for _, tc := range slices.Concat(experimentRoundTripCases(ctx), experimentQueryCases(ctx), experimentListCases(ctx)) { + t.Run(tc.name, func(t *testing.T) { + t.Log(tc.description) + tc.run(t, open(t).Repos()) + }) + } +} + +// experimentRoundTripCases covers what Save writes and Get reads back. +func experimentRoundTripCases(ctx context.Context) []repoCase { + return []repoCase{ + {"insert-relational", "positive: cohort, phases, baseline and evidence references reconstruct the experiment exactly", func(t *testing.T, rp store.Repos) { + e := populated() + must(t, rp.Experiments.Save(ctx, e)) + got, err := rp.Experiments.Get(ctx, e.ID) + must(t, err) + sameExperiment(t, "expected the saved experiment", got, e) + exists, err := rp.Experiments.Exists(ctx, e.ID) + must(t, err) + if !exists { + t.Fatal("expected Exists to be true") + } + baseline, err := rp.Evidence.Get(ctx, "baseline") + must(t, err) + sameEvidence(t, "expected the baseline stored once in the evidence repository", baseline, e.Baseline) + }}, + {"update-replaces", "positive: saving again replaces status, revision, phases and evidence references", func(t *testing.T, rp store.Repos) { + e := populated() + must(t, rp.Experiments.Save(ctx, e)) + n := e.Clone() + n.Status = treatment.StatusComplete + n.Revision = 3 + n.UpdatedAt = now.Add(time.Hour) + n.Phases = n.Phases[:1] + n.Phases[0].Outcome = treatment.OutcomeStableObserved + must(t, rp.Experiments.Save(ctx, n)) + got, err := rp.Experiments.Get(ctx, e.ID) + must(t, err) + sameExperiment(t, "expected the replacement with the trailing phase removed", got, n) + }}, + {"cohort-immutable", "corner: the cohort order written first is kept even if a later save differs", func(t *testing.T, rp store.Repos) { + e := populated() + must(t, rp.Experiments.Save(ctx, e)) + n := e.Clone() + n.CohortOrder = n.CohortOrder[:2] + must(t, rp.Experiments.Save(ctx, n)) + got, err := rp.Experiments.Get(ctx, e.ID) + must(t, err) + if len(got.CohortOrder) != 16 { + t.Fatalf("expected the 16-host cohort to survive, got %d", len(got.CohortOrder)) + } + }}, + {"no-evidence", "boundary: an experiment without baseline, latest evidence or phases round-trips", func(t *testing.T, rp store.Repos) { + e := &treatment.Experiment{ID: "bare", Location: locationCst, Hypothesis: "h", Treatment: fixtures.Treatment(), Policy: treatment.DefaultPolicy(), Status: treatment.StatusProposed, Revision: 1, ProposedAt: now, UpdatedAt: now} + must(t, rp.Experiments.Save(ctx, e)) + got, err := rp.Experiments.Get(ctx, "bare") + must(t, err) + sameExperiment(t, "expected the bare experiment", got, e) + }}, + {"max-cohort", "boundary: a cohort of MaxAgents positions is stored in order", func(t *testing.T, rp store.Repos) { + e := &treatment.Experiment{ID: "big", Location: locationCst, Hypothesis: "h", Treatment: fixtures.Treatment(), Policy: treatment.DefaultPolicy(), Status: treatment.StatusProposed, Revision: 1, ProposedAt: now, UpdatedAt: now} + for i := range treatment.MaxAgents { + e.CohortOrder = append(e.CohortOrder, fmt.Sprintf("host-%05d", i)) + } + must(t, rp.Experiments.Save(ctx, e)) + got, err := rp.Experiments.Get(ctx, "big") + must(t, err) + if !slices.Equal(got.CohortOrder, e.CohortOrder) { + t.Fatalf("expected %d ordered cohort members, got %d", len(e.CohortOrder), len(got.CohortOrder)) + } + }}, + } +} + +// Numbered returns populated() renamed to exp-, with evidence IDs of its +// own so many copies can share one store. +func Numbered(i int) *treatment.Experiment { + e := populated() + e.ID = fmt.Sprintf("exp-%03d", i) + e.Baseline.ID = e.ID + "-baseline" + after := e.LatestEvidence.Clone() + after.ID = e.ID + "-after" + e.LatestEvidence, e.Phases[0].Evidence = after, after.Clone() + return e +} + +// experimentListCases covers List: every row it returns must equal Get. +func experimentListCases(ctx context.Context) []repoCase { + return []repoCase{ + {"list-many", "positive: List of 50 experiments returns each in ID order, equal to Get", func(t *testing.T, rp store.Repos) { + for i := range 50 { + must(t, rp.Experiments.Save(ctx, Numbered(49-i))) + } + list, err := rp.Experiments.List(ctx, "", 1000) + must(t, err) + if len(list) != 50 { + t.Fatalf("expected 50 experiments, got %d", len(list)) + } + for i, got := range list { + sameExperiment(t, got.ID, got, Numbered(i)) + } + }}, + {"shared-evidence", "positive: latest evidence and phase 0 share an ID and each gets its own copy", func(t *testing.T, rp store.Repos) { + must(t, rp.Experiments.Save(ctx, populated())) + list, err := rp.Experiments.List(ctx, "exp", 10) + must(t, err) + if len(list) != 1 { + t.Fatalf("expected one experiment, got %d", len(list)) + } + e := list[0] + if e.LatestEvidence == nil || e.Phases[0].Evidence == nil || e.LatestEvidence == e.Phases[0].Evidence { + t.Fatal("expected two distinct copies of the shared evidence") + } + sameEvidence(t, "shared evidence", e.Phases[0].Evidence, e.LatestEvidence) + }}, + {"limit-one", "boundary: limit 1 returns only the lowest ID", func(t *testing.T, rp store.Repos) { + for i := range 4 { + must(t, rp.Experiments.Save(ctx, Numbered(3-i))) + } + list, err := rp.Experiments.List(ctx, "", 1) + must(t, err) + if len(list) != 1 || list[0].ID != "exp-000" { + t.Fatalf("expected only exp-000, got %d", len(list)) + } + }}, + {"no-children", "boundary: an experiment without phases, cohort or evidence lists with nil evidence", func(t *testing.T, rp store.Repos) { + e := &treatment.Experiment{ID: "bare", Location: locationCst, Hypothesis: "h", Treatment: fixtures.Treatment(), Policy: treatment.DefaultPolicy(), Status: treatment.StatusProposed, Revision: 1, ProposedAt: now, UpdatedAt: now} + must(t, rp.Experiments.Save(ctx, e)) + list, err := rp.Experiments.List(ctx, "", 10) + must(t, err) + if len(list) != 1 { + t.Fatalf("expected one experiment, got %d", len(list)) + } + got := list[0] + if got.Baseline != nil || got.LatestEvidence != nil || len(got.Phases) != 0 || len(got.CohortOrder) != 0 { + t.Fatalf("expected no children, got %+v", got) + } + sameExperiment(t, "bare experiment", got, e) + }}, + } +} + +// experimentQueryCases covers lookups, conflicts, listing and status filters. +func experimentQueryCases(ctx context.Context) []repoCase { + return []repoCase{ + {missingCst, "negative: an unknown experiment is ErrNotFound and does not exist", func(t *testing.T, rp store.Repos) { + if _, err := rp.Experiments.Get(ctx, "ghost"); !errors.Is(err, store.ErrNotFound) { + t.Fatalf("expected ErrNotFound, got %v", err) + } + exists, err := rp.Experiments.Exists(ctx, "ghost") + must(t, err) + if exists { + t.Fatal("expected Exists to be false") + } + list, err := rp.Experiments.List(ctx, "ghost", 10) + must(t, err) + if len(list) != 0 { + t.Fatalf("expected an empty list, got %d", len(list)) + } + }}, + {"evidence-conflict", "negative: an experiment cannot claim evidence another experiment stored", func(t *testing.T, rp store.Repos) { + e := populated() + must(t, rp.Experiments.Save(ctx, e)) + other := e.Clone() + other.ID = "other" + if err := rp.Experiments.Save(ctx, other); !errors.Is(err, store.ErrEvidenceConflict) { + t.Fatalf("expected ErrEvidenceConflict, got %v", err) + } + exists, err := rp.Experiments.Exists(ctx, "other") + must(t, err) + if exists { + t.Fatal("expected the conflicting save to leave no row") + } + }}, + {"list-and-ids", "positive: List orders by ID and honors the limit; IDs filters by status", func(t *testing.T, rp store.Repos) { + for i, s := range []treatment.Status{treatment.StatusRunning, treatment.StatusProposed, treatment.StatusRetired, treatment.StatusRunning} { + e := &treatment.Experiment{ID: fmt.Sprintf("e%d", 3-i), Location: locationCst, Hypothesis: "h", Treatment: fixtures.Treatment(), Policy: treatment.DefaultPolicy(), Status: s, Revision: 1, ProposedAt: now, UpdatedAt: now} + must(t, rp.Experiments.Save(ctx, e)) + } + list, err := rp.Experiments.List(ctx, "", 3) + must(t, err) + ids := make([]string, len(list)) + for i, e := range list { + ids[i] = e.ID + } + if !slices.Equal(ids, []string{"e0", "e1", "e2"}) { + t.Fatalf("expected e0,e1,e2, got %v", ids) + } + one, err := rp.Experiments.List(ctx, "e3", 3) + must(t, err) + if len(one) != 1 || one[0].ID != "e3" { + t.Fatalf("expected only e3, got %d", len(one)) + } + running, err := rp.Experiments.IDs(ctx, treatment.StatusRunning, treatment.StatusPaused) + must(t, err) + none, err := rp.Experiments.IDs(ctx) + must(t, err) + if !slices.Equal(running, []string{"e0", "e3"}) || len(none) != 0 { + t.Fatalf("expected [e0 e3] and nothing for no statuses, got %v %v", running, none) + } + }}, + } +} + +// eligibility is the discovery contract: which prior experiments reserve a +// destination or consume the location's single-experiment budget. +func eligibility(t *testing.T, open Opener) { + ctx := context.Background() + dst := netip.MustParsePrefix(destinationCst) + for _, tc := range []struct { + name, description string + status treatment.Status + age time.Duration + location, destination string + expectBlocked bool + expectActive bool + }{ + {"proposed", "positive: pending review reserves the destination", treatment.StatusProposed, 48 * time.Hour, locationCst, destinationCst, true, true}, + {"running", "positive: an active trial is not rediscovered", treatment.StatusRunning, 48 * time.Hour, locationCst, destinationCst, true, true}, + {"paused", "positive: paused trials remain reserved", treatment.StatusPaused, 48 * time.Hour, locationCst, destinationCst, true, true}, + {"suspended", "positive: temporary holds are not bypassed", treatment.StatusSuspended, 48 * time.Hour, locationCst, destinationCst, true, true}, + {"stable", "positive: completed stable treatments stay reserved and free the budget", treatment.StatusComplete, 48 * time.Hour, locationCst, destinationCst, true, false}, + {"recent-rollback", "negative: a recent withdrawal is in cooldown", treatment.StatusRolledBack, 23 * time.Hour, locationCst, destinationCst, true, false}, + {"recent-retirement", "negative: a recent retirement is in cooldown", treatment.StatusRetired, 23 * time.Hour, locationCst, destinationCst, true, false}, + {"cooldown-boundary", "boundary: cooldown ends at exactly 24 hours", treatment.StatusRolledBack, 24 * time.Hour, locationCst, destinationCst, false, false}, + {"old-retirement", "boundary: an old retirement does not reserve the destination", treatment.StatusRetired, 25 * time.Hour, locationCst, destinationCst, false, false}, + {"other-location", "corner: reservation is location specific", treatment.StatusRunning, time.Hour, "dc2", destinationCst, false, false}, + {"other-destination", "corner: another destination consumes the budget only", treatment.StatusRunning, time.Hour, locationCst, "192.0.2.2/32", false, true}, + {"covering-prefix", "corner: a /24 experiment does not reserve a /32 inside it", treatment.StatusRunning, time.Hour, locationCst, "192.0.2.0/24", false, true}, + } { + t.Run(tc.name, func(t *testing.T) { + rp := open(t).Repos() + tr := fixtures.Treatment() + tr.Destination = netip.MustParsePrefix(tc.destination) + must(t, rp.Experiments.Save(ctx, &treatment.Experiment{ID: "prior", Location: tc.location, Hypothesis: "h", Treatment: tr, Policy: treatment.DefaultPolicy(), Status: tc.status, Revision: 1, ProposedAt: now.Add(-tc.age), UpdatedAt: now.Add(-tc.age)})) + blocked, err := rp.Experiments.DestinationBlocked(ctx, locationCst, dst, now.Add(-24*time.Hour)) + must(t, err) + active, err := rp.Experiments.HasActive(ctx, locationCst) + must(t, err) + if blocked != tc.expectBlocked || active != tc.expectActive { + t.Fatalf("%s: blocked=%t active=%t, expected %t/%t", tc.description, blocked, active, tc.expectBlocked, tc.expectActive) + } + }) + } + t.Run("v6-destination", func(t *testing.T) { + t.Log("corner: a /128 destination is reserved by exact match") + rp := open(t).Repos() + tr := fixtures.Treatment() + tr.Destination = netip.MustParsePrefix("2001:db8::1/128") + must(t, rp.Experiments.Save(ctx, &treatment.Experiment{ID: "v6", Location: locationCst, Hypothesis: "h", Treatment: tr, Policy: treatment.DefaultPolicy(), Status: treatment.StatusRunning, Revision: 1, ProposedAt: now, UpdatedAt: now})) + hit, err := rp.Experiments.DestinationBlocked(ctx, locationCst, tr.Destination, now) + must(t, err) + miss, err := rp.Experiments.DestinationBlocked(ctx, locationCst, netip.MustParsePrefix("2001:db8::2/128"), now) + must(t, err) + if !hit || miss { + t.Fatalf("expected exact /128 match only, got hit=%t miss=%t", hit, miss) + } + }) +} + +func evidence(t *testing.T, open Opener) { + ctx := context.Background() + base := func() *treatment.Evidence { + return &treatment.Evidence{ID: "ev-1", AnalyzedAt: now, WindowStart: now.Add(-time.Hour), WindowEnd: now, QueryVersion: "v1", EnrichmentVersion: "e1", ArtifactSHA256: strings.Repeat("b", 64), Hosts: []treatment.HostEvidence{{AgentID: host1Cst, Sockets: 10, BytesAcked: 1 << 20, GoodputBps: 1e6, RetransmissionRatio: .001, RttP95Ms: 2.5, ExposedSockets: 9, CollectionHealthy: true}}} + } + for _, tc := range []struct { + name, description string + run func(t *testing.T, v store.Evidence) + }{ + {"roundtrip", "positive: every column and host row survives", func(t *testing.T, v store.Evidence) { + e := base() + must(t, v.Put(ctx, "exp", e)) + got, err := v.Get(ctx, "ev-1") + must(t, err) + sameEvidence(t, "expected the stored evidence", got, e) + }}, + {"idempotent", "positive: storing identical content again under the same owner is a no-op", func(t *testing.T, v store.Evidence) { + must(t, v.Put(ctx, "exp", base())) + must(t, v.Put(ctx, "exp", base())) + }}, + {"content-conflict", "negative: the same ID with different content is rejected", func(t *testing.T, v store.Evidence) { + must(t, v.Put(ctx, "exp", base())) + e := base() + e.Hosts[0].GoodputBps++ + if err := v.Put(ctx, "exp", e); !errors.Is(err, store.ErrEvidenceConflict) { + t.Fatalf("expected ErrEvidenceConflict, got %v", err) + } + got, err := v.Get(ctx, "ev-1") + must(t, err) + sameEvidence(t, "expected the original content to remain", got, base()) + }}, + {"owner-conflict", "negative: another experiment cannot adopt the evidence", func(t *testing.T, v store.Evidence) { + must(t, v.Put(ctx, "exp", base())) + if err := v.Put(ctx, "other", base()); !errors.Is(err, store.ErrEvidenceConflict) { + t.Fatalf("expected ErrEvidenceConflict, got %v", err) + } + }}, + {"nanosecond-clock", "corner: evidence stamped with a nanosecond clock re-saves after a microsecond read back", func(t *testing.T, v store.Evidence) { + e := base() + e.AnalyzedAt = e.AnalyzedAt.Add(1500 * time.Nanosecond) + e.WindowEnd = e.WindowEnd.Add(999 * time.Nanosecond) + must(t, v.Put(ctx, "exp", e)) + got, err := v.Get(ctx, "ev-1") + must(t, err) + must(t, v.Put(ctx, "exp", got)) + must(t, v.Put(ctx, "exp", e)) + }}, + {missingCst, "negative: unknown evidence is ErrNotFound", func(t *testing.T, v store.Evidence) { + if _, err := v.Get(ctx, "ghost"); !errors.Is(err, store.ErrNotFound) { + t.Fatalf("expected ErrNotFound, got %v", err) + } + }}, + {"no-hosts", "boundary: evidence with an empty population stores and reads back empty", func(t *testing.T, v store.Evidence) { + e := base() + e.Hosts = nil + must(t, v.Put(ctx, "exp", e)) + got, err := v.Get(ctx, "ev-1") + must(t, err) + if len(got.Hosts) != 0 { + t.Fatalf("expected no hosts, got %d", len(got.Hosts)) + } + }}, + {"max-hosts", "boundary: MaxAgents host rows are stored in order in one call", func(t *testing.T, v store.Evidence) { + e := base() + e.Hosts = nil + for i := range treatment.MaxAgents { + e.Hosts = append(e.Hosts, treatment.HostEvidence{AgentID: fmt.Sprintf("host-%05d", i), Sockets: uint64(i), BytesAcked: 1 << 20, GoodputBps: float64(i), RttP95Ms: 1, CollectionHealthy: i%2 == 0}) + } + must(t, v.Put(ctx, "exp", e)) + got, err := v.Get(ctx, "ev-1") + must(t, err) + if len(got.Hosts) != treatment.MaxAgents { + t.Fatalf("expected %d hosts, got %d", treatment.MaxAgents, len(got.Hosts)) + } + for i := range got.Hosts { + if got.Hosts[i] != e.Hosts[i] { + t.Fatalf("expected host %d to be %+v, got %+v", i, e.Hosts[i], got.Hosts[i]) + } + } + }}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Log(tc.description) + tc.run(t, open(t).Repos().Evidence) + }) + } +} + +func holds(t *testing.T, open Opener) { + ctx := context.Background() + for _, tc := range []struct { + name, description string + set, clear, ask []string + expected bool + }{ + {fleetScopeCst, "positive: a fleet hold answers any scope list containing it", []string{fleetScopeCst}, nil, []string{fleetScopeCst, locationScopeCst, agentScopeCst}, true}, + {"narrower", "positive: an agent hold is seen when asked for that agent", []string{agentScopeCst}, nil, []string{fleetScopeCst, locationScopeCst, agentScopeCst}, true}, + {"cleared", "negative: a cleared hold no longer answers", []string{fleetScopeCst}, []string{fleetScopeCst}, []string{fleetScopeCst}, false}, + {"other-scope", "negative: holds on other scopes do not answer", []string{"location:dc2"}, nil, []string{fleetScopeCst, locationScopeCst}, false}, + {"no-scopes", "boundary: asking for no scopes is never held", []string{fleetScopeCst}, nil, nil, false}, + {"clear-missing", "corner: clearing an absent scope is not an error and leaves others set", []string{fleetScopeCst}, []string{"agent:ghost"}, []string{fleetScopeCst}, true}, + {"reset-reason", "corner: setting a held scope again keeps it held", []string{fleetScopeCst, fleetScopeCst}, nil, []string{fleetScopeCst}, true}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Log(tc.description) + h := open(t).Repos().Holds + for _, s := range tc.set { + must(t, h.Set(ctx, s, "reason "+s)) + } + for _, s := range tc.clear { + must(t, h.Clear(ctx, s)) + } + got, err := h.Held(ctx, tc.ask...) + must(t, err) + if got != tc.expected { + t.Fatalf("expected held=%t, got %t", tc.expected, got) + } + }) + } +} + +func audit(t *testing.T, open Opener) { + ctx := context.Background() + for _, tc := range []struct { + name, description string + run func(t *testing.T, a store.Audit) + }{ + {"append-lookup", "positive: an event is found by request ID with its payload intact", func(t *testing.T, a store.Audit) { + must(t, a.Append(ctx, "operator/alice", "req-1", "review", []byte(`{"approve":true}`))) + got, err := a.Lookup(ctx, "req-1") + must(t, err) + if got.Actor != "operator/alice" || got.Kind != "review" || got.RequestID != "req-1" || got.Sequence < 1 || got.OccurredAt.IsZero() || !strings.Contains(string(got.Payload), `"approve"`) { + t.Fatalf("expected the appended event, got %+v", got) + } + }}, + {"duplicate-request", "negative: a request ID can be appended once", func(t *testing.T, a store.Audit) { + must(t, a.Append(ctx, "x", "req-1", "review", []byte(`{}`))) + if err := a.Append(ctx, "x", "req-1", "control", []byte(`{}`)); !errors.Is(err, store.ErrExists) { + t.Fatalf("expected ErrExists, got %v", err) + } + n, err := a.Count(ctx) + must(t, err) + if n != 1 { + t.Fatalf("expected one event, got %d", n) + } + }}, + {"anonymous-events", "boundary: events without a request ID never collide", func(t *testing.T, a store.Audit) { + must(t, a.Append(ctx, "maintenance", "", "renew", []byte(`{}`))) + must(t, a.Append(ctx, "maintenance", "", "renew", []byte(`{}`))) + n, err := a.Count(ctx) + must(t, err) + if n != 2 { + t.Fatalf("expected two events, got %d", n) + } + if _, err := a.Lookup(ctx, ""); !errors.Is(err, store.ErrNotFound) { + t.Fatalf("expected ErrNotFound for the empty request ID, got %v", err) + } + }}, + {missingCst, "negative: an unknown request ID is ErrNotFound", func(t *testing.T, a store.Audit) { + if _, err := a.Lookup(ctx, "ghost"); !errors.Is(err, store.ErrNotFound) { + t.Fatalf("expected ErrNotFound, got %v", err) + } + }}, + {"monotonic", "corner: sequence numbers increase in append order", func(t *testing.T, a store.Audit) { + var last int64 + for i := range 5 { + id := fmt.Sprintf("req-%d", i) + must(t, a.Append(ctx, "x", id, "k", []byte(`{}`))) + got, err := a.Lookup(ctx, id) + must(t, err) + if got.Sequence <= last { + t.Fatalf("expected sequence above %d, got %d", last, got.Sequence) + } + last = got.Sequence + } + }}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Log(tc.description) + tc.run(t, open(t).Repos().Audit) + }) + } +} + +func tx(t *testing.T, open Opener) { + ctx := context.Background() + t.Run("commit", func(t *testing.T) { + t.Log("positive: writes inside a successful Tx are visible afterwards") + s := open(t) + must(t, s.Tx(ctx, func(rp store.Repos) error { + if err := rp.Holds.Set(ctx, fleetScopeCst, "incident"); err != nil { + return err + } + return rp.Agents.Enroll(ctx, host1Cst, locationCst, fixtures.Desired(now)) + })) + held, err := s.Repos().Holds.Held(ctx, fleetScopeCst) + must(t, err) + if _, err := s.Repos().Agents.Get(ctx, host1Cst); err != nil || !held { + t.Fatalf("expected committed hold and agent, got held=%t err=%v", held, err) + } + }) + t.Run("rollback", func(t *testing.T) { + t.Log("negative: a failing Tx leaves no trace of its writes") + s := open(t) + boom := errors.New("boom") + err := s.Tx(ctx, func(rp store.Repos) error { + if err := rp.Holds.Set(ctx, fleetScopeCst, "incident"); err != nil { + return err + } + if err := rp.Audit.Append(ctx, "x", "req-1", "k", []byte(`{}`)); err != nil { + return err + } + return boom + }) + if !errors.Is(err, boom) { + t.Fatalf("expected the callback error, got %v", err) + } + held, err := s.Repos().Holds.Held(ctx, fleetScopeCst) + must(t, err) + n, err := s.Repos().Audit.Count(ctx) + must(t, err) + if held || n != 0 { + t.Fatalf("expected nothing persisted, got held=%t events=%d", held, n) + } + }) + t.Run("read-your-writes", func(t *testing.T) { + t.Log("positive: a Tx sees its own uncommitted writes") + s := open(t) + must(t, s.Tx(ctx, func(rp store.Repos) error { + if err := rp.Experiments.Save(ctx, populated()); err != nil { + return err + } + got, err := rp.Experiments.Get(ctx, "exp") + if err != nil { + return err + } + if got.Revision != 2 { + return fmt.Errorf("expected revision 2 inside the transaction, got %d", got.Revision) + } + return nil + })) + }) + t.Run("list-in-tx", func(t *testing.T) { listInTx(t, open) }) + t.Run("canceled-context", func(t *testing.T) { + t.Log("boundary: a canceled context fails the Tx and persists nothing") + s := open(t) + canceled, cancel := context.WithCancel(ctx) + cancel() + if err := s.Tx(canceled, func(rp store.Repos) error { return rp.Holds.Set(ctx, fleetScopeCst, "x") }); err == nil { + t.Fatal("expected an error from a canceled context") + } + held, err := s.Repos().Holds.Held(ctx, fleetScopeCst) + must(t, err) + if held { + t.Fatal("expected no hold after a canceled transaction") + } + }) + t.Run("serializes", func(t *testing.T) { + t.Log("corner: two concurrent Tx calls run one after the other, both commit, sequences stay monotonic") + s := open(t) + entered := make(chan struct{}) + var mu sync.Mutex + var order []string + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + must(t, s.Tx(ctx, func(rp store.Repos) error { + close(entered) + mu.Lock() + order = append(order, "first-start") + mu.Unlock() + time.Sleep(200 * time.Millisecond) + mu.Lock() + order = append(order, "first-end") + mu.Unlock() + return rp.Audit.Append(ctx, "x", "first", "k", []byte(`{}`)) + })) + }() + go func() { + defer wg.Done() + <-entered + must(t, s.Tx(ctx, func(rp store.Repos) error { + mu.Lock() + order = append(order, "second-start") + mu.Unlock() + return rp.Audit.Append(ctx, "x", "second", "k", []byte(`{}`)) + })) + }() + wg.Wait() + if !slices.Equal(order, []string{"first-start", "first-end", "second-start"}) { + t.Fatalf("expected the second transaction to wait for the first, got %v", order) + } + first, err := s.Repos().Audit.Lookup(ctx, "first") + must(t, err) + second, err := s.Repos().Audit.Lookup(ctx, "second") + must(t, err) + if first.Sequence >= second.Sequence { + t.Fatalf("expected sequence %d < %d", first.Sequence, second.Sequence) + } + }) +} + +// settle separates two stamps by more than a timestamptz microsecond so the +// watermark tests order them deterministically on either store. +// listInTx: List inside a Tx locks its rows and returns what List outside +// returns. +func listInTx(t *testing.T, open Opener) { + ctx := context.Background() + t.Log("corner: List inside a Tx locks its rows and returns what List outside returns") + s := open(t) + for i := range 3 { + must(t, s.Repos().Experiments.Save(ctx, Numbered(i))) + } + outside, err := s.Repos().Experiments.List(ctx, "", 10) + must(t, err) + must(t, s.Tx(ctx, func(rp store.Repos) error { + inside, err := rp.Experiments.List(ctx, "", 10) + if err != nil { + return err + } + if len(inside) != len(outside) { + return fmt.Errorf("expected %d experiments inside the transaction, got %d", len(outside), len(inside)) + } + for i := range inside { + sameExperiment(t, inside[i].ID, inside[i], outside[i]) + } + return nil + })) +} + +func settle() { time.Sleep(2 * time.Millisecond) } + +func lease(t *testing.T, open Opener) { + ctx := context.Background() + t.Run("free", func(t *testing.T) { + t.Log("positive: a free lease runs fn and reports held") + s := open(t) + ran := false + held, err := s.Lease(ctx, "housekeeping", func() error { ran = true; return nil }) + must(t, err) + if !held || !ran { + t.Fatalf("expected held and run, got held=%t ran=%t", held, ran) + } + }) + t.Run("held-elsewhere", func(t *testing.T) { + t.Log("corner: while one caller holds the lease a second caller is told so and fn never runs") + s := open(t) + entered, release := make(chan struct{}), make(chan struct{}) + var wg sync.WaitGroup + wg.Go(func() { + held, err := s.Lease(ctx, "housekeeping", func() error { close(entered); <-release; return nil }) + if err != nil || !held { + t.Errorf("first holder: held=%t err=%v", held, err) + } + }) + <-entered + held, err := s.Lease(ctx, "housekeeping", func() error { t.Error("second caller ran under a held lease"); return nil }) + must(t, err) + if held { + t.Fatal("expected the second caller to be refused") + } + close(release) + wg.Wait() + held, err = s.Lease(ctx, "housekeeping", func() error { return nil }) + must(t, err) + if !held { + t.Fatal("expected the lease to be free once the holder returned") + } + }) + t.Run("released-on-error", func(t *testing.T) { + t.Log("negative: fn's error is returned with held=true and the lease is released") + s := open(t) + boom := errors.New("boom") + held, err := s.Lease(ctx, "housekeeping", func() error { return boom }) + if !held || !errors.Is(err, boom) { + t.Fatalf("expected held with the callback error, got held=%t err=%v", held, err) + } + held, err = s.Lease(ctx, "housekeeping", func() error { return nil }) + must(t, err) + if !held { + t.Fatal("expected the lease to be free after a failed pass") + } + }) + t.Run("independent-names", func(t *testing.T) { + t.Log("boundary: different names are different leases") + s := open(t) + held, err := s.Lease(ctx, "a", func() error { + inner, err := s.Lease(ctx, "b", func() error { return nil }) + if err != nil || !inner { + return fmt.Errorf("expected lease b while holding a, got held=%t err=%v", inner, err) + } + return nil + }) + must(t, err) + if !held { + t.Fatal("expected lease a") + } + }) + t.Run("canceled-context", func(t *testing.T) { + t.Log("negative: a canceled context fails before fn runs") + s := open(t) + canceled, cancel := context.WithCancel(ctx) + cancel() + held, err := s.Lease(canceled, "housekeeping", func() error { t.Error("fn ran with a canceled context"); return nil }) + if err == nil || held { + t.Fatalf("expected an error and held=false, got held=%t err=%v", held, err) + } + }) +} + +func metrics(t *testing.T, open Opener) { + ctx := context.Background() + t.Run("empty", func(t *testing.T) { + t.Log("boundary: an empty store reports every gauge as zero") + got, err := open(t).Repos().Metrics.Snapshot(ctx, now) + must(t, err) + for _, k := range []string{"agents", "agents_connected", "agents_suspended", "assignments", "routes_verified", "routes_failed", "routes_expired", "experiments_pending", "experiments_running", "experiments_complete", "audit_events"} { + v, ok := got[k] + if !ok || v != 0 { + t.Fatalf("expected %s=0, got %v (present=%t)", k, v, ok) + } + } + }) + t.Run("populated", func(t *testing.T) { + t.Log("positive: gauges reflect agents, records, experiments and events") + s := open(t) + rp := s.Repos() + must(t, rp.Agents.Enroll(ctx, host1Cst, locationCst, fixtures.Desired(now))) + must(t, rp.Agents.Observe(ctx, report(host1Cst, locationCst), now.Add(-time.Minute))) + must(t, rp.Agents.Enroll(ctx, host2Cst, locationCst, &treatment.DesiredState{AgentID: host2Cst, Revision: 1, Suspended: true, IssuedAt: now})) + must(t, rp.Agents.Enroll(ctx, "host-3", locationCst, &treatment.DesiredState{AgentID: "host-3", Revision: 1, IssuedAt: now})) + must(t, rp.Agents.Observe(ctx, &treatment.AgentReport{AgentID: "host-3", Location: locationCst, Capabilities: treatment.Capabilities{BootID: "b"}, Records: []treatment.ApplicationRecord{{Assignment: fixtures.Desired(now).Assignments[0], Status: treatment.ApplyExpired, ExpiredLatched: true}}}, now.Add(-10*time.Minute))) + for id, st := range map[string]treatment.Status{"p": treatment.StatusProposed, "r": treatment.StatusRunning, "c": treatment.StatusComplete, "x": treatment.StatusRetired} { + must(t, rp.Experiments.Save(ctx, &treatment.Experiment{ID: id, Location: locationCst, Hypothesis: "h", Treatment: fixtures.Treatment(), Policy: treatment.DefaultPolicy(), Status: st, Revision: 1, ProposedAt: now, UpdatedAt: now})) + } + must(t, rp.Audit.Append(ctx, "x", "", "k", []byte(`{}`))) + got, err := rp.Metrics.Snapshot(ctx, now) + must(t, err) + expected := map[string]float64{"agents": 3, "agents_connected": 1, "agents_suspended": 2, "assignments": 1, "routes_verified": 1, "routes_failed": 1, "routes_expired": 1, "experiments_pending": 1, "experiments_running": 1, "experiments_complete": 1, "audit_events": 1} + for k, v := range expected { + if got[k] != v { + t.Errorf("expected %s=%g, got %g", k, v, got[k]) + } + } + }) +} + +func must(t *testing.T, err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } +} diff --git a/pkg/treatment/enums.go b/pkg/treatment/enums.go new file mode 100644 index 000000000..d757dd73e --- /dev/null +++ b/pkg/treatment/enums.go @@ -0,0 +1,223 @@ +package treatment + +import "fmt" + +// The enumerations below are the domain's own. Their numeric values mirror +// the xtcp_treatment.v1 protobuf enums one-for-one so the wire package can +// convert with a range-checked cast; wire's mirror tests pin that +// correspondence. Names are the snake_case forms used in SQL, logs and docs. + +// unspecifiedNameCst names the zero value of every enumeration. +const unspecifiedNameCst = "unspecified" + +// Status is an experiment's lifecycle state. Legal changes are the state +// machine in package experiment. +type Status uint8 + +const ( + StatusUnspecified Status = iota + StatusProposed + StatusRunning + StatusPaused + StatusSuspended + StatusComplete + StatusRetired + StatusRolledBack + statusCount +) + +var statusNames = [statusCount]string{unspecifiedNameCst, "proposed", "running", "paused", "suspended", "complete", "retired", "rolled_back"} + +func (s Status) String() string { return enumName(uint8(s), statusNames[:], "status") } + +// Valid reports whether s is a defined, non-zero status. +func (s Status) Valid() bool { return s > StatusUnspecified && s < statusCount } + +// Active reports whether the experiment still consumes the location's budget. +func (s Status) Active() bool { + return s == StatusProposed || s == StatusRunning || s == StatusPaused || s == StatusSuspended +} + +// Terminal reports whether no event can move the experiment again. +func (s Status) Terminal() bool { return s == StatusRetired || s == StatusRolledBack } + +// ParseStatus accepts the snake_case name. +func ParseStatus(s string) (Status, error) { + i, err := parseEnum(s, statusNames[:], "status") + return Status(i), err +} + +// Statuses lists every defined status including unspecified, for exhaustive tests. +func Statuses() []Status { + out := make([]Status, 0, statusCount) + for s := StatusUnspecified; s < statusCount; s++ { + out = append(out, s) + } + return out +} + +// AssignmentMode says what an agent must do with an assignment. +type AssignmentMode uint8 + +const ( + ModeUnspecified AssignmentMode = iota + // ModeTrial installs the treatment until the lease expires. + ModeTrial + // ModeStable installs the treatment without a lease. + ModeStable + // ModeSuspended withdraws the treatment but keeps the assignment. + ModeSuspended + // ModeRetired withdraws the treatment; the assignment is a tombstone. + ModeRetired + modeCount +) + +var modeNames = [modeCount]string{unspecifiedNameCst, "trial", "stable", "suspended", "retired"} + +func (m AssignmentMode) String() string { return enumName(uint8(m), modeNames[:], "mode") } + +// Valid reports whether m is a defined, non-zero mode. +func (m AssignmentMode) Valid() bool { return m > ModeUnspecified && m < modeCount } + +// Installs reports whether the mode asks the agent to keep a route present. +func (m AssignmentMode) Installs() bool { return m == ModeTrial || m == ModeStable } + +// ParseAssignmentMode accepts the snake_case name. +func ParseAssignmentMode(s string) (AssignmentMode, error) { + i, err := parseEnum(s, modeNames[:], "assignment mode") + return AssignmentMode(i), err +} + +// ApplyStatus is an agent's report of one assignment's kernel state. +type ApplyStatus uint8 + +const ( + ApplyUnspecified ApplyStatus = iota + ApplyPending + ApplyVerified + ApplyRemoved + ApplyExpired + ApplyFailed + applyCount +) + +var applyNames = [applyCount]string{unspecifiedNameCst, "pending", "verified", "removed", "expired", "failed"} + +func (a ApplyStatus) String() string { return enumName(uint8(a), applyNames[:], "apply status") } + +// Valid reports whether a is a defined value. Unspecified is accepted: an +// agent may report an assignment it has not acted on yet. +func (a ApplyStatus) Valid() bool { return a < applyCount } + +// ParseApplyStatus accepts the snake_case name. +func ParseApplyStatus(s string) (ApplyStatus, error) { + i, err := parseEnum(s, applyNames[:], "apply status") + return ApplyStatus(i), err +} + +// Outcome is the result of evaluating evidence against a phase, or of drift +// monitoring a completed treatment. +type Outcome uint8 + +const ( + OutcomeUnspecified Outcome = iota + OutcomeBaseline + OutcomeAwaitingApplication + OutcomeAwaitingExposure + OutcomeInsufficientDuration + OutcomeInsufficientData + OutcomeInsufficientControls + OutcomeStale + OutcomeUnavailable + OutcomeInconclusive + OutcomeSafetyOnly + OutcomeFinalSafety + OutcomeBeneficial + OutcomeHarmful + OutcomeExpired + OutcomeStableObserved + OutcomeStableEvidenceIncomplete + OutcomeStableRegressionReviewRequired + OutcomeObserving + outcomeCount +) + +var outcomeNames = [outcomeCount]string{ + unspecifiedNameCst, + "baseline", + "awaiting_application", + "awaiting_exposure", + "insufficient_duration", + "insufficient_data", + "insufficient_controls", + "stale", + "unavailable", + "inconclusive", + "safety_only", + "final_safety", + "beneficial", + "harmful", + "expired", + "stable_observed", + "stable_evidence_incomplete", + "stable_regression_review_required", + "observing", +} + +func (o Outcome) String() string { return enumName(uint8(o), outcomeNames[:], "outcome") } + +// Valid reports whether o is a known value. Unspecified is valid: it is the +// state of an experiment nothing has evaluated yet. +func (o Outcome) Valid() bool { return o < outcomeCount } + +// Promotable reports whether a reviewer may advance the phase on this +// outcome. Every other outcome blocks promotion. +func (o Outcome) Promotable() bool { + return o == OutcomeBeneficial || o == OutcomeSafetyOnly || o == OutcomeFinalSafety +} + +// Withdraws reports whether the safety controller must roll the experiment +// back on this outcome without waiting for a reviewer. +func (o Outcome) Withdraws() bool { return o == OutcomeHarmful || o == OutcomeExpired } + +// RenewsLease reports whether healthy evidence with this outcome may renew +// the current phase's trial leases. Stale or missing data cannot. +func (o Outcome) RenewsLease() bool { return o != OutcomeStale && o != OutcomeInsufficientData } + +// ParseOutcome accepts the snake_case names used in documentation, logs and +// the pre-enum journal format. +func ParseOutcome(s string) (Outcome, error) { + i, err := parseEnum(s, outcomeNames[:], "outcome") + return Outcome(i), err +} + +// Outcomes lists every defined outcome including unspecified. +func Outcomes() []Outcome { + out := make([]Outcome, 0, outcomeCount) + for o := OutcomeUnspecified; o < outcomeCount; o++ { + out = append(out, o) + } + return out +} + +// EnumCounts reports how many values each domain enumeration defines, so the +// wire package can assert the protobuf enums have exactly the same size. +func EnumCounts() (statuses, modes, applyStatuses, outcomes int) { + return int(statusCount), int(modeCount), int(applyCount), int(outcomeCount) +} + +func enumName(v uint8, names []string, kind string) string { + if int(v) < len(names) { + return names[v] + } + return fmt.Sprintf("%s(%d)", kind, v) +} + +func parseEnum(s string, names []string, kind string) (uint8, error) { + for i, n := range names { + if n == s { + return uint8(i), nil + } + } + return 0, fmt.Errorf("unknown %s %q", kind, s) +} diff --git a/pkg/treatment/experiment/benchmark_test.go b/pkg/treatment/experiment/benchmark_test.go new file mode 100644 index 000000000..b9c6c7a64 --- /dev/null +++ b/pkg/treatment/experiment/benchmark_test.go @@ -0,0 +1,64 @@ +package experiment + +import ( + "fmt" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +func fleetFixture(n int) (*treatment.Experiment, *treatment.Evidence, time.Time) { + now := time.Unix(1700000000, 0) + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + e.CohortOrder, e.Baseline.Hosts, v.Hosts = nil, nil, nil + e.Phases[0].TargetHosts = uint32(n / 2) + for i := range n { + id := fmt.Sprintf("host-%d", i) + h := treatment.HostEvidence{AgentID: id, Sockets: 100, ExposedSockets: 100, BytesAcked: 1 << 25, GoodputBps: 1e8, RttP95Ms: 5, CollectionHealthy: true} + e.CohortOrder = append(e.CohortOrder, id) + e.Baseline.Hosts = append(e.Baseline.Hosts, h) + current := h + if i < n/2 { + current.GoodputBps *= 1.3 + float64(i%7)*.001 + } + v.Hosts = append(v.Hosts, current) + } + return e, v, now +} + +func BenchmarkFleetEvidence(b *testing.B) { + for _, n := range []int{100, 1000, 10000} { + e, v, now := fleetFixture(n) + for _, op := range []struct { + name string + run func() error + }{ + {"Validate", func() error { return treatment.ValidateEvidence(v) }}, + {"Safety", func() error { + h, bad := HealthyEvidence(e, v, now) + if !h || bad { + return fmt.Errorf("unexpected safety result") + } + return nil + }}, + {"Evaluate", func() error { + got, err := Evaluate(e, v, now) + if err == nil && got.Outcome != treatment.OutcomeBeneficial { + return fmt.Errorf("unexpected outcome %s", got.Outcome) + } + return err + }}, + } { + b.Run(fmt.Sprintf("%s/%d", op.name, n), func(b *testing.B) { + b.ReportAllocs() + for b.Loop() { + if err := op.run(); err != nil { + b.Fatal(err) + } + } + }) + } + } +} diff --git a/pkg/treatment/experiment/boundaries_test.go b/pkg/treatment/experiment/boundaries_test.go new file mode 100644 index 000000000..abc7c5607 --- /dev/null +++ b/pkg/treatment/experiment/boundaries_test.go @@ -0,0 +1,232 @@ +package experiment + +import ( + "reflect" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +func TestEvaluationBoundaries(t *testing.T) { + now := time.Unix(1700000000, 0) + for _, tc := range []struct { + name, description string + want treatment.Outcome + wantError bool + change func(*treatment.Experiment, *treatment.Evidence) + }{ + {"no-phase", "unstarted experiment cannot be evaluated", treatment.OutcomeUnspecified, true, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases = nil }}, + {"no-observation", "all canaries must acknowledge exposure", treatment.OutcomeAwaitingExposure, false, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases[0].ObservationStartedAt = time.Time{} }}, + {"expiry-equality", "phase expires exactly at its deadline", treatment.OutcomeExpired, false, func(e *treatment.Experiment, _ *treatment.Evidence) { + e.Phases[0].IssuedAt = now.Add(-24 * time.Hour) + }}, + {"freshness-equality", "evidence at maximum age is usable", treatment.OutcomeBeneficial, false, func(_ *treatment.Experiment, v *treatment.Evidence) { v.WindowEnd = now.Add(-2 * time.Minute) }}, + {"freshness-over", "one nanosecond beyond maximum age is stale", treatment.OutcomeStale, false, func(_ *treatment.Experiment, v *treatment.Evidence) { + v.WindowEnd = now.Add(-2*time.Minute - time.Nanosecond) + }}, + {"clock-equality", "30 seconds of forward clock skew is allowed", treatment.OutcomeBeneficial, false, func(_ *treatment.Experiment, v *treatment.Evidence) { v.AnalyzedAt = now.Add(30 * time.Second) }}, + {"clock-over", "excess forward skew is rejected", treatment.OutcomeStale, false, func(_ *treatment.Experiment, v *treatment.Evidence) { + v.AnalyzedAt = now.Add(30*time.Second + time.Nanosecond) + }}, + {"duration-equality", "exactly minimum observation is sufficient", treatment.OutcomeBeneficial, false, func(_ *treatment.Experiment, v *treatment.Evidence) { + v.WindowStart = v.WindowEnd.Add(-30 * time.Minute) + }}, + {"duration-under", "one nanosecond short is insufficient", treatment.OutcomeInsufficientDuration, false, func(_ *treatment.Experiment, v *treatment.Evidence) { + v.WindowStart = v.WindowEnd.Add(-30*time.Minute + time.Nanosecond) + }}, + {"old-window", "pre-treatment data cannot support promotion", treatment.OutcomeInsufficientDuration, false, func(e *treatment.Experiment, v *treatment.Evidence) { + v.WindowStart = e.Phases[0].ObservationStartedAt.Add(-time.Nanosecond) + }}, + {"zero-target", "phase must have at least one canary", treatment.OutcomeUnspecified, true, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases[0].TargetHosts = 0 }}, + {"over-target", "phase cannot exceed fleet size", treatment.OutcomeUnspecified, true, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases[0].TargetHosts = 17 }}, + {"sample-equality", "exact sample and exposure thresholds suffice", treatment.OutcomeBeneficial, false, func(e *treatment.Experiment, v *treatment.Evidence) { + for i := range v.Hosts { + h := &v.Hosts[i] + h.Sockets = e.Policy.MinimumSocketsPerHost + h.ExposedSockets = h.Sockets + h.BytesAcked = e.Policy.MinimumBytesPerHost + } + }}, + {"missing-host", "missing cohort host blocks evaluation", treatment.OutcomeInsufficientData, false, func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts = v.Hosts[1:] }}, + {"missing-baseline", "missing baseline host blocks evaluation", treatment.OutcomeInsufficientData, false, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Baseline.Hosts = e.Baseline.Hosts[1:] }}, + {"low-bytes", "too few bytes blocks evaluation", treatment.OutcomeInsufficientData, false, func(e *treatment.Experiment, v *treatment.Evidence) { + v.Hosts[0].BytesAcked = e.Policy.MinimumBytesPerHost - 1 + }}, + {"zero-goodput", "zero goodput cannot enter log comparison", treatment.OutcomeInsufficientData, false, func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[0].GoodputBps = 0 }}, + {"zero-baseline-rtt", "zero baseline RTT cannot enter ratio", treatment.OutcomeInsufficientData, false, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Baseline.Hosts[0].RttP95Ms = 0 }}, + {"first-canary", "small cohorts permit safety review only", treatment.OutcomeSafetyOnly, false, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases[0].TargetHosts = 1 }}, + {"small-cohort-regression", "large goodput loss blocks small cohort promotion", treatment.OutcomeHarmful, false, func(e *treatment.Experiment, v *treatment.Evidence) { + e.Phases[0].TargetHosts = 1 + v.Hosts[0].GoodputBps = 1 + }}, + {"one-control", "one control cannot estimate variance", treatment.OutcomeInsufficientControls, false, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases[0].TargetHosts = 15 }}, + {"full-fleet", "last phase checks safety without controls", treatment.OutcomeFinalSafety, false, func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases[0].TargetHosts = 16 }}, + {"full-fleet-harm", "last phase still rejects goodput regression", treatment.OutcomeHarmful, false, func(e *treatment.Experiment, v *treatment.Evidence) { + e.Phases[0].TargetHosts = 16 + for i := range v.Hosts { + h := &v.Hosts[i] + h.GoodputBps = 1 + } + }}, + {"invalid-evidence", "malformed evidence fails before decision", treatment.OutcomeUnspecified, true, func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[0] = treatment.HostEvidence{} }}, + } { + t.Run(tc.name, func(t *testing.T) { + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + tc.change(e, v) + before := e.Clone() + evidenceBefore := v.Clone() + got, err := Evaluate(e, v, now) + if (err != nil) != tc.wantError || got.Outcome != tc.want { + t.Fatalf("%s: got %+v err=%v; want %s error=%t", tc.description, got, err, tc.want, tc.wantError) + } + if !reflect.DeepEqual(e, before) || !reflect.DeepEqual(v, evidenceBefore) { + t.Fatal("evaluation mutated its input") + } + }) + } +} + +func TestSafetyGateBoundaries(t *testing.T) { + now := time.Unix(1700000000, 0) + for _, tc := range []struct { + name, description string + change func(*treatment.Experiment, *treatment.Evidence) + healthy, harmful bool + }{ + {"healthy", "complete unchanged observations renew leases", func(*treatment.Experiment, *treatment.Evidence) {}, true, false}, + {"missing-host", "partial evidence cannot renew leases", func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts = v.Hosts[1:] }, false, false}, + {"unhealthy-collector", "collection failures cannot renew leases", func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[0].CollectionHealthy = false }, false, false}, + {"low-samples", "too few samples cannot renew leases", func(e *treatment.Experiment, v *treatment.Evidence) { + v.Hosts[0].Sockets = e.Policy.MinimumSocketsPerHost - 1 + v.Hosts[0].ExposedSockets = 0 + }, false, false}, + {"stale", "old observations cannot renew leases", func(_ *treatment.Experiment, v *treatment.Evidence) { v.WindowEnd = now.Add(-3 * time.Minute) }, false, false}, + {"loss-equality", "loss guard is strictly greater than its limit", func(e *treatment.Experiment, v *treatment.Evidence) { + v.Hosts[0].RetransmissionRatio = e.Policy.MaximumRetransmissionIncrease + }, true, false}, + {"loss-over", "excess loss is harmful", func(e *treatment.Experiment, v *treatment.Evidence) { + v.Hosts[0].RetransmissionRatio = e.Policy.MaximumRetransmissionIncrease + 1e-9 + }, false, true}, + {"rtt-equality", "exactly representable RTT limit is inclusive", func(e *treatment.Experiment, v *treatment.Evidence) { + e.Policy.MaximumRTTIncrease = .5 + v.Hosts[0].RttP95Ms = 1.5 + }, true, false}, + {"control-harm", "controls are protected too", func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[15].RttP95Ms = 10 }, false, true}, + {"partial-harm", "missing data does not conceal observed harm", func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts = v.Hosts[1:]; v.Hosts[0].RttP95Ms = 10 }, false, true}, + } { + t.Run(tc.name, func(t *testing.T) { + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + tc.change(e, v) + h, bad := HealthyEvidence(e, v, now) + if h != tc.healthy || bad != tc.harmful { + t.Fatalf("%s: healthy=%t harmful=%t; want %t/%t", tc.description, h, bad, tc.healthy, tc.harmful) + } + }) + } +} + +func TestAdvanceTransitions(t *testing.T) { + now := time.Unix(1700000000, 0) + for _, tc := range []struct { + name, description string + change func(*treatment.Experiment, *treatment.Evidence) + want treatment.Status + phases int + wantError bool + }{ + {"initial", "approved proposal starts one canary", func(e *treatment.Experiment, _ *treatment.Evidence) { + e.Phases = nil + e.Status = treatment.StatusProposed + }, treatment.StatusRunning, 1, false}, + {"promotion", "benefit permits the next reviewed phase", func(*treatment.Experiment, *treatment.Evidence) {}, treatment.StatusRunning, 2, false}, + {"completion", "full fleet safety review completes the experiment", func(e *treatment.Experiment, _ *treatment.Evidence) { e.Phases[0].TargetHosts = 16 }, treatment.StatusComplete, 1, false}, + {"rolled-back", "rolled back experiments cannot advance", func(e *treatment.Experiment, _ *treatment.Evidence) { e.Status = treatment.StatusRolledBack }, 0, 0, true}, + {"harm", "harm cannot be promoted", func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[0].RttP95Ms = 100 }, 0, 0, true}, + } { + t.Run(tc.name, func(t *testing.T) { + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + tc.change(e, v) + before := e.Clone() + got, err := Advance(e, v, now, "reviewer", "measured benefit") + if (err != nil) != tc.wantError { + t.Fatalf("%s: err=%v wantError=%t", tc.description, err, tc.wantError) + } + if err == nil { + if got.Status != tc.want || len(got.Phases) != tc.phases || got.Revision != e.Revision+1 { + t.Fatalf("%s: wrong transition: %v", tc.description, got) + } + last := got.Phases[len(got.Phases)-1] + if last.Reviewer != "reviewer" || last.Reason != "measured benefit" { + t.Fatal("review provenance missing") + } + } + if !reflect.DeepEqual(e, before) { + t.Fatal("advance mutated input") + } + }) + } +} + +func TestNextCohortBoundaries(t *testing.T) { + for _, tc := range []struct { + description string + current, total, want int + }{ + {"start smallest fleet", 0, 3, 1}, {"reserve two controls", 1, 3, 3}, {"start large fleet", 0, 10000, 1}, {"double first canary", 1, 10000, 2}, {"double second phase", 2, 10000, 4}, {"cap before consuming controls", 4096, 10000, 8192}, {"retain final two controls", 8192, 10000, 9998}, {"final reviewed expansion", 9998, 10000, 10000}, {"completed fleet is unchanged", 10000, 10000, 10000}, + } { + t.Run(tc.description, func(t *testing.T) { + if got := NextCohort(tc.current, tc.total); got != tc.want { + t.Fatalf("got %d want %d", got, tc.want) + } + }) + } +} + +func TestDefaultRTTGuardExactBoundary(t *testing.T) { + for _, tc := range []struct { + description string + rtt float64 + want treatment.Outcome + healthy bool + }{ + {"exactly ten percent increase is within the configured guard", 5.5, treatment.OutcomeBeneficial, true}, + {"measurable increase above ten percent is harmful", 5.500001, treatment.OutcomeHarmful, false}, + } { + t.Run(tc.description, func(t *testing.T) { + now := time.Unix(1700000000, 0) + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + for i := range e.Baseline.Hosts { + h := &e.Baseline.Hosts[i] + h.RttP95Ms = 5 + } + for i := range v.Hosts { + h := &v.Hosts[i] + h.RttP95Ms = tc.rtt + } + healthy, harm := HealthyEvidence(e, v, now) + if healthy != tc.healthy || harm == tc.healthy { + t.Errorf("safety gate healthy=%t harmful=%t; want healthy=%t", healthy, harm, tc.healthy) + } + got, err := Evaluate(e, v, now) + if err != nil || got.Outcome != tc.want { + t.Fatalf("evaluation %v %v; want %s", got, err, tc.want) + } + }) + } +} + +func TestRTTGuardFleetBoundary(t *testing.T) { + for _, n := range []int{100, 1000, 10000} { + e, v, now := fleetFixture(n) + for i := range v.Hosts { + h := &v.Hosts[i] + h.RttP95Ms = 5.5 + } + got, err := Evaluate(e, v, now) + if err != nil || got.Outcome != treatment.OutcomeBeneficial { + t.Errorf("%d hosts at exactly the RTT guard: %v %v", n, got, err) + } + } +} diff --git a/pkg/treatment/experiment/experiment.go b/pkg/treatment/experiment/experiment.go new file mode 100644 index 000000000..9ddd84ce5 --- /dev/null +++ b/pkg/treatment/experiment/experiment.go @@ -0,0 +1,313 @@ +// Package experiment is the controller's pure decision core: evidence +// evaluation, the safety gate, cohort growth, phase advancement and the +// experiment state machine. Every function here is a function of its inputs +// and now; persistence and authorization live in package controller. +package experiment + +import ( + "errors" + "fmt" + "math" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +type Evaluation struct { + Outcome treatment.Outcome + Improvement, LowerBound float64 +} + +// Evaluate compares per-host log changes against contemporaneous controls. +// The host is the randomization unit; polls and sockets are not replicates. +// A conservative Welch interval budgets minute-by-minute looks across all +// planned phases. This interval is a review aid, not an automatic promotion. +func Evaluate(e *treatment.Experiment, ev *treatment.Evidence, now time.Time) (Evaluation, error) { + if err := treatment.ValidateEvidence(ev); err != nil { + return Evaluation{}, err + } + phase := e.CurrentPhase() + if phase == nil { + return Evaluation{}, errors.New("experiment has no phase") + } + p := e.Policy + if o, ok := windowOutcome(&p, phase, ev, now); ok { + return Evaluation{Outcome: o}, nil + } + if e.Baseline == nil { + return Evaluation{}, errors.New("experiment has no baseline") + } + target := int(phase.TargetHosts) + if target < 1 || target > len(e.CohortOrder) { + return Evaluation{}, errors.New("invalid phase cohort size") + } + treated, control, o := cohortSamples(e, ev, target) + if o != treatment.OutcomeUnspecified { + return Evaluation{Outcome: o}, nil + } + // Guardrails protect controls as well as treated traffic. A shared-link + // regression is harmful even if treated hosts outperform their peers. + if treated.breaches(&p) || control.breaches(&p) { + return Evaluation{Outcome: treatment.OutcomeHarmful}, nil + } + return compare(&p, treated.goodput, control.goodput, len(e.CohortOrder)), nil +} + +// windowOutcome reports the outcome when the phase or the evidence window +// cannot support an evaluation yet: no exposure, expiry, stale evidence or +// too short a window. +func windowOutcome(p *treatment.Policy, phase *treatment.Phase, ev *treatment.Evidence, now time.Time) (treatment.Outcome, bool) { + switch { + case phase.ObservationStartedAt.IsZero(): + return treatment.OutcomeAwaitingExposure, true + case now.Sub(phase.IssuedAt) >= p.MaximumPhase: + return treatment.OutcomeExpired, true + case ev.AnalyzedAt.After(now.Add(30*time.Second)) || now.Sub(ev.WindowEnd) > p.MaximumEvidenceAge: + return treatment.OutcomeStale, true + case ev.WindowStart.Before(phase.ObservationStartedAt) || ev.WindowEnd.Sub(ev.WindowStart) < p.MinimumObservation: + return treatment.OutcomeInsufficientDuration, true + } + return treatment.OutcomeUnspecified, false +} + +// samples are one arm's per-host changes against the baseline: log goodput +// ratio, retransmission ratio difference and log RTT p95 ratio. +type samples struct{ goodput, retrans, latency []float64 } + +func newSamples(n int) samples { + return samples{make([]float64, 0, n), make([]float64, 0, n), make([]float64, 0, n)} +} + +func (s *samples) add(h, b *treatment.HostEvidence) { + s.goodput = append(s.goodput, math.Log(h.GoodputBps/b.GoodputBps)) + s.retrans = append(s.retrans, h.RetransmissionRatio-b.RetransmissionRatio) + s.latency = append(s.latency, math.Log1p((max(h.RttP95Ms, .001)-b.RttP95Ms)/b.RttP95Ms)) +} + +// breaches reports whether the arm's mean retransmission or RTT change +// exceeds the policy's guardrail. +func (s *samples) breaches(p *treatment.Policy) bool { + return mean(s.retrans) > p.MaximumRetransmissionIncrease || mean(s.latency) > math.Log1p(p.MaximumRTTIncrease) +} + +// cohortSamples splits the cohort into the treated first target hosts and +// the controls. A host without usable data, or a treated host not yet +// exposed, stops the evaluation with that outcome. +func cohortSamples(e *treatment.Experiment, ev *treatment.Evidence, target int) (treated, control samples, o treatment.Outcome) { + p := &e.Policy + base, current := hostIndex(e.Baseline.Hosts), hostIndex(ev.Hosts) + treated, control = newSamples(target), newSamples(len(e.CohortOrder)-target) + for i, id := range e.CohortOrder { + h, b := current[id], base[id] + if h == nil || b == nil || !h.CollectionHealthy || !b.CollectionHealthy || h.Sockets < p.MinimumSocketsPerHost || h.BytesAcked < p.MinimumBytesPerHost || h.GoodputBps <= 0 || b.GoodputBps <= 0 || b.RttP95Ms <= 0 { + return treated, control, treatment.OutcomeInsufficientData + } + if i >= target { + control.add(h, b) + continue + } + if h.ExposedSockets < p.MinimumSocketsPerHost { + return treated, control, treatment.OutcomeAwaitingExposure + } + treated.add(h, b) + } + return treated, control, treatment.OutcomeUnspecified +} + +// compare turns the treated and control goodput changes into an outcome. +// cohort is the full cohort size, used to budget the number of looks. +func compare(p *treatment.Policy, treated, control []float64, cohort int) Evaluation { + effect := mean(treated) - mean(control) + harmful := effect < -math.Log1p(p.MinimumImprovement) + switch { + case len(control) == 0 && harmful, len(treated) < int(p.MinimumTreatedHosts) && harmful: + return Evaluation{Outcome: treatment.OutcomeHarmful} + case len(control) == 0: + // Final 100% phase is a safety check; causal benefit was established + // before the last control cohort received the treatment. + return Evaluation{Outcome: treatment.OutcomeFinalSafety, Improvement: math.Expm1(effect)} + case len(treated) < int(p.MinimumTreatedHosts): + return Evaluation{Outcome: treatment.OutcomeSafetyOnly, Improvement: math.Expm1(effect)} + case len(control) < 2: + return Evaluation{Outcome: treatment.OutcomeInsufficientControls} + } + a, b := variance(treated)/float64(len(treated)), variance(control)/float64(len(control)) + se := math.Sqrt(a + b) + lower := effect + if se > 0 { + df := (a + b) * (a + b) / (a*a/float64(len(treated)-1) + b*b/float64(len(control)-1)) + looks := (math.Ceil(math.Log2(float64(cohort))) + 2) * math.Ceil(p.MaximumPhase.Minutes()) + lower -= studentQuantile(1-.05/looks, df) * se + } + out := Evaluation{Outcome: treatment.OutcomeInconclusive, Improvement: math.Expm1(effect), LowerBound: math.Expm1(lower)} + if lower > math.Log1p(p.MinimumImprovement) { + out.Outcome = treatment.OutcomeBeneficial + } + return out +} + +func hostIndex(hosts []treatment.HostEvidence) map[string]*treatment.HostEvidence { + m := make(map[string]*treatment.HostEvidence, len(hosts)) + for i := range hosts { + m[hosts[i].AgentID] = &hosts[i] + } + return m +} + +// HealthyEvidence is the fast safety gate, independent of the minimum benefit +// observation window. It also prevents missing hosts from renewing leases. +func HealthyEvidence(e *treatment.Experiment, v *treatment.Evidence, now time.Time) (healthy, harmful bool) { + if e.Baseline == nil || treatment.ValidateEvidence(v) != nil || v.AnalyzedAt.After(now.Add(30*time.Second)) || now.Sub(v.WindowEnd) > e.Policy.MaximumEvidenceAge { + return false, false + } + base, current := hostIndex(e.Baseline.Hosts), hostIndex(v.Hosts) + healthy = true + for _, id := range e.CohortOrder { + h, b := current[id], base[id] + if h == nil || b == nil || !h.CollectionHealthy || h.Sockets < e.Policy.MinimumSocketsPerHost || h.BytesAcked < e.Policy.MinimumBytesPerHost { + healthy = false + continue + } + if h.RetransmissionRatio-b.RetransmissionRatio > e.Policy.MaximumRetransmissionIncrease || b.RttP95Ms > 0 && (h.RttP95Ms-b.RttP95Ms)/b.RttP95Ms > e.Policy.MaximumRTTIncrease { + harmful = true + } + } + return healthy && !harmful, harmful +} + +func mean(x []float64) float64 { + if len(x) == 0 { + return 0 + } + s := 0. + for _, v := range x { + s += v + } + return s / float64(len(x)) +} +func variance(x []float64) float64 { + if len(x) < 2 { + return 0 + } + m, s := mean(x), 0. + for _, v := range x { + s += (v - m) * (v - m) + } + return s / float64(len(x)-1) +} + +// Continued fraction for the regularized incomplete beta, used for the +// Student-t CDF. Numerical Recipes' convergent fraction; bounded iterations. +func betaFraction(a, b, x float64) float64 { + const tiny = 1e-300 + c, d := 1., 1-(a+b)*x/(a+1) + if math.Abs(d) < tiny { + d = tiny + } + d = 1 / d + h := d + for m := 1; m <= 200; m++ { + mf := float64(m) + m2 := 2 * mf + for _, aa := range []float64{mf * (b - mf) * x / ((a - 1 + m2) * (a + m2)), -(a + mf) * (a + b + mf) * x / ((a + m2) * (a + 1 + m2))} { + d = 1 + aa*d + if math.Abs(d) < tiny { + d = tiny + } + c = 1 + aa/c + if math.Abs(c) < tiny { + c = tiny + } + d = 1 / d + delta := d * c + h *= delta + if aa < 0 && math.Abs(delta-1) < 1e-12 { + return h + } + } + } + return h +} +func betaRegularized(x, a, b float64) float64 { + if x <= 0 { + return 0 + } + if x >= 1 { + return 1 + } + lab, _ := math.Lgamma(a + b) + la, _ := math.Lgamma(a) + lb, _ := math.Lgamma(b) + bt := math.Exp(lab - la - lb + a*math.Log(x) + b*math.Log1p(-x)) + if x < (a+1)/(a+b+2) { + return bt * betaFraction(a, b, x) / a + } + return 1 - bt*betaFraction(b, a, 1-x)/b +} +func studentQuantile(p, df float64) float64 { + lo, hi := 0., 1e6 + for range 100 { + mid := (lo + hi) / 2 + cdf := 1 - .5*betaRegularized(df/(df+mid*mid), df/2, .5) + if cdf < p { + lo = mid + } else { + hi = mid + } + } + return (lo + hi) / 2 +} + +func NextCohort(current, total int) int { + if current == 0 { + return 1 + } + if current >= total-2 { + return total + } + return min(current*2, total-2) +} + +// Advance is pure and returns a new experiment. Callers persist it and all +// assignments in one PostgreSQL transaction after authenticating the reviewer. +func Advance(e *treatment.Experiment, ev *treatment.Evidence, now time.Time, reviewer, reason string) (*treatment.Experiment, error) { + n := e.Clone() + // Both outcomes of approval are checked up front so an illegal status + // fails before any evidence is attached to the phase. + if _, err := Transition(n.Status, EventApprove); err != nil { + return nil, err + } + target := 0 + if phase := n.CurrentPhase(); phase != nil { + target = int(phase.TargetHosts) + v, err := Evaluate(n, ev, now) + if err != nil { + return nil, err + } + if !v.Outcome.Promotable() { + return nil, fmt.Errorf("promotion blocked: %s", v.Outcome) + } + phase.Evidence = ev.Clone() + phase.Outcome = v.Outcome + phase.EvaluatedAt = now + phase.Reviewer = reviewer + phase.Reason = reason + if target == len(n.CohortOrder) { + status, err := Transition(n.Status, EventApproveFinal) + if err != nil { + return nil, err + } + n.Status = status + n.Revision++ + return n, nil + } + } + n.Phases = append(n.Phases, treatment.Phase{TargetHosts: uint32(NextCohort(target, len(n.CohortOrder))), IssuedAt: now, Reviewer: reviewer, Reason: reason}) + status, err := Transition(n.Status, EventApprove) + if err != nil { + return nil, err + } + n.Status = status + n.Revision++ + return n, nil +} diff --git a/pkg/treatment/experiment/experiment_test.go b/pkg/treatment/experiment/experiment_test.go new file mode 100644 index 000000000..6607528b3 --- /dev/null +++ b/pkg/treatment/experiment/experiment_test.go @@ -0,0 +1,119 @@ +package experiment + +import ( + "math" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +func TestEvaluationBenefitHarmAndEvidenceGates(t *testing.T) { + now := time.Now() + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + for _, tc := range []struct { + name string + want treatment.Outcome + change func(*treatment.Experiment, *treatment.Evidence) + }{ + {"benefit", treatment.OutcomeBeneficial, func(*treatment.Experiment, *treatment.Evidence) {}}, + {"loss", treatment.OutcomeHarmful, func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[0].RetransmissionRatio = .2 }}, + {"control harm", treatment.OutcomeHarmful, func(_ *treatment.Experiment, v *treatment.Evidence) { + for i := range v.Hosts[4:] { + h := &v.Hosts[4+i] + h.RttP95Ms = 3 + } + }}, + {"missing exposure", treatment.OutcomeAwaitingExposure, func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[0].ExposedSockets = 0 }}, + {"stale", treatment.OutcomeStale, func(_ *treatment.Experiment, v *treatment.Evidence) { v.WindowEnd = now.Add(-3 * time.Minute) }}, + {"missing data", treatment.OutcomeInsufficientData, func(_ *treatment.Experiment, v *treatment.Evidence) { v.Hosts[0].CollectionHealthy = false }}, + {"too early", treatment.OutcomeInsufficientDuration, func(_ *treatment.Experiment, v *treatment.Evidence) { v.WindowStart = now.Add(-5 * time.Minute) }}, + {"no benefit", treatment.OutcomeInconclusive, func(_ *treatment.Experiment, v *treatment.Evidence) { + for i := range v.Hosts { + h := &v.Hosts[i] + h.GoodputBps = 1e8 + } + }}, + } { + t.Run(tc.name, func(t *testing.T) { + n := e.Clone() + w := v.Clone() + tc.change(n, w) + got, err := Evaluate(n, w, now) + if err != nil || got.Outcome != tc.want { + t.Fatalf("got %+v %v want %s", got, err, tc.want) + } + }) + } +} + +func TestHealthyEvidenceSoakRTTRegression(t *testing.T) { + // Reproduce the low-netem failure: 5.305 -> 5.922ms crosses production's + // 10% guard. The fixture's explicit tolerance must still reject 180ms. + for _, tc := range []struct { + name string + limit, rtt, retrans float64 + wantHarm bool + }{ + {"production-rejects-observed-increase", .1, 5.922, .00005452860025083156, true}, + {"soak-allows-observed-increase", 1, 5.922, .00005452860025083156, false}, + {"soak-rejects-netem-regression", 1, 180, 0, true}, + {"soak-still-rejects-loss", 1, 5.305, .006, true}, + } { + t.Run(tc.name, func(t *testing.T) { + now := time.Now() + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + e.Policy.MaximumRTTIncrease = tc.limit + for i := range e.Baseline.Hosts { + h := &e.Baseline.Hosts[i] + h.RttP95Ms = 5.305 + } + for i := range v.Hosts { + h := &v.Hosts[i] + h.RttP95Ms = 5.305 + } + v.Hosts[0].RttP95Ms, v.Hosts[0].RetransmissionRatio = tc.rtt, tc.retrans + healthy, harmful := HealthyEvidence(e, v, now) + if harmful != tc.wantHarm || healthy == harmful { + t.Fatalf("healthy=%t harmful=%t", healthy, harmful) + } + }) + } +} +func TestAdvancePreservesInputAndRequiresReviewableEvidence(t *testing.T) { + now := time.Now() + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + next, err := Advance(e, v, now, "operator", "reviewed") + if err != nil { + t.Fatal(err) + } + if len(e.Phases) != 1 || len(next.Phases) != 2 || next.Phases[1].TargetHosts != 8 { + t.Fatal("incorrect phase transition") + } + if _, err = Advance(next, v, now, "operator", "reuse evidence"); err == nil { + t.Fatal("reused previous phase evidence") + } +} +func TestStudentQuantile(t *testing.T) { + for _, tc := range []struct{ p, df, want float64 }{{.975, 1, 12.706204736}, {.975, 10, 2.228138852}, {.95, 30, 1.697260887}} { + if got := studentQuantile(tc.p, tc.df); math.Abs(got-tc.want) > 1e-5 { + t.Fatalf("got %g want %g", got, tc.want) + } + } +} +func TestTenThousandAgentCohorts(t *testing.T) { + n := 0 + steps := 0 + for n < 10000 { + next := NextCohort(n, 10000) + if next <= n || next > 10000 { + t.Fatal("invalid growth") + } + n = next + steps++ + } + if steps > 16 { + t.Fatal("unexpected phases", steps) + } +} diff --git a/pkg/treatment/experiment/statemachine.go b/pkg/treatment/experiment/statemachine.go new file mode 100644 index 000000000..421320f4c --- /dev/null +++ b/pkg/treatment/experiment/statemachine.go @@ -0,0 +1,132 @@ +package experiment + +import ( + "errors" + "fmt" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +// Event is something that can change an experiment's status. Review, Control +// and Maintain all go through Transition, so the complete set of legal status +// changes is the table below and nothing else. +type Event uint8 + +const ( + eventUnspecified Event = iota + // EventApprove: a reviewer approved the proposal or the current phase; + // the next phase is issued. + EventApprove + // EventApproveFinal: a reviewer approved the last (100%) phase. + EventApproveFinal + // EventReject: a reviewer declined; the treatment is retired. + EventReject + // EventPause: an operator paused a running trial; routes stay in place. + EventPause + // EventSuspend: an operator suspended; routes are withdrawn but the + // experiment may be resumed. + EventSuspend + // EventResume: an operator resumed a held trial; a fresh phase of the + // same size is issued. + EventResume + // EventResumeStable: an operator resumed a held completed treatment. + EventResumeStable + // EventRollback: an operator or the safety controller withdrew the + // treatment and restored any predecessor. + EventRollback + // EventRetire: an operator ended the experiment without restoring a + // predecessor. + EventRetire + // EventExpire: the phase exceeded the policy's maximum duration. + EventExpire + // EventHarm: evidence crossed a guardrail. + EventHarm + eventCount +) + +var eventNames = [eventCount]string{"unspecified", "approve", "approve_final", "reject", "pause", "suspend", "resume", "resume_stable", "rollback", "retire", "expire", "harm"} + +func (e Event) String() string { + if e < eventCount { + return eventNames[e] + } + return fmt.Sprintf("event(%d)", uint8(e)) +} + +// Events lists every defined event, for exhaustive tests. +func Events() []Event { + out := make([]Event, 0, eventCount-1) + for e := EventApprove; e < eventCount; e++ { + out = append(out, e) + } + return out +} + +// ErrIllegalTransition is returned for any (status, event) pair not in the +// table. Callers map it to FailedPrecondition. +var ErrIllegalTransition = errors.New("illegal experiment transition") + +type transitionKey struct { + from treatment.Status + event Event +} + +const ( + proposed = treatment.StatusProposed + running = treatment.StatusRunning + paused = treatment.StatusPaused + suspended = treatment.StatusSuspended + complete = treatment.StatusComplete + retired = treatment.StatusRetired + rolledBack = treatment.StatusRolledBack +) + +// transitions is the whole state machine. Retired and rolled back are +// terminal: nothing reactivates them. A new experiment is proposed instead. +var transitions = map[transitionKey]treatment.Status{ + {proposed, EventApprove}: running, + {proposed, EventReject}: retired, + {proposed, EventSuspend}: suspended, + {proposed, EventRollback}: rolledBack, + {proposed, EventRetire}: retired, + + {running, EventApprove}: running, + {running, EventApproveFinal}: complete, + {running, EventReject}: retired, + {running, EventPause}: paused, + {running, EventSuspend}: suspended, + {running, EventRollback}: rolledBack, + {running, EventRetire}: retired, + {running, EventExpire}: rolledBack, + {running, EventHarm}: rolledBack, + + {paused, EventReject}: retired, + {paused, EventSuspend}: suspended, + {paused, EventResume}: running, + {paused, EventResumeStable}: complete, + {paused, EventRollback}: rolledBack, + {paused, EventRetire}: retired, + {paused, EventExpire}: rolledBack, + + {suspended, EventReject}: retired, + {suspended, EventSuspend}: suspended, // re-suspend with a new reason is a no-op change + {suspended, EventResume}: running, + {suspended, EventResumeStable}: complete, + {suspended, EventRollback}: rolledBack, + {suspended, EventRetire}: retired, + + {complete, EventReject}: retired, + {complete, EventSuspend}: suspended, + {complete, EventRollback}: rolledBack, + {complete, EventRetire}: retired, +} + +// Transition returns the status that follows from applying event to from, or +// ErrIllegalTransition. It is pure; callers bump the revision and persist. +func Transition(from treatment.Status, event Event) (treatment.Status, error) { + to, ok := transitions[transitionKey{from, event}] + if !ok { + return from, fmt.Errorf("%w: %s on %s", ErrIllegalTransition, event, from) + } + return to, nil +} diff --git a/pkg/treatment/experiment/statemachine_test.go b/pkg/treatment/experiment/statemachine_test.go new file mode 100644 index 000000000..b02e542ec --- /dev/null +++ b/pkg/treatment/experiment/statemachine_test.go @@ -0,0 +1,162 @@ +package experiment + +import ( + "errors" + "testing" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +// legal is the expected state machine written out independently of the +// implementation table. A pair missing here must return ErrIllegalTransition. +var legal = map[treatment.Status]map[Event]treatment.Status{ + proposed: { + EventApprove: running, + EventReject: retired, + EventSuspend: suspended, + EventRollback: rolledBack, + EventRetire: retired, + }, + running: { + EventApprove: running, + EventApproveFinal: complete, + EventReject: retired, + EventPause: paused, + EventSuspend: suspended, + EventRollback: rolledBack, + EventRetire: retired, + EventExpire: rolledBack, + EventHarm: rolledBack, + }, + paused: { + EventReject: retired, + EventSuspend: suspended, + EventResume: running, + EventResumeStable: complete, + EventRollback: rolledBack, + EventRetire: retired, + EventExpire: rolledBack, + }, + suspended: { + EventReject: retired, + EventSuspend: suspended, + EventResume: running, + EventResumeStable: complete, + EventRollback: rolledBack, + EventRetire: retired, + }, + complete: { + EventReject: retired, + EventSuspend: suspended, + EventRollback: rolledBack, + EventRetire: retired, + }, + retired: {}, + rolledBack: {}, + treatment.StatusUnspecified: {}, +} + +// TestTransitionExhaustive visits every (status, event) pair treatment.Statuses() +// and Events() can produce and checks it against the legal table, so +// adding a status, an event or a transition without updating both fails. +func TestTransitionExhaustive(t *testing.T) { + statuses, events := treatment.Statuses(), Events() + if len(statuses) != len(legal) { + t.Fatalf("legal table covers %d statuses, the domain defines %d", len(legal), len(statuses)) + } + if len(events) != int(eventCount)-1 { + t.Fatalf("Events() returned %d, want %d", len(events), eventCount-1) + } + visited, legalCount := 0, 0 + for _, from := range statuses { + row, ok := legal[from] + if !ok { + t.Fatalf("status %s has no row in the legal table", from) + } + for _, ev := range events { + visited++ + got, err := Transition(from, ev) + want, allowed := row[ev] + switch { + case allowed: + legalCount++ + if err != nil || got != want { + t.Errorf("%s on %s: got %s err=%v; want %s", ev, from, got, err, want) + } + case !errors.Is(err, ErrIllegalTransition): + t.Errorf("%s on %s: want ErrIllegalTransition, got %s err=%v", ev, from, got, err) + case got != from: + t.Errorf("%s on %s: illegal transition must leave the status unchanged, got %s", ev, from, got) + } + } + } + if visited != len(statuses)*len(events) { + t.Fatalf("visited %d pairs, want %d", visited, len(statuses)*len(events)) + } + if legalCount != len(transitions) { + t.Fatalf("implementation has %d transitions, legal table has %d", len(transitions), legalCount) + } +} + +func TestTransitionCases(t *testing.T) { + for _, tc := range []struct { + name, description string + from treatment.Status + event Event + expected treatment.Status + expectError bool + }{ + {"proposed-approve", "positive: first review starts the trial", proposed, EventApprove, running, false}, + {"running-approve", "positive: phase approval keeps running while cohorts remain", running, EventApprove, running, false}, + {"running-approve-final", "positive: approving the 100% phase completes", running, EventApproveFinal, complete, false}, + {"paused-resume-stable", "positive: a paused completed treatment resumes to complete", paused, EventResumeStable, complete, false}, + {"retired-approve", "negative: terminal status cannot be approved", retired, EventApprove, retired, true}, + {"rolled-back-resume", "negative: rollback is final", rolledBack, EventResume, rolledBack, true}, + {"proposed-pause", "negative: nothing to pause before the first phase", proposed, EventPause, proposed, true}, + {"complete-expire", "negative: completed treatments have no lease to expire", complete, EventExpire, complete, true}, + {"unspecified-status", "boundary: zero status accepts no event", treatment.StatusUnspecified, EventApprove, treatment.StatusUnspecified, true}, + {"unspecified-event", "boundary: zero event is never legal", running, eventUnspecified, running, true}, + {"event-count-sentinel", "boundary: the sentinel just past the last event is illegal", running, eventCount, running, true}, + {"unknown-event", "corner: an event value from a newer build is rejected, not defaulted", running, Event(200), running, true}, + {"suspended-suspend", "corner: re-suspending with a new reason is a self loop", suspended, EventSuspend, suspended, false}, + {"suspended-harm", "corner: no routes are installed while suspended, so harm cannot withdraw", suspended, EventHarm, suspended, true}, + } { + t.Run(tc.name, func(t *testing.T) { + got, err := Transition(tc.from, tc.event) + if (err != nil) != tc.expectError || got != tc.expected { + t.Fatalf("%s: got %s err=%v; expected %s error=%t", tc.description, got, err, tc.expected, tc.expectError) + } + if tc.expectError && !errors.Is(err, ErrIllegalTransition) { + t.Fatalf("%s: error %v is not ErrIllegalTransition", tc.description, err) + } + }) + } +} + +func TestTerminal(t *testing.T) { + for _, s := range treatment.Statuses() { + got := s.Terminal() + expected := len(legal[s]) == 0 && s != treatment.StatusUnspecified + if got != expected { + t.Errorf("Terminal(%s)=%t, expected %t", s, got, expected) + } + } +} + +func TestEventString(t *testing.T) { + for _, tc := range []struct { + description string + event Event + expected string + }{ + {"positive: first event", EventApprove, "approve"}, + {"positive: last event", EventHarm, "harm"}, + {"boundary: zero value", eventUnspecified, "unspecified"}, + {"boundary: sentinel", eventCount, "event(12)"}, + {"corner: far out of range", Event(255), "event(255)"}, + } { + if got := tc.event.String(); got != tc.expected { + t.Errorf("%s: got %q expected %q", tc.description, got, tc.expected) + } + } +} diff --git a/pkg/treatment/identity/identity.go b/pkg/treatment/identity/identity.go new file mode 100644 index 000000000..dfa00b221 --- /dev/null +++ b/pkg/treatment/identity/identity.go @@ -0,0 +1,109 @@ +// Package identity is the shared mTLS identity contract between the treatment +// controller, agents, operator tooling and tests. It is deliberately a leaf: +// it knows about certificates, SPIFFE URI SANs and gRPC peer metadata, and +// nothing about persistence, experiments or the wire schema. +// +// Certificates bind agent identity AND enrollment location. Merely presenting +// any certificate from the CA does not confer operator permissions. +// URI SANs: spiffe://xtcp/agent// or spiffe://xtcp/operator/. +package identity + +import ( + "context" + "crypto/x509" + "errors" + "strings" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/peer" + "google.golang.org/grpc/status" +) + +// Role is the principal class encoded in the certificate URI SAN. +type Role string + +const ( + RoleAgent Role = "agent" + RoleOperator Role = "operator" +) + +// Identity is the parsed principal. Location is empty for operators. +type Identity struct { + Role Role + ID string + Location string +} + +// ErrNoIdentity is returned when a certificate does not carry exactly one +// xtcp identity URI SAN. Two SANs are as invalid as zero: ambiguity fails. +var ErrNoIdentity = errors.New("exactly one xtcp identity URI SAN required") + +// FromCertificate parses the single xtcp SPIFFE URI SAN of a leaf certificate. +func FromCertificate(cert *x509.Certificate) (Identity, error) { + var found []Identity + for _, u := range cert.URIs { + if u.Scheme != "spiffe" || u.Host != "xtcp" || u.RawQuery != "" || u.Fragment != "" { + continue + } + p := strings.Split(strings.TrimPrefix(u.Path, "/"), "/") + switch { + case len(p) == 3 && p[0] == string(RoleAgent) && treatment.ValidID(p[1]) && treatment.ValidID(p[2]): + found = append(found, Identity{Role: RoleAgent, Location: p[1], ID: p[2]}) + case len(p) == 2 && p[0] == string(RoleOperator) && treatment.ValidID(p[1]): + found = append(found, Identity{Role: RoleOperator, ID: p[1]}) + } + } + if len(found) != 1 { + return Identity{}, ErrNoIdentity + } + return found[0], nil +} + +// FromPeer resolves the verified client certificate of the gRPC peer. Errors +// already carry gRPC status codes so handlers and interceptors can return +// them unchanged. +func FromPeer(ctx context.Context) (Identity, error) { + p, ok := peer.FromContext(ctx) + if !ok { + return Identity{}, status.Error(codes.Unauthenticated, "mTLS required") + } + t, ok := p.AuthInfo.(credentials.TLSInfo) + if !ok || len(t.State.VerifiedChains) == 0 || len(t.State.PeerCertificates) == 0 { + return Identity{}, status.Error(codes.Unauthenticated, "verified client certificate required") + } + id, e := FromCertificate(t.State.PeerCertificates[0]) + if e != nil { + return Identity{}, status.Error(codes.PermissionDenied, e.Error()) + } + return id, nil +} + +// Agent requires the caller to be the agent named by want. Agents may only +// speak for themselves; the controller passes the request's agent_id here. +// It uses the identity an interceptor already resolved when there is one. +func Agent(ctx context.Context, want string) (Identity, error) { + id, e := resolve(ctx) + if e != nil { + return id, e + } + if id.Role != RoleAgent || id.ID != want { + return Identity{}, status.Error(codes.PermissionDenied, "agent identity mismatch") + } + return id, nil +} + +// Operator requires an operator certificate and returns the operator ID, +// which callers record as the audit actor. It uses the identity an +// interceptor already resolved when there is one. +func Operator(ctx context.Context) (string, error) { + id, e := resolve(ctx) + if e != nil { + return "", e + } + if id.Role != RoleOperator { + return "", status.Error(codes.PermissionDenied, "operator certificate required") + } + return id.ID, nil +} diff --git a/pkg/treatment/identity/identity_test.go b/pkg/treatment/identity/identity_test.go new file mode 100644 index 000000000..514d66eb4 --- /dev/null +++ b/pkg/treatment/identity/identity_test.go @@ -0,0 +1,152 @@ +package identity + +import ( + "crypto/x509" + "net/url" + "strings" + "testing" +) + +func certWithURIs(t *testing.T, uris ...string) *x509.Certificate { + t.Helper() + c := &x509.Certificate{} + for _, raw := range uris { + u, e := url.Parse(raw) + if e != nil { + t.Fatal(e) + } + c.URIs = append(c.URIs, u) + } + return c +} + +// go test ./pkg/treatment/identity -run TestFromCertificate +func TestFromCertificate(t *testing.T) { + long := strings.Repeat("a", 128) + tests := []struct { + description string + uris []string + expected Identity + wantErr bool + }{ + { + description: "positive: agent SAN yields role, location and id", + uris: []string{"spiffe://xtcp/agent/dc1/host-1"}, + expected: Identity{Role: RoleAgent, Location: "dc1", ID: "host-1"}, + }, + { + description: "positive: operator SAN yields role and id with empty location", + uris: []string{"spiffe://xtcp/operator/alice"}, + expected: Identity{Role: RoleOperator, ID: "alice"}, + }, + { + description: "positive: foreign SANs are ignored around the one xtcp SAN", + uris: []string{"spiffe://other/agent/dc1/host-1", "https://example.com/x", "spiffe://xtcp/operator/bob"}, + expected: Identity{Role: RoleOperator, ID: "bob"}, + }, + { + description: "negative: no SAN at all", + uris: nil, + wantErr: true, + }, + { + description: "negative: two xtcp SANs are ambiguous and rejected", + uris: []string{"spiffe://xtcp/agent/dc1/host-1", "spiffe://xtcp/operator/alice"}, + wantErr: true, + }, + { + description: "negative: agent SAN missing the location segment", + uris: []string{"spiffe://xtcp/agent/host-1"}, + wantErr: true, + }, + { + description: "negative: operator SAN with an extra segment is not an agent either", + uris: []string{"spiffe://xtcp/operator/alice/extra"}, + wantErr: true, + }, + { + description: "negative: unknown role segment", + uris: []string{"spiffe://xtcp/root/dc1/host-1"}, + wantErr: true, + }, + { + description: "negative: wrong trust domain host", + uris: []string{"spiffe://xtcp2/agent/dc1/host-1"}, + wantErr: true, + }, + { + description: "negative: query string is rejected even with a valid path", + uris: []string{"spiffe://xtcp/agent/dc1/host-1?x=1"}, + wantErr: true, + }, + { + description: "negative: fragment is rejected even with a valid path", + uris: []string{"spiffe://xtcp/agent/dc1/host-1#f"}, + wantErr: true, + }, + { + description: "boundary: id at the maximum valid length is accepted", + uris: []string{"spiffe://xtcp/operator/" + long}, + expected: Identity{Role: RoleOperator, ID: long}, + }, + { + description: "boundary: id one byte over the maximum is rejected", + uris: []string{"spiffe://xtcp/operator/" + long + "a"}, + wantErr: true, + }, + { + description: "boundary: empty id segment is rejected", + uris: []string{"spiffe://xtcp/operator/"}, + wantErr: true, + }, + { + // url.Parse lowercases the scheme, and x509 parses SANs with it, + // so this is accepted. Recorded so the behavior is deliberate. + description: "corner: upper-case scheme is normalized by the URL parser and accepted", + uris: []string{"SPIFFE://xtcp/agent/dc1/host-1"}, + expected: Identity{Role: RoleAgent, Location: "dc1", ID: "host-1"}, + }, + { + description: "corner: escaped path separators are not segment separators", + uris: []string{"spiffe://xtcp/agent/dc/host%2Fextra"}, + wantErr: true, + }, + { + description: "corner: a trailing slash adds an empty segment and is rejected", + uris: []string{"spiffe://xtcp/agent/dc1/host-1/"}, + wantErr: true, + }, + { + description: "corner: an identical SAN repeated twice still counts as two", + uris: []string{"spiffe://xtcp/operator/alice", "spiffe://xtcp/operator/alice"}, + wantErr: true, + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + got, err := FromCertificate(certWithURIs(t, tc.uris...)) + if tc.wantErr { + if err == nil { + t.Fatalf("expected error, got %+v", got) + } + if got != (Identity{}) { + t.Fatalf("identity must be zero on error, got %+v", got) + } + return + } + if err != nil { + t.Fatal(err) + } + if got != tc.expected { + t.Fatalf("got %+v, expected %+v", got, tc.expected) + } + }) + } +} + +// go test ./pkg/treatment/identity -run TestLeaf +func TestLeaf(t *testing.T) { + if _, e := Leaf(nil); e == nil { + t.Fatal("nil config must not yield a leaf") + } +} diff --git a/pkg/treatment/identity/interceptor.go b/pkg/treatment/identity/interceptor.go new file mode 100644 index 000000000..0b46da5ba --- /dev/null +++ b/pkg/treatment/identity/interceptor.go @@ -0,0 +1,107 @@ +package identity + +import ( + "context" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// Policy maps full gRPC method names ("/pkg.Service/Method") to the Role a +// caller must present. The controller derives it from the proto's per-RPC +// role option; this package only enforces it. A method absent from the +// policy is refused for everyone, so an RPC added without a declaration +// fails closed rather than open. +type Policy map[string]Role + +type ctxKey struct{} + +// WithIdentity stores a resolved identity so handlers do not parse the +// certificate again. +func WithIdentity(ctx context.Context, id Identity) context.Context { + return context.WithValue(ctx, ctxKey{}, id) +} + +// FromContext returns the identity an interceptor resolved, if any. +func FromContext(ctx context.Context) (Identity, bool) { + id, ok := ctx.Value(ctxKey{}).(Identity) + return id, ok +} + +// resolve prefers the interceptor's identity and falls back to the peer, so +// handlers behave the same whether or not the interceptor ran (direct calls +// in tests, or a server wired without it). +func resolve(ctx context.Context) (Identity, error) { + if id, ok := FromContext(ctx); ok { + return id, nil + } + return FromPeer(ctx) +} + +// Authorize resolves the peer once and checks it against the policy for +// method. It returns a context carrying the identity for the handler. +func (p Policy) Authorize(ctx context.Context, method string) (context.Context, error) { + required, ok := p[method] + if !ok || required == "" { + return nil, status.Errorf(codes.PermissionDenied, "%s has no role declaration", method) + } + id, e := FromPeer(ctx) + if e != nil { + return nil, e + } + if id.Role != required { + return nil, status.Errorf(codes.PermissionDenied, "%s certificate required", required) + } + return WithIdentity(ctx, id), nil +} + +// agentRequest is the part of an agent RPC's request the interceptor can +// check generically: an agent speaks only for itself and only from its +// enrolled location. Requests without these fields are left to the handler. +func agentRequest(id Identity, req any) error { + if r, ok := req.(interface{ GetAgentId() string }); ok && r.GetAgentId() != id.ID { + return status.Error(codes.PermissionDenied, "agent identity mismatch") + } + if r, ok := req.(interface{ GetLocation() string }); ok && r.GetLocation() != "" && r.GetLocation() != id.Location { + return status.Error(codes.PermissionDenied, "agent location differs from certificate") + } + return nil +} + +// UnaryInterceptor enforces the policy for unary RPCs and hands the handler +// a context carrying the identity. +func (p Policy) UnaryInterceptor() grpc.UnaryServerInterceptor { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { + ctx, e := p.Authorize(ctx, info.FullMethod) + if e != nil { + return nil, e + } + if id, _ := FromContext(ctx); id.Role == RoleAgent { + if e = agentRequest(id, req); e != nil { + return nil, e + } + } + return handler(ctx, req) + } +} + +type identifiedStream struct { + grpc.ServerStream + ctx context.Context +} + +func (s identifiedStream) Context() context.Context { return s.ctx } + +// StreamInterceptor enforces the policy for streaming RPCs. The first +// message is not visible here, so per-request agent checks stay in the +// handler; the identity itself is resolved once and carried on the stream. +func (p Policy) StreamInterceptor() grpc.StreamServerInterceptor { + return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + ctx, e := p.Authorize(ss.Context(), info.FullMethod) + if e != nil { + return e + } + return handler(srv, identifiedStream{ServerStream: ss, ctx: ctx}) + } +} diff --git a/pkg/treatment/identity/interceptor_test.go b/pkg/treatment/identity/interceptor_test.go new file mode 100644 index 000000000..c516c0cb7 --- /dev/null +++ b/pkg/treatment/identity/interceptor_test.go @@ -0,0 +1,141 @@ +package identity + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "net/url" + "testing" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/peer" + "google.golang.org/grpc/status" +) + +// peerContext fakes a verified mTLS peer whose leaf carries the given SAN +// path; an empty path is a plaintext peer. +func peerContext(path string) context.Context { + if path == "" { + return context.Background() + } + u, _ := url.Parse("spiffe://xtcp/" + path) + cert := &x509.Certificate{URIs: []*url.URL{u}} + return peer.NewContext(context.Background(), &peer.Peer{AuthInfo: credentials.TLSInfo{State: tls.ConnectionState{PeerCertificates: []*x509.Certificate{cert}, VerifiedChains: [][]*x509.Certificate{{cert}}}}}) +} + +// agentRequestFixture mimics a request with the generic agent fields. +type agentRequestFixture struct{ agentID, location string } + +func (r agentRequestFixture) GetAgentId() string { return r.agentID } +func (r agentRequestFixture) GetLocation() string { return r.location } + +const ( + checkIn = "/xtcp_treatment.v1.AgentControlService/CheckIn" + propose = "/xtcp_treatment.v1.OperatorService/Propose" + watch = "/xtcp_treatment.v1.AgentControlService/WatchDesiredState" +) + +var testPolicy = Policy{checkIn: RoleAgent, watch: RoleAgent, propose: RoleOperator} + +func TestPolicyUnaryInterceptor(t *testing.T) { + for _, tc := range []struct { + name, description, peer, method string + request any + expected codes.Code + wantIdentity Identity + }{ + {"agent-calls-checkin", "positive: an agent certificate may call an agent RPC for itself", "agent/dc1/host-1", checkIn, agentRequestFixture{"host-1", "dc1"}, codes.OK, Identity{Role: RoleAgent, Location: "dc1", ID: "host-1"}}, + {"operator-calls-propose", "positive: an operator certificate may call an operator RPC", "operator/alice", propose, struct{}{}, codes.OK, Identity{Role: RoleOperator, ID: "alice"}}, + {"agent-calls-propose", "negative: an agent certificate cannot call an operator RPC", "agent/dc1/host-1", propose, struct{}{}, codes.PermissionDenied, Identity{}}, + {"operator-calls-checkin", "negative: an operator certificate cannot call an agent RPC", "operator/alice", checkIn, agentRequestFixture{"host-1", "dc1"}, codes.PermissionDenied, Identity{}}, + {"no-peer-cert", "negative: a plaintext peer is unauthenticated before any role check", "", propose, struct{}{}, codes.Unauthenticated, Identity{}}, + {"bad-spiffe-path", "negative: a certificate whose SAN is not an xtcp identity is refused", "agent/only-one-segment", checkIn, agentRequestFixture{"only-one-segment", ""}, codes.PermissionDenied, Identity{}}, + {"unclassified-method", "boundary: a method missing from the policy is refused for everyone (fail closed)", "operator/alice", "/xtcp_treatment.v1.OperatorService/Undeclared", struct{}{}, codes.PermissionDenied, Identity{}}, + {"agent-id-mismatch", "corner: an agent naming another host is refused before the handler", "agent/dc1/host-1", checkIn, agentRequestFixture{"host-2", "dc1"}, codes.PermissionDenied, Identity{}}, + {"location-mismatch", "corner: an agent reporting from another location is refused before the handler", "agent/dc1/host-1", checkIn, agentRequestFixture{"host-1", "dc2"}, codes.PermissionDenied, Identity{}}, + {"location-unset", "boundary: a request without a location leaves the location check to enrollment", "agent/dc1/host-1", checkIn, agentRequestFixture{"host-1", ""}, codes.OK, Identity{Role: RoleAgent, Location: "dc1", ID: "host-1"}}, + } { + t.Run(tc.name, func(t *testing.T) { + var seen Identity + called := false + handler := func(ctx context.Context, _ any) (any, error) { + called = true + seen, _ = FromContext(ctx) + return nil, nil + } + _, err := testPolicy.UnaryInterceptor()(peerContext(tc.peer), tc.request, &grpc.UnaryServerInfo{FullMethod: tc.method}, handler) + if status.Code(err) != tc.expected { + t.Fatalf("%s: got %v, expected %v", tc.description, err, tc.expected) + } + if called != (tc.expected == codes.OK) { + t.Fatalf("%s: handler called=%t", tc.description, called) + } + if seen != tc.wantIdentity { + t.Fatalf("%s: handler saw %+v, want %+v", tc.description, seen, tc.wantIdentity) + } + }) + } +} + +type fakeStream struct { + grpc.ServerStream + ctx context.Context +} + +func (s fakeStream) Context() context.Context { return s.ctx } + +func TestPolicyStreamInterceptor(t *testing.T) { + for _, tc := range []struct { + name, description, peer, method string + expected codes.Code + }{ + {"agent-watch", "positive: an agent may open an agent stream and the handler sees its identity once", "agent/dc1/host-1", watch, codes.OK}, + {"operator-watch", "negative: an operator cannot open an agent stream", "operator/alice", watch, codes.PermissionDenied}, + {"plaintext", "negative: a plaintext stream is unauthenticated", "", watch, codes.Unauthenticated}, + {"unclassified", "boundary: an undeclared stream method is refused", "agent/dc1/host-1", "/xtcp_treatment.v1.AgentControlService/Undeclared", codes.PermissionDenied}, + } { + t.Run(tc.name, func(t *testing.T) { + called := false + handler := func(_ any, ss grpc.ServerStream) error { + called = true + id, ok := FromContext(ss.Context()) + if !ok || id.ID != "host-1" { + return errors.New("stream lost identity") + } + // The handler's own check must not need to re-read the peer. + if _, err := Agent(ss.Context(), "host-1"); err != nil { + return err + } + return nil + } + err := testPolicy.StreamInterceptor()(nil, fakeStream{ctx: peerContext(tc.peer)}, &grpc.StreamServerInfo{FullMethod: tc.method}, handler) + if status.Code(err) != tc.expected || called != (tc.expected == codes.OK) { + t.Fatalf("%s: err=%v called=%t expected %v", tc.description, err, called, tc.expected) + } + }) + } +} + +func TestResolvePrefersInterceptorIdentity(t *testing.T) { + for _, tc := range []struct { + name, description string + ctx context.Context + want string + expected codes.Code + }{ + {"context", "positive: a resolved identity is reused without re-reading the peer", WithIdentity(context.Background(), Identity{Role: RoleOperator, ID: "alice"}), "alice", codes.OK}, + {"peer", "positive: without an interceptor the peer certificate is read", peerContext("operator/bob"), "bob", codes.OK}, + {"context-wins", "corner: the interceptor's identity takes precedence over a conflicting peer", WithIdentity(peerContext("agent/dc1/host-1"), Identity{Role: RoleOperator, ID: "carol"}), "carol", codes.OK}, + {"none", "negative: neither source yields an identity", context.Background(), "", codes.Unauthenticated}, + } { + t.Run(tc.name, func(t *testing.T) { + got, err := Operator(tc.ctx) + if status.Code(err) != tc.expected || got != tc.want { + t.Fatalf("%s: got %q %v", tc.description, got, err) + } + }) + } +} diff --git a/pkg/treatment/identity/mtls_test.go b/pkg/treatment/identity/mtls_test.go new file mode 100644 index 000000000..dd9b5ad02 --- /dev/null +++ b/pkg/treatment/identity/mtls_test.go @@ -0,0 +1,172 @@ +package identity + +import ( + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "net" + "net/url" + "os" + "path/filepath" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/status" + "google.golang.org/grpc/test/bufconn" +) + +// authProbe trusts the interceptor: it only reports what identity reached +// the handler, so a wrong answer here is the interceptor's fault. +type authProbe struct { + pb.UnimplementedAgentControlServiceServer + pb.UnimplementedOperatorServiceServer +} + +func (authProbe) CheckIn(ctx context.Context, r *pb.CheckInRequest) (*pb.CheckInResponse, error) { + id, ok := FromContext(ctx) + if !ok || id.Role != RoleAgent || id.ID != r.AgentId { + return nil, status.Error(codes.Internal, "interceptor did not resolve the agent") + } + return &pb.CheckInResponse{}, nil +} +func (authProbe) Inspect(ctx context.Context, _ *pb.InspectRequest) (*pb.InspectResponse, error) { + id, ok := FromContext(ctx) + if !ok || id.Role != RoleOperator { + return nil, status.Error(codes.Internal, "interceptor did not resolve the operator") + } + return &pb.InspectResponse{}, nil +} + +var probePolicy = Policy{ + "/xtcp_treatment.v1.AgentControlService/CheckIn": RoleAgent, + "/xtcp_treatment.v1.OperatorService/Inspect": RoleOperator, +} + +func TestMTLSHandshakesAndRoleBoundaries(t *testing.T) { + dir := t.TempDir() + now := time.Now() + caKey, e := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if e != nil { + t.Fatal(e) + } + ca := &x509.Certificate{SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: "test CA"}, NotBefore: now.Add(-time.Minute), NotAfter: now.Add(time.Hour), IsCA: true, BasicConstraintsValid: true, KeyUsage: x509.KeyUsageCertSign} + der, e := x509.CreateCertificate(rand.Reader, ca, ca, &caKey.PublicKey, caKey) + if e != nil { + t.Fatal(e) + } + caFile := filepath.Join(dir, "ca.crt") + if e = os.WriteFile(caFile, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), 0600); e != nil { + t.Fatal(e) + } + issue := func(name, identity string, server bool) *tls.Config { + t.Helper() + key, e := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if e != nil { + t.Fatal(e) + } + leaf := &x509.Certificate{SerialNumber: big.NewInt(int64(len(name) + 2)), NotBefore: now.Add(-time.Minute), NotAfter: now.Add(time.Hour), KeyUsage: x509.KeyUsageDigitalSignature} + if server { + leaf.DNSNames = []string{"controller.test"} + leaf.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} + } else { + u, e := url.Parse(identity) + if e != nil { + t.Fatal(e) + } + leaf.URIs = []*url.URL{u} + leaf.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} + } + der, e := x509.CreateCertificate(rand.Reader, leaf, ca, &key.PublicKey, caKey) + if e != nil { + t.Fatal(e) + } + keyDER, e := x509.MarshalPKCS8PrivateKey(key) + if e != nil { + t.Fatal(e) + } + certFile, keyFile := filepath.Join(dir, name+".crt"), filepath.Join(dir, name+".key") + if e = os.WriteFile(certFile, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}), 0600); e != nil { + t.Fatal(e) + } + if e = os.WriteFile(keyFile, pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: keyDER}), 0600); e != nil { + t.Fatal(e) + } + config, e := TLSConfig(certFile, keyFile, caFile, "controller.test", server) + if e != nil { + t.Fatal(e) + } + return config + } + listener := bufconn.Listen(1 << 20) + server := grpc.NewServer(grpc.Creds(credentials.NewTLS(issue("server", "", true))), grpc.ChainUnaryInterceptor(probePolicy.UnaryInterceptor()), grpc.ChainStreamInterceptor(probePolicy.StreamInterceptor())) + pb.RegisterAgentControlServiceServer(server, authProbe{}) + pb.RegisterOperatorServiceServer(server, authProbe{}) + go server.Serve(listener) + t.Cleanup(func() { + server.Stop() + if e := listener.Close(); e != nil { + t.Error(e) + } + }) + connect := func(config *tls.Config) *grpc.ClientConn { + t.Helper() + conn, e := grpc.NewClient("passthrough:///controller.test", grpc.WithTransportCredentials(credentials.NewTLS(config)), grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return listener.Dial() })) + if e != nil { + t.Fatal(e) + } + t.Cleanup(func() { + if e := conn.Close(); e != nil { + t.Error(e) + } + }) + return conn + } + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + agentTLS := issue("agent", "spiffe://xtcp/agent/dc1/host-1", false) + agent := connect(agentTLS) + if _, e = pb.NewAgentControlServiceClient(agent).CheckIn(ctx, &pb.CheckInRequest{AgentId: "host-1"}); e != nil { + t.Fatal("authenticated agent", e) + } + if _, e = pb.NewAgentControlServiceClient(agent).CheckIn(ctx, &pb.CheckInRequest{AgentId: "host-2"}); status.Code(e) != codes.PermissionDenied { + t.Fatal("cross-host access", e) + } + if _, e = pb.NewOperatorServiceClient(agent).Inspect(ctx, &pb.InspectRequest{}); status.Code(e) != codes.PermissionDenied { + t.Fatal("agent operator access", e) + } + operator := connect(issue("operator", "spiffe://xtcp/operator/alice", false)) + if _, e = pb.NewOperatorServiceClient(operator).Inspect(ctx, &pb.InspectRequest{}); e != nil { + t.Fatal("authenticated operator", e) + } + if _, e = pb.NewOperatorServiceClient(operator).Propose(ctx, &pb.ProposeRequest{}); status.Code(e) != codes.PermissionDenied { + t.Fatal("undeclared method must fail closed", e) + } + for name, config := range map[string]*tls.Config{"missing_client_certificate": agentTLS.Clone(), "wrong_server_name": agentTLS.Clone(), "untrusted_server": agentTLS.Clone()} { + t.Run(name, func(t *testing.T) { + switch name { + case "missing_client_certificate": + config.Certificates = nil + case "wrong_server_name": + config.ServerName = "wrong.test" + case "untrusted_server": + config.RootCAs = x509.NewCertPool() + } + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + _, e := pb.NewAgentControlServiceClient(connect(config)).CheckIn(ctx, &pb.CheckInRequest{AgentId: "host-1"}) + if e == nil { + t.Fatal("invalid TLS was accepted") + } + }) + } +} diff --git a/pkg/treatment/identity/tls.go b/pkg/treatment/identity/tls.go new file mode 100644 index 000000000..5e87668c9 --- /dev/null +++ b/pkg/treatment/identity/tls.go @@ -0,0 +1,46 @@ +package identity + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "os" +) + +// TLSConfig loads a leaf key pair and a private CA bundle. Both ends pin TLS +// 1.3 and trust only that CA; servers additionally require and verify a client +// certificate so every RPC arrives with a peer identity for FromPeer. +func TLSConfig(certFile, keyFile, caFile, serverName string, server bool) (*tls.Config, error) { + cert, e := tls.LoadX509KeyPair(certFile, keyFile) + if e != nil { + return nil, e + } + ca, e := os.ReadFile(caFile) + if e != nil { + return nil, e + } + roots := x509.NewCertPool() + if !roots.AppendCertsFromPEM(ca) { + return nil, errors.New("CA file has no certificates") + } + c := &tls.Config{ + MinVersion: tls.VersionTLS13, + Certificates: []tls.Certificate{cert}, + RootCAs: roots, + ServerName: serverName, + } + if server { + c.ClientCAs = roots + c.ClientAuth = tls.RequireAndVerifyClientCert + } + return c, nil +} + +// Leaf returns the parsed leaf certificate of a config built by TLSConfig, so +// a client can check its own identity before dialing anything. +func Leaf(c *tls.Config) (*x509.Certificate, error) { + if c == nil || len(c.Certificates) == 0 || len(c.Certificates[0].Certificate) == 0 { + return nil, errors.New("tls config has no leaf certificate") + } + return x509.ParseCertificate(c.Certificates[0].Certificate[0]) +} diff --git a/pkg/treatment/internal/fixtures/fixtures.go b/pkg/treatment/internal/fixtures/fixtures.go new file mode 100644 index 000000000..7521a6ae8 --- /dev/null +++ b/pkg/treatment/internal/fixtures/fixtures.go @@ -0,0 +1,72 @@ +// Package fixtures holds test fixtures shared by the treatment packages' +// tests, in domain form and, through package wire, in protobuf form for the +// code that still keeps messages at rest (the agent's journal). +package fixtures + +import ( + "fmt" + "net/netip" + "strings" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" +) + +func ptr[T any](v T) *T { return &v } + +// CollectionID is a well-formed collection nonce for reports and sessions. +const CollectionID = "0123456789abcdef0123456789abcdef" + +// Treatment is CUBIC on a single /32. +func Treatment() treatment.Treatment { + return treatment.Treatment{ID: "cubic", Revision: 1, Destination: netip.MustParsePrefix("192.0.2.1/32"), Settings: treatment.TCPSettings{CongestionControl: ptr("cubic")}} +} + +// Desired is a minimal valid desired state for agent host-1: one trial +// assignment of CUBIC to a single /32 with a one-hour lease. +func Desired(now time.Time) *treatment.DesiredState { + return &treatment.DesiredState{ + AgentID: "host-1", + Revision: 1, + IssuedAt: now, + Assignments: []treatment.Assignment{{ + ExperimentID: "trial-1", + Generation: 1, + Mode: treatment.ModeTrial, + LeaseExpiresAt: now.Add(time.Hour), + Treatment: Treatment(), + }}, + } +} + +// DesiredWire is Desired in protobuf form. +func DesiredWire(now time.Time) *pb.DesiredState { return wire.Desired(Desired(now)) } + +// Experiment is a running 16-host experiment at its first 4-host phase with +// baseline and a current evidence window in which the treated hosts gained 30%. +func Experiment(now time.Time, policy treatment.Policy) (*treatment.Experiment, *treatment.Evidence) { + b := &treatment.Evidence{ID: "baseline", AnalyzedAt: now.Add(-time.Hour), WindowStart: now.Add(-2 * time.Hour), WindowEnd: now.Add(-time.Hour), QueryVersion: "v1", ArtifactSHA256: strings.Repeat("a", 64)} + e := &treatment.Experiment{ID: "exp", Location: "dc1", Hypothesis: "cubic improves throughput", Treatment: Treatment(), Policy: policy, Baseline: b, Status: treatment.StatusRunning, Revision: 2, Phases: []treatment.Phase{{TargetHosts: 4, IssuedAt: now.Add(-40 * time.Minute), ObservationStartedAt: now.Add(-35 * time.Minute)}}} + for i := range 16 { + id := fmt.Sprintf("host-%d", i) + e.CohortOrder = append(e.CohortOrder, id) + b.Hosts = append(b.Hosts, treatment.HostEvidence{AgentID: id, Sockets: 100, ExposedSockets: 100, BytesAcked: 1 << 25, GoodputBps: 1e8, RttP95Ms: 1, CollectionHealthy: true}) + } + ev := b.Clone() + ev.ID = "after" + ev.WindowStart = now.Add(-34 * time.Minute) + ev.WindowEnd = now.Add(-time.Second) + ev.AnalyzedAt = now + for i := range ev.Hosts[:4] { + ev.Hosts[i].GoodputBps *= 1.3 + } + return e, ev +} + +// ExperimentWire is Experiment in protobuf form. +func ExperimentWire(now time.Time, policy treatment.Policy) (*pb.Experiment, *pb.Evidence) { + e, v := Experiment(now, policy) + return wire.Experiment(e), wire.Evidence(v) +} diff --git a/pkg/treatment/local/config.go b/pkg/treatment/local/config.go new file mode 100644 index 000000000..88a8a08f0 --- /dev/null +++ b/pkg/treatment/local/config.go @@ -0,0 +1,83 @@ +// Package local is the host-side configuration shared by every process that +// touches the treatment journal (the embedded or standalone agent, the +// watchdog and the treatmentctl commands) and the construction of the +// kernel-backed reconciler from it. It never speaks gRPC, never reads TLS +// material and never resolves DNS: the watchdog must work with the controller +// unreachable and the certificate expired. +package local + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "os" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +// Config is /etc/xtcp2/controller-agent.json. The controller and credential +// fields are only read by the agent; the watchdog ignores them. +type Config struct { + AgentID string `json:"agent_id"` + Location string `json:"location"` + Controller string `json:"controller"` + ServerName string `json:"server_name"` + Certificate string `json:"certificate"` + PrivateKey string `json:"private_key"` + CA string `json:"ca"` + Directory string `json:"directory"` + EnableApply bool `json:"enable_apply"` + Table uint32 `json:"table"` + RulePriority uint32 `json:"rule_priority"` + Protocol uint8 `json:"protocol"` + ProtectedPrefixes []string `json:"protected_prefixes"` +} + +// DefaultDirectory is where the journal lives unless the config says otherwise. +const DefaultDirectory = "/var/lib/xtcp2/routes" + +// LoadConfig reads and validates the JSON file, applying the private route +// table defaults. Unknown fields and trailing documents are errors so a typo +// can never silently disable a setting. +func LoadConfig(path string) (Config, error) { + var c Config + f, e := os.Open(path) + if e != nil { + return c, e + } + defer f.Close() + d := json.NewDecoder(io.LimitReader(f, 65537)) + d.DisallowUnknownFields() + if e = d.Decode(&c); e != nil { + return c, e + } + var extra any + if d.Decode(&extra) != io.EOF { + return c, errors.New("trailing config data") + } + if !treatment.ValidID(c.AgentID) || !treatment.ValidID(c.Location) || c.Controller == "" { + return c, errors.New("agent_id, location and controller are required") + } + c.applyDefaults() + return c, nil +} + +func (c *Config) applyDefaults() { + if c.Directory == "" { + c.Directory = DefaultDirectory + } + if c.Table == 0 { + c.Table = 10002 + } + if c.RulePriority == 0 { + c.RulePriority = 30000 + } + if c.Protocol == 0 { + c.Protocol = 242 + } +} + +func (c Config) String() string { + return fmt.Sprintf("agent=%s location=%s controller=%s apply=%t", c.AgentID, c.Location, c.Controller, c.EnableApply) +} diff --git a/pkg/treatment/local/helpers_test.go b/pkg/treatment/local/helpers_test.go new file mode 100644 index 000000000..4f2ccf6fa --- /dev/null +++ b/pkg/treatment/local/helpers_test.go @@ -0,0 +1,5 @@ +package local + +import "net/netip" + +func mustPrefix(s string) netip.Prefix { return netip.MustParsePrefix(s) } diff --git a/pkg/treatment/local/host.go b/pkg/treatment/local/host.go new file mode 100644 index 000000000..d1dcd7832 --- /dev/null +++ b/pkg/treatment/local/host.go @@ -0,0 +1,107 @@ +package local + +import ( + "context" + "errors" + "net/netip" + "os" + "strings" + + "github.com/randomizedcoder/xtcp2/internal/goip/actuate" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" + "golang.org/x/sys/unix" +) + +// Identity is what the kernel says about the process: the boot it runs in +// and the network namespace it will mutate. +type Identity struct { + BootID string + NetnsInode uint64 +} + +// HostIdentity inspects the running host. The actuator must run in the host +// network namespace, because the routes it installs are host routes. +func HostIdentity() (Identity, error) { + boot, err := os.ReadFile("/proc/sys/kernel/random/boot_id") + if err != nil { + return Identity{}, err + } + var ns, initNS unix.Stat_t + if err = unix.Stat("/proc/self/ns/net", &ns); err != nil { + return Identity{}, err + } + if err = unix.Stat("/proc/1/ns/net", &initNS); err != nil { + return Identity{}, err + } + if ns.Ino != initNS.Ino { + return Identity{}, errors.New("actuator must run in the host network namespace") + } + return Identity{BootID: strings.TrimSpace(string(boot)), NetnsInode: ns.Ino}, nil +} + +// Host is the offline, mutation-capable half of an agent: the reconciler over +// the journal and the goip route backend. It is everything the watchdog and +// the local commands need and nothing the controller connection needs. +type Host struct { + Config Config + Identity Identity + Reconciler *reconcile.Reconciler + backend *routeBackend +} + +// New builds the Host. A nil identity inspects the running host; tests pass +// a fixed one so configuration and lifecycle checks do not depend on +// permission to inspect PID 1's network namespace. +func New(c Config, id *Identity) (*Host, error) { + if !treatment.ValidID(c.AgentID) || !treatment.ValidID(c.Location) { + return nil, errors.New("invalid local agent identity") + } + c.applyDefaults() + if id == nil { + v, err := HostIdentity() + if err != nil { + return nil, err + } + id = &v + } + b := &routeBackend{Backend: &actuate.Backend{Table: c.Table, Priority: c.RulePriority, Protocol: c.Protocol, Enabled: c.EnableApply}} + for _, v := range c.ProtectedPrefixes { + p, err := netip.ParsePrefix(v) + if err != nil { + return nil, err + } + b.Protected = append(b.Protected, p) + } + if c.EnableApply && len(b.Protected) == 0 { + return nil, errors.New("protected_prefixes must cover management, DNS and telemetry networks before enabling application") + } + h := &Host{Config: c, Identity: *id, backend: b} + h.Reconciler = &reconcile.Reconciler{Journal: reconcile.Journal{Dir: c.Directory}, Backend: b, AgentID: c.AgentID, Location: c.Location, BootID: id.BootID} + return h, nil +} + +// Protect adds a prefix the backend must never override, such as the +// controller's own addresses. +func (h *Host) Protect(p netip.Prefix) { h.backend.Protected = append(h.backend.Protected, p) } + +// SimpleHostRouting reports whether the host's rule table is the plain shape +// the treatment routes are designed for. +func (h *Host) SimpleHostRouting(ctx context.Context) bool { return h.backend.Check(ctx) == nil } + +// routeBackend adapts goip's treatment backend to the reconcile.Backend +// contract: it validates the domain treatment and maps it onto goip's own +// route type, so goip never imports the treatment packages. +type routeBackend struct{ *actuate.Backend } + +func (b *routeBackend) Plan(ctx context.Context, t *treatment.Treatment) ([]byte, error) { + if err := treatment.ValidateTreatment(t); err != nil { + return nil, err + } + s := t.Settings + return b.Backend.Plan(ctx, &actuate.RouteTreatment{Destination: t.Destination.String(), Settings: &actuate.TCPRouteSettings{ + CongestionControl: s.CongestionControl, CongestionLock: s.CongestionLock, RtoMinMs: s.RTOMinMs, + InitialCongestionWindow: s.InitialCongestionWindow, InitialReceiveWindow: s.InitialReceiveWindow, + QuickAck: s.QuickAck, Ecn: s.ECN, + }}) +} diff --git a/pkg/treatment/local/local_test.go b/pkg/treatment/local/local_test.go new file mode 100644 index 000000000..675e06cf6 --- /dev/null +++ b/pkg/treatment/local/local_test.go @@ -0,0 +1,110 @@ +package local + +import ( + "context" + "os" + "path/filepath" + "strings" + "testing" +) + +func TestLoadConfigContracts(t *testing.T) { + for _, tc := range []struct{ name, description, input, wantError string }{ + {"defaults", "positive: minimal config receives safe defaults", `{"agent_id":"host","location":"dc","controller":"localhost:9000"}`, ""}, + {"explicit", "positive: explicit private route settings are preserved", `{"agent_id":"host","location":"dc","controller":"localhost:9000","table":10003,"rule_priority":30001,"protocol":243}`, ""}, + {"unknown", "negative: typos cannot silently disable settings", `{"agent_id":"host","location":"dc","controller":"localhost:9000","enable_aply":true}`, "unknown field"}, + {"trailing", "negative: two JSON documents are rejected", `{} {}`, "trailing"}, + {"missing", "negative: enrollment fields are required", `{}`, "required"}, + {"bad-id", "negative: path-like agent identity is rejected", `{"agent_id":"../host","location":"dc","controller":"localhost:9000"}`, "required"}, + {"malformed", "corner: truncated JSON is rejected", `{`, "EOF"}, + {"oversized", "boundary: oversized config cannot bypass the limit", `{"agent_id":"host","location":"dc","controller":"` + strings.Repeat("x", 65537) + `"}`, "EOF"}, + } { + t.Run(tc.name, func(t *testing.T) { + path := filepath.Join(t.TempDir(), "agent.json") + if err := os.WriteFile(path, []byte(tc.input), 0600); err != nil { + t.Fatal(err) + } + c, err := LoadConfig(path) + if tc.wantError != "" { + if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("%s: expected %q, got %v", tc.description, tc.wantError, err) + } + return + } + if err != nil { + t.Fatal(err) + } + wantTable, wantPriority, wantProtocol := uint32(10002), uint32(30000), uint8(242) + if tc.name == "explicit" { + wantTable++ + wantPriority++ + wantProtocol++ + } + if c.Table != wantTable || c.RulePriority != wantPriority || c.Protocol != wantProtocol || c.EnableApply || c.Directory != DefaultDirectory { + t.Fatalf("%s: unexpected config %+v", tc.description, c) + } + if !strings.Contains(c.String(), "agent=host") { + t.Fatal("config diagnostic missing identity") + } + }) + } + if _, err := LoadConfig(filepath.Join(t.TempDir(), "missing.json")); err == nil { + t.Fatal("missing file accepted") + } +} + +func TestNewHostContracts(t *testing.T) { + testIdentity := &Identity{BootID: "boot", NetnsInode: 123} + for _, tc := range []struct { + name, description string + change func(*Config) + wantError string + }{ + {"offline", "positive: offline construction needs no TLS, DNS or controller", func(*Config) {}, ""}, + {"identity", "negative: invalid agent identity fails before initialization", func(c *Config) { c.AgentID = "../host" }, "identity"}, + {"location", "negative: invalid location fails before initialization", func(c *Config) { c.Location = "" }, "identity"}, + {"bad-prefix", "negative: malformed protected prefixes fail closed", func(c *Config) { c.ProtectedPrefixes = []string{"bad"} }, "ParsePrefix"}, + {"no-exclusions", "negative: application requires management exclusions", func(c *Config) { c.EnableApply = true }, "protected_prefixes"}, + {"protected", "positive: explicit exclusions allow backend construction without writes", func(c *Config) { c.EnableApply = true; c.ProtectedPrefixes = []string{"192.0.2.0/24"} }, ""}, + {"defaults", "boundary: a config built in code without the loader still gets the table defaults", func(c *Config) { c.Table, c.RulePriority, c.Protocol = 0, 0, 0 }, ""}, + } { + t.Run(tc.name, func(t *testing.T) { + c := Config{AgentID: "host", Location: "dc", Directory: t.TempDir(), Table: 10002, RulePriority: 30000, Protocol: 242} + tc.change(&c) + h, err := New(c, testIdentity) + if tc.wantError != "" { + if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("%s: got %v want %q", tc.description, err, tc.wantError) + } + return + } + if err != nil { + t.Fatal(err) + } + if h.Identity != *testIdentity || h.Reconciler.BootID != "boot" || h.Reconciler.AgentID != "host" || h.Reconciler.Location != "dc" || h.Reconciler.Journal.Dir != c.Directory { + t.Fatalf("%s: reconciler not wired from config: %+v", tc.description, h.Reconciler) + } + if h.Config.Table != 10002 || h.Config.RulePriority != 30000 || h.Config.Protocol != 242 { + t.Fatalf("%s: defaults not applied: %+v", tc.description, h.Config) + } + before := len(h.backend.Protected) + h.Protect(mustPrefix("198.51.100.1/32")) + if len(h.backend.Protected) != before+1 { + t.Fatal("Protect did not extend the exclusions") + } + }) + } +} + +// Plan validates the domain treatment before goip sees it, so an invalid +// treatment never reaches the kernel planner. +func TestRouteBackendPlanValidates(t *testing.T) { + h, err := New(Config{AgentID: "host", Location: "dc", Directory: t.TempDir()}, &Identity{BootID: "boot", NetnsInode: 1}) + if err != nil { + t.Fatal(err) + } + _, err = h.backend.Plan(context.Background(), nil) + if err == nil || !strings.Contains(err.Error(), "treatment requires") { + t.Fatalf("nil treatment planned: %v", err) + } +} diff --git a/pkg/treatment/model.go b/pkg/treatment/model.go new file mode 100644 index 000000000..0b8b415fc --- /dev/null +++ b/pkg/treatment/model.go @@ -0,0 +1,327 @@ +package treatment + +import ( + "net/netip" + "slices" + "time" +) + +// The types in this file are the controller's domain model. The protobuf +// messages in gen/go/xtcp_treatment are a wire format for them (see package +// wire) and the PostgreSQL tables are a storage format for them (see +// controller/store/postgres); neither is the model. Optional fields are +// pointers so "unset" survives every conversion. A zero time.Time means a +// timestamp was not set. + +// TCPSettings are the per-route socket parameters a treatment applies. +type TCPSettings struct { + CongestionControl *string + CongestionLock bool + RTOMinMs *uint32 + InitialCongestionWindow *uint32 + InitialReceiveWindow *uint32 + QuickAck *bool + ECN *bool +} + +// Empty reports whether no parameter is set. +func (s TCPSettings) Empty() bool { + return s.CongestionControl == nil && s.RTOMinMs == nil && s.InitialCongestionWindow == nil && s.InitialReceiveWindow == nil && s.QuickAck == nil && s.ECN == nil +} + +// Algorithm returns the congestion control name or "" when unset. +func (s TCPSettings) Algorithm() string { + if s.CongestionControl == nil { + return "" + } + return *s.CongestionControl +} + +// Equal compares every parameter including whether it is set. +func (s TCPSettings) Equal(o TCPSettings) bool { + return s.CongestionLock == o.CongestionLock && eqPtr(s.CongestionControl, o.CongestionControl) && eqPtr(s.RTOMinMs, o.RTOMinMs) && eqPtr(s.InitialCongestionWindow, o.InitialCongestionWindow) && eqPtr(s.InitialReceiveWindow, o.InitialReceiveWindow) && eqPtr(s.QuickAck, o.QuickAck) && eqPtr(s.ECN, o.ECN) +} + +func eqPtr[T comparable](a, b *T) bool { + if a == nil || b == nil { + return a == b + } + return *a == *b +} + +// Treatment is a versioned set of TCP settings for one host destination. +type Treatment struct { + ID string + Revision uint64 + // Destination is a /32 or /128 host prefix; the zero value is unset. + Destination netip.Prefix + Settings TCPSettings + ECNFabricVerified bool +} + +// Equal is a field-wise comparison. +func (t Treatment) Equal(o Treatment) bool { + return t.ID == o.ID && t.Revision == o.Revision && t.Destination == o.Destination && t.ECNFabricVerified == o.ECNFabricVerified && t.Settings.Equal(o.Settings) +} + +// Assignment binds a treatment to one agent on behalf of one experiment. +type Assignment struct { + ExperimentID string + Treatment Treatment + Mode AssignmentMode + // LeaseExpiresAt is zero for assignments without a lease. + LeaseExpiresAt time.Time + // Predecessor is the stable treatment this one replaced, restored on + // rollback. Nil when the destination had none. + Predecessor *Treatment + Generation uint64 +} + +// Equal compares every field, including the predecessor by value. +func (a Assignment) Equal(o Assignment) bool { + if a.ExperimentID != o.ExperimentID || a.Mode != o.Mode || a.Generation != o.Generation || !a.LeaseExpiresAt.Equal(o.LeaseExpiresAt) || !a.Treatment.Equal(o.Treatment) { + return false + } + if a.Predecessor == nil || o.Predecessor == nil { + return a.Predecessor == o.Predecessor + } + return a.Predecessor.Equal(*o.Predecessor) +} + +// Clone copies the predecessor so the two values share nothing. +func (a Assignment) Clone() Assignment { + if a.Predecessor != nil { + p := *a.Predecessor + a.Predecessor = &p + } + return a +} + +// DesiredState is everything the controller wants one agent to hold. +type DesiredState struct { + AgentID string + Revision uint64 + Suspended bool + Assignments []Assignment + IssuedAt time.Time +} + +// Equal compares the header and every assignment in order. +func (d *DesiredState) Equal(o *DesiredState) bool { + if d == nil || o == nil { + return d == o + } + if d.AgentID != o.AgentID || d.Revision != o.Revision || d.Suspended != o.Suspended || !d.IssuedAt.Equal(o.IssuedAt) || len(d.Assignments) != len(o.Assignments) { + return false + } + for i := range d.Assignments { + if !d.Assignments[i].Equal(o.Assignments[i]) { + return false + } + } + return true +} + +// Clone deep-copies the assignments. +func (d *DesiredState) Clone() *DesiredState { + if d == nil { + return nil + } + c := *d + c.Assignments = make([]Assignment, len(d.Assignments)) + for i := range d.Assignments { + c.Assignments[i] = d.Assignments[i].Clone() + } + return &c +} + +// Find returns a pointer into d.Assignments for the experiment, or nil. +func (d *DesiredState) Find(experimentID string) *Assignment { + for i := range d.Assignments { + if d.Assignments[i].ExperimentID == experimentID { + return &d.Assignments[i] + } + } + return nil +} + +// Capabilities are the facts an agent reports about its host. +type Capabilities struct { + BootID string + KernelRelease string + CongestionAlgorithms []string + SimpleHostRouting bool + ActuatorEnabled bool + // CollectionID is the agent process's nonce; see ValidCollectionID. + CollectionID string +} + +// Supports reports whether the host offers the congestion algorithm. +func (c Capabilities) Supports(algorithm string) bool { + return slices.Contains(c.CongestionAlgorithms, algorithm) +} + +// ApplicationRecord is an agent's report of what it did with one assignment. +type ApplicationRecord struct { + Assignment Assignment + DesiredRevision uint64 + Status ApplyStatus + ReceivedAt time.Time + AttemptedAt time.Time + AppliedAt time.Time + VerifiedAt time.Time + RemovedAt time.Time + Error string + ExpiredLatched bool +} + +// AgentReport is one check-in: identity, capabilities and the application +// records for every assignment the agent knows about. +type AgentReport struct { + AgentID string + Location string + Capabilities Capabilities + DesiredRevision uint64 + Records []ApplicationRecord + LocallySuspended bool +} + +// Record returns the record for the experiment, or nil. +func (r *AgentReport) Record(experimentID string) *ApplicationRecord { + for i := range r.Records { + if r.Records[i].Assignment.ExperimentID == experimentID { + return &r.Records[i] + } + } + return nil +} + +// Session is one (boot, collection nonce) pair an agent reported at +// check-in, with when the controller first and last heard it. Evidence +// counts only records stamped with a session of the agent they name. +type Session struct { + AgentID, BootID, CollectionID string + FirstSeen, LastSeen time.Time +} + +// HostEvidence is one host's aggregate for one evidence window. +type HostEvidence struct { + AgentID string + Sockets uint64 + BytesAcked uint64 + GoodputBps float64 + RetransmissionRatio float64 + RttP95Ms float64 + ExposedSockets uint64 + CollectionHealthy bool + // UnboundSockets carry this agent ID but no (boot, collection) session + // the agent reported; they are excluded from every other field. + UnboundSockets uint64 +} + +// Evidence is an immutable per-host measurement set for a window. +type Evidence struct { + ID string + AnalyzedAt time.Time + WindowStart time.Time + WindowEnd time.Time + QueryVersion string + EnrichmentVersion string + Hosts []HostEvidence + ArtifactSHA256 string +} + +// Clone copies the host slice so the caller can mutate independently. +func (e *Evidence) Clone() *Evidence { + if e == nil { + return nil + } + c := *e + c.Hosts = slices.Clone(e.Hosts) + return &c +} + +// Equal compares every field and every host in order. +func (e *Evidence) Equal(o *Evidence) bool { + if e == nil || o == nil { + return e == o + } + return e.ID == o.ID && e.AnalyzedAt.Equal(o.AnalyzedAt) && e.WindowStart.Equal(o.WindowStart) && e.WindowEnd.Equal(o.WindowEnd) && e.QueryVersion == o.QueryVersion && e.EnrichmentVersion == o.EnrichmentVersion && e.ArtifactSHA256 == o.ArtifactSHA256 && slices.Equal(e.Hosts, o.Hosts) +} + +// Policy bounds how an experiment is run and judged. +type Policy struct { + MinimumObservation time.Duration + MaximumPhase time.Duration + MaximumEvidenceAge time.Duration + MinimumSocketsPerHost uint64 + MinimumBytesPerHost uint64 + MinimumTreatedHosts uint32 + MinimumImprovement float64 + MaximumRetransmissionIncrease float64 + MaximumRTTIncrease float64 +} + +// Phase is one step of exposure: the first TargetHosts of the cohort order. +type Phase struct { + TargetHosts uint32 + IssuedAt time.Time + ObservationStartedAt time.Time + EvaluatedAt time.Time + Evidence *Evidence + Outcome Outcome + Reviewer string + Reason string +} + +// Experiment is a reviewed, phased rollout of one treatment in one location. +type Experiment struct { + ID string + Location string + Hypothesis string + Treatment Treatment + Policy Policy + Baseline *Evidence + CohortOrder []string + Phases []Phase + Status Status + Revision uint64 + ProposedAt time.Time + LatestEvidence *Evidence + LatestOutcome Outcome + // UpdatedAt is when the controller last changed the experiment. The + // discovery cooldown counts from it for terminal experiments. + UpdatedAt time.Time +} + +// Clone deep-copies the experiment so pure functions can return a new value. +func (e *Experiment) Clone() *Experiment { + if e == nil { + return nil + } + c := *e + c.Baseline = e.Baseline.Clone() + c.LatestEvidence = e.LatestEvidence.Clone() + c.CohortOrder = slices.Clone(e.CohortOrder) + c.Phases = slices.Clone(e.Phases) + for i := range c.Phases { + c.Phases[i].Evidence = e.Phases[i].Evidence.Clone() + } + return &c +} + +// CurrentPhase returns a pointer to the last phase, or nil before review. +func (e *Experiment) CurrentPhase() *Phase { + if len(e.Phases) == 0 { + return nil + } + return &e.Phases[len(e.Phases)-1] +} + +// Target is the number of treated hosts in the current phase, zero before review. +func (e *Experiment) Target() int { + if p := e.CurrentPhase(); p != nil { + return int(p.TargetHosts) + } + return 0 +} diff --git a/pkg/treatment/reconcile/contracts_test.go b/pkg/treatment/reconcile/contracts_test.go new file mode 100644 index 000000000..ffe39b464 --- /dev/null +++ b/pkg/treatment/reconcile/contracts_test.go @@ -0,0 +1,176 @@ +package reconcile + +import ( + "context" + "errors" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +type faultBackend struct { + *fakeBackend + fail string +} + +func (b *faultBackend) BeginReconcile() {} + +func (b *faultBackend) Plan(ctx context.Context, t *treatment.Treatment) ([]byte, error) { + if b.fail == "plan" { + return nil, errors.New("plan failed") + } + return b.fakeBackend.Plan(ctx, t) +} +func (b *faultBackend) Install(ctx context.Context, raw []byte) error { + if b.fail == "install" { + return errors.New("install failed") + } + return b.fakeBackend.Install(ctx, raw) +} +func (b *faultBackend) Enable(ctx context.Context) error { + if b.fail == "enable" { + return errors.New("enable failed") + } + return b.fakeBackend.Enable(ctx) +} + +func TestReconcileFailureRecovery(t *testing.T) { + for _, tc := range []struct { + name, description string + wantRoutes int + }{ + {"plan", "forwarding changes withdraw an existing override", 0}, + {"install", "failed installation cannot enable lookup", 0}, + {"enable", "failed rule installation isolates installed routes", 1}, + } { + t.Run(tc.name, func(t *testing.T) { + now := time.Unix(1700000000, 0) + b := &faultBackend{fakeBackend: &fakeBackend{routes: map[string]bool{}}} + r := newReconciler(t, b, &now) + d := fixtures.Desired(now) + if tc.name == "plan" { + if _, err := r.Run(context.Background(), d, ModeFull); err != nil { + t.Fatal(err) + } + } + b.fail = tc.name + s, err := r.Run(context.Background(), d, ModeFull) + if err == nil || !strings.Contains(err.Error(), tc.name+" failed") || s.Records[0].Status != treatment.ApplyFailed || b.enabled || len(b.routes) != tc.wantRoutes { + t.Fatalf("%s: err=%v enabled=%t routes=%d state=%v", tc.description, err, b.enabled, len(b.routes), s) + } + b.fail = "" + s, err = r.Run(context.Background(), nil, ModeFull) + if err != nil || !b.enabled || len(b.routes) != 1 || s.Records[0].Status != treatment.ApplyVerified { + t.Fatalf("retry did not recover: %v %v", s, err) + } + }) + } +} + +func TestReconcileRevisionContracts(t *testing.T) { + for _, tc := range []struct { + name, description string + change func(*treatment.DesiredState) + mode Mode + wantError string + }{ + {"idempotent", "identical state verifies without reinstall", func(*treatment.DesiredState) {}, ModeFull, ""}, + {"conflict", "same revision cannot carry different contents", func(d *treatment.DesiredState) { d.Suspended = true }, ModeFull, "conflicting"}, + {"wrong-host", "another agent's state is rejected", func(d *treatment.DesiredState) { d.AgentID = "other" }, ModeFull, "another agent"}, + {"watchdog", "watchdog cannot accept controller instructions", func(*treatment.DesiredState) {}, ModeExpiryOnly, "watchdog"}, + {"invalid", "an invalid desired state is rejected before the journal changes", func(d *treatment.DesiredState) { d.Revision = 0 }, ModeFull, "desired-state header"}, + } { + t.Run(tc.name, func(t *testing.T) { + now := time.Unix(1700000000, 0) + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + d := fixtures.Desired(now) + s, err := r.Run(context.Background(), d, ModeFull) + if err != nil { + t.Fatal(err) + } + original := s.Desired.Clone() + tc.change(d) + _, err = r.Run(context.Background(), d, tc.mode) + if tc.wantError == "" { + if err != nil { + t.Fatal(err) + } + } else if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("%s: expected %q got %v", tc.description, tc.wantError, err) + } + if b.installs != 1 { + t.Fatal("rejected/idempotent state reinstalled route") + } + if err = r.Journal.WithLock(context.Background(), func(s *State, _ func() error) error { + if !s.Desired.Equal(original) { + t.Fatal("rejected request changed journal") + } + return nil + }); err != nil { + t.Fatal(err) + } + }) + } +} + +func TestReconcileLeaseBoundary(t *testing.T) { + for _, tc := range []struct { + description string + offset time.Duration + want treatment.ApplyStatus + routes int + }{ + {"one nanosecond before expiry is active", time.Nanosecond, treatment.ApplyVerified, 1}, + {"exact expiry is withdrawn", 0, treatment.ApplyExpired, 0}, + {"one nanosecond after expiry is withdrawn", -time.Nanosecond, treatment.ApplyExpired, 0}, + } { + t.Run(tc.description, func(t *testing.T) { + now := time.Unix(1700000000, 0) + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + d := fixtures.Desired(now) + d.Assignments[0].LeaseExpiresAt = now.Add(tc.offset) + s, err := r.Run(context.Background(), d, ModeFull) + if err != nil || s.Records[0].Status != tc.want || len(b.routes) != tc.routes { + t.Fatalf("got %v %v routes=%d; want %v routes=%d", s, err, len(b.routes), tc.want, tc.routes) + } + record := s.Records[0] + if !record.ReceivedAt.Equal(now) { + t.Fatal("receipt timestamp missing") + } + if tc.routes == 1 && !record.AppliedAt.Equal(now) { + t.Fatal("application timestamp missing") + } + }) + } +} + +// Reports strips the kernel-local fields, which is how the check-in path +// guarantees route bytes never cross the wire. +func TestReportsStripLocalFields(t *testing.T) { + now := time.Unix(1700000000, 0) + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + s, err := r.Run(context.Background(), fixtures.Desired(now), ModeFull) + if err != nil { + t.Fatal(err) + } + if len(s.Records[0].InstalledRoute) == 0 || s.Records[0].InstalledBootID != "boot-1" { + t.Fatal("fixture did not install a route") + } + reports := s.Reports() + if len(reports) != 1 || reports[0].Status != treatment.ApplyVerified || reports[0].Assignment.ExperimentID != "trial-1" { + t.Fatalf("report mismatch: %+v", reports) + } + reports[0].Assignment.Treatment.ID = "mutated" + if s.Records[0].Assignment.Treatment.ID == "mutated" { + t.Fatal("report aliases the snapshot") + } + if (*State)(nil).Reports() != nil || (*State)(nil).Held() || (*State)(nil).Revision() != 0 { + t.Fatal("nil state accessors must be safe") + } +} diff --git a/pkg/treatment/reconcile/journal.go b/pkg/treatment/reconcile/journal.go new file mode 100644 index 000000000..a0deed928 --- /dev/null +++ b/pkg/treatment/reconcile/journal.go @@ -0,0 +1,213 @@ +package reconcile + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "golang.org/x/sys/unix" +) + +// Journal serializes the daemon, watchdog and local administrative commands. +// The single atomic snapshot is authoritative. Per-assignment files are human +// readable projections only, never an input to recovery. +type Journal struct{ Dir string } + +// ErrJournalBusy is returned, wrapping the context's error, when the lock +// was still held by another process or goroutine at the context's deadline. +var ErrJournalBusy = errors.New("treatment journal busy") + +// lockPollMaxCst bounds the retry interval while waiting for the lock. The +// kernel's blocking flock cannot be interrupted by a context, so the wait is +// a non-blocking attempt repeated with a doubling delay from 1 ms to this. +const lockPollMaxCst = 50 * time.Millisecond + +// pendingPrefix names atomicFile's temporary files. One is only ever created +// under the lock, so any found by a new lock holder belongs to a writer that +// died mid-write and is swept before the snapshot is read. +const pendingPrefix = ".pending-" + +// WithLock loads the snapshot under the exclusive journal lock, runs fn with +// a save callback that persists the current state atomically, and refreshes +// the per-assignment projections if anything was saved. A snapshot that +// fails validation never reaches fn. +// +// The lock waits: the daemon's reconcile pass, the watchdog's expiry pass and +// a local suspend/resume each take it in turn rather than one skipping its +// pass because another held it. The wait is bounded by ctx; at its deadline +// WithLock returns ErrJournalBusy wrapping ctx.Err() without having read or +// written anything. `treatmentctl status` reads the snapshot without the lock +// and never waits. +func (j Journal) WithLock(ctx context.Context, fn func(*State, func() error) error) (err error) { + if err = os.MkdirAll(j.Dir, 0700); err != nil { + return err + } + fd, err := unix.Open(filepath.Join(j.Dir, ".lock"), unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC|unix.O_NOFOLLOW, 0600) + if err != nil { + return err + } + defer func() { + if cerr := unix.Close(fd); cerr != nil && err == nil { + err = cerr + } + }() + if err = lock(ctx, fd); err != nil { + return err + } + defer func() { + if uerr := unix.Flock(fd, unix.LOCK_UN); uerr != nil && err == nil { + err = uerr + } + }() + if err = j.sweepPending(); err != nil { + return err + } + s := new(State) + f, err := os.OpenFile(filepath.Join(j.Dir, SnapshotFile), os.O_RDONLY|unix.O_NOFOLLOW, 0) + if err == nil { + b, rerr := readLimited(f) + cerr := f.Close() + if rerr != nil { + return rerr + } + if cerr != nil { + return cerr + } + if s, err = UnmarshalText(b); err != nil { + return err + } + } else if !errors.Is(err, os.ErrNotExist) { + return err + } + dirty := false + save := func() error { + b, err := MarshalText(s) + if err != nil { + return err + } + if len(b) > treatment.MaxStateBytes { + return errors.New("journal exceeds size limit") + } + if err = atomicFile(j.Dir, SnapshotFile, b); err != nil { + return err + } + dirty = true + return nil + } + result := fn(s, save) + if dirty { + for i := range s.Records { + r := &s.Records[i] + b, err := recordText(r) + if err != nil { + return errors.Join(result, err) + } + name := "assignment-" + r.Assignment.ExperimentID + ".textproto" + old, rerr := os.ReadFile(filepath.Join(j.Dir, name)) + if rerr == nil && bytes.Equal(old, b) { + continue + } + if err = atomicFile(j.Dir, name, b); err != nil { + return errors.Join(result, err) + } + } + } + return result +} + +// lock takes the exclusive flock, waiting until ctx is done. +func lock(ctx context.Context, fd int) error { + delay := time.Millisecond + for { + err := unix.Flock(fd, unix.LOCK_EX|unix.LOCK_NB) + if err == nil { + return nil + } + if !errors.Is(err, unix.EWOULDBLOCK) { + return err + } + timer := time.NewTimer(delay) + select { + case <-ctx.Done(): + timer.Stop() + return fmt.Errorf("%w: %w", ErrJournalBusy, ctx.Err()) + case <-timer.C: + } + delay = min(2*delay, lockPollMaxCst) + } +} + +// sweepPending removes temporary files left by a writer that died between +// CreateTemp and Rename. The caller holds the lock, so none is in use. +func (j Journal) sweepPending() error { + entries, err := os.ReadDir(j.Dir) + if err != nil { + return err + } + for _, e := range entries { + if !strings.HasPrefix(e.Name(), pendingPrefix) { + continue + } + if err = os.Remove(filepath.Join(j.Dir, e.Name())); err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } + } + return nil +} + +func readLimited(f *os.File) ([]byte, error) { + b, err := io.ReadAll(io.LimitReader(f, treatment.MaxStateBytes+1)) + if err != nil { + return nil, err + } + if len(b) > treatment.MaxStateBytes { + return nil, errors.New("journal too large") + } + return b, nil +} + +// atomicFile writes b to a temporary file in dir, syncs it, renames it over +// name and syncs the directory. On failure the temporary file is removed; a +// crash before that point leaves one for sweepPending. +func atomicFile(dir, name string, b []byte) (err error) { + f, err := os.CreateTemp(dir, pendingPrefix) + if err != nil { + return err + } + tmp := f.Name() + defer func() { + if err == nil { + return + } + if rerr := os.Remove(tmp); rerr != nil && !errors.Is(rerr, os.ErrNotExist) { + err = errors.Join(err, rerr) + } + }() + if _, err = f.Write(b); err != nil { + return errors.Join(err, f.Close()) + } + if err = f.Sync(); err != nil { + return errors.Join(err, f.Close()) + } + if err = f.Close(); err != nil { + return err + } + if err = os.Rename(tmp, filepath.Join(dir, name)); err != nil { + return err + } + d, err := os.Open(dir) + if err != nil { + return err + } + if err = d.Sync(); err != nil { + return errors.Join(err, d.Close()) + } + return d.Close() +} diff --git a/pkg/treatment/reconcile/journal_test.go b/pkg/treatment/reconcile/journal_test.go new file mode 100644 index 000000000..964f4a338 --- /dev/null +++ b/pkg/treatment/reconcile/journal_test.go @@ -0,0 +1,345 @@ +package reconcile + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" + + jpb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment_journal" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// legacySnapshot is the pre-journal-package format: prototext of the RPC +// LocalState message. It must fail closed, never half-load. +const legacySnapshot = `desired: { + agent_id: "host-1" + revision: 1 + issued_at: { seconds: 1700000000 } +} +records: { + assignment: { experiment_id: "trial-1" } +} +` + +func TestJournalRejectsInvalidSnapshots(t *testing.T) { + for _, tc := range []struct { + name, description string + change func(*jpb.Journal) + raw string + want string + }{ + {"valid", "positive: valid snapshot can be reopened", func(*jpb.Journal) {}, "", ""}, + {"bad-desired", "negative: invalid desired state is not recovered", func(j *jpb.Journal) { j.Desired.Revision = 0 }, "", "invalid persisted"}, + {"missing-assignment", "negative: records require an assignment", func(j *jpb.Journal) { j.Records[0].Assignment = nil }, "", "missing assignment"}, + {"bad-id", "negative: projection names cannot contain paths", func(j *jpb.Journal) { j.Records[0].Assignment.ExperimentId = "../escape"; j.Desired = nil }, "", "invalid journal record"}, + {"duplicate", "negative: duplicate records cannot shadow each other", func(j *jpb.Journal) { j.Records = append(j.Records, j.Records[0]) }, "", "duplicate"}, + {"bad-treatment", "negative: invalid treatment cannot be recovered", func(j *jpb.Journal) { j.Records[0].Assignment.Treatment = nil; j.Desired = nil }, "", "invalid journal treatment"}, + {"unknown-mode", "negative: a mode from a newer writer is refused, not zeroed", func(j *jpb.Journal) { j.Records[0].Assignment.Mode = 99; j.Desired = nil }, "", "unknown assignment mode"}, + {"unknown-status", "negative: an apply status from a newer writer is refused", func(j *jpb.Journal) { j.Records[0].Status = 42 }, "", "unknown apply status"}, + {"bad-timestamp", "negative: an out-of-range timestamp is a parse error", func(j *jpb.Journal) { j.UpdatedAt = ×tamppb.Timestamp{Seconds: 1 << 60} }, "", "updated_at"}, + {"bad-identity", "negative: a path-like agent id in the header is refused", func(j *jpb.Journal) { j.AgentId = "../x" }, "", "invalid journal identity"}, + {"bad-collection", "negative: a collection nonce that is not 32 hex digits is refused before it is stamped", func(j *jpb.Journal) { j.CollectionId = "x'" }, "", "invalid journal identity"}, + {"no-collection", "boundary: a journal written before the agent owned a nonce still opens", func(j *jpb.Journal) { j.CollectionId = "" }, "", ""}, + {"legacy-format", "corner: the pre-journal-package LocalState text fails closed", nil, legacySnapshot, "invalid treatment journal"}, + {"garbage", "corner: non-prototext bytes fail closed", nil, "\x00\x01 not text", "invalid treatment journal"}, + } { + t.Run(tc.name, func(t *testing.T) { + j := Journal{Dir: t.TempDir()} + raw := []byte(tc.raw) + if tc.change != nil { + d := fixtures.Desired(time.Unix(1700000000, 0)) + s := &State{AgentID: "host-1", Location: "dc1", BootID: "boot-1", Desired: d, Records: []Record{{ApplicationRecord: treatment.ApplicationRecord{Assignment: d.Assignments[0]}}}} + p := toJournal(s) + tc.change(p) + var err error + if raw, err = prototext.Marshal(p); err != nil { + t.Fatal(err) + } + } + if err := os.WriteFile(filepath.Join(j.Dir, SnapshotFile), raw, 0600); err != nil { + t.Fatal(err) + } + called := false + err := j.WithLock(context.Background(), func(*State, func() error) error { called = true; return nil }) + if tc.want == "" { + if err != nil || !called { + t.Fatalf("%s: %v", tc.description, err) + } + return + } + if err == nil || !strings.Contains(err.Error(), tc.want) || called { + t.Fatalf("%s: got %v, callback=%t; want %q without callback", tc.description, err, called, tc.want) + } + if _, rerr := ReadSnapshot(j.Dir); rerr == nil || !strings.Contains(rerr.Error(), tc.want) { + t.Fatalf("%s: lock-free read disagrees: %v", tc.description, rerr) + } + }) + } +} + +// TestJournalLockWaits is the lock's contract: a free lock is taken at once, +// a held one is waited for, and the wait ends at the context's deadline with +// ErrJournalBusy and nothing read or written. +func TestJournalLockWaits(t *testing.T) { + for _, tc := range []struct { + name, description string + hold time.Duration // how long a competing holder keeps the lock; 0 is none + timeout time.Duration + wantBusy bool + }{ + {"uncontended", "positive: a free lock runs the callback immediately", 0, time.Second, false}, + {"contended-waits", "positive: a lock held 100 ms is waited for within a 1 s budget, then the callback runs", 100 * time.Millisecond, 5 * time.Second, false}, + {"ctx-deadline", "negative: a lock held past a 150 ms budget returns ErrJournalBusy wrapping the deadline, callback never called", 400 * time.Millisecond, 150 * time.Millisecond, true}, + {"zero-budget", "boundary: an already expired context fails busy without touching the journal when the lock is held", 400 * time.Millisecond, 0, true}, + } { + t.Run(tc.name, func(t *testing.T) { + j := Journal{Dir: t.TempDir()} + if err := j.WithLock(context.Background(), func(s *State, save func() error) error { + s.SuspensionReason = "first writer" + return save() + }); err != nil { + t.Fatal(err) + } + held, released := make(chan struct{}), make(chan struct{}) + if tc.hold > 0 { + go func() { + defer close(released) + _ = j.WithLock(context.Background(), func(*State, func() error) error { + close(held) + time.Sleep(tc.hold) + return nil + }) + }() + <-held + } else { + close(released) + } + ctx, cancel := context.WithTimeout(context.Background(), tc.timeout) + defer cancel() + called := false + start := time.Now() + err := j.WithLock(ctx, func(s *State, save func() error) error { + called = true + s.SuspensionReason = "second writer" + return save() + }) + waited := time.Since(start) + <-released + if tc.wantBusy { + if !errors.Is(err, ErrJournalBusy) || !errors.Is(err, context.DeadlineExceeded) || called { + t.Fatalf("%s: err=%v called=%t", tc.description, err, called) + } + } else if err != nil || !called { + t.Fatalf("%s: err=%v called=%t", tc.description, err, called) + } + if tc.hold > 0 && !tc.wantBusy && waited < tc.hold/2 { + t.Fatalf("%s: ran after %v without waiting for the holder", tc.description, waited) + } + want := "second writer" + if tc.wantBusy { + want = "first writer" + } + s, err := ReadSnapshot(j.Dir) + if err != nil || s.SuspensionReason != want { + t.Fatalf("%s: snapshot %+v err=%v, want reason %q", tc.description, s, err, want) + } + }) + } +} + +// The lock-free reader sees the committed snapshot while the lock is held: +// `treatmentctl status` never waits. +func TestJournalLockFreeReadUnderLock(t *testing.T) { + j := Journal{Dir: t.TempDir()} + if err := j.WithLock(context.Background(), func(s *State, save func() error) error { + s.SuspensionReason = "committed" + return save() + }); err != nil { + t.Fatal(err) + } + hold, held, released := make(chan struct{}), make(chan struct{}), make(chan struct{}) + go func() { + defer close(released) + _ = j.WithLock(context.Background(), func(s *State, save func() error) error { + close(held) + <-hold + return nil + }) + }() + <-held + s, err := ReadSnapshot(j.Dir) + close(hold) + <-released + if err != nil || s.SuspensionReason != "committed" { + t.Fatalf("lock-free read under lock: %v %+v", err, s) + } +} + +// TestJournalLockHolderDies kills a process holding the lock mid-write: the +// kernel drops its flock, the next holder acquires at once and sweeps the +// temporary file the dead writer left, and the committed snapshot is intact. +func TestJournalLockHolderDies(t *testing.T) { + dir := t.TempDir() + j := Journal{Dir: dir} + if err := j.WithLock(context.Background(), func(s *State, save func() error) error { + s.SuspensionReason = "committed" + return save() + }); err != nil { + t.Fatal(err) + } + // /proc/self/exe re-executes this test binary. + cmd := exec.Command("/proc/self/exe", "-test.run=^TestJournalLockHolderHelper$") + cmd.Env = append(os.Environ(), "XTCP_JOURNAL_HOLD_DIR="+dir) + out, err := cmd.StdoutPipe() + if err != nil { + t.Fatal(err) + } + if err = cmd.Start(); err != nil { + t.Fatal(err) + } + line := make([]byte, 5) + if _, err = io.ReadFull(out, line); err != nil || string(line) != "held\n" { + _ = cmd.Process.Kill() + t.Fatalf("holder did not report the lock: %q %v", line, err) + } + // While the child holds the lock, a short wait fails busy. + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + err = j.WithLock(ctx, func(*State, func() error) error { t.Fatal("entered under a live holder"); return nil }) + cancel() + if !errors.Is(err, ErrJournalBusy) { + t.Fatalf("live holder: %v", err) + } + if err = cmd.Process.Kill(); err != nil { + t.Fatal(err) + } + _ = cmd.Wait() + ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + if err = j.WithLock(ctx, func(s *State, save func() error) error { + if s.SuspensionReason != "committed" { + t.Fatalf("dead writer corrupted the snapshot: %+v", s) + } + return nil + }); err != nil { + t.Fatalf("lock not released by the dead holder: %v", err) + } + entries, err := os.ReadDir(dir) + if err != nil { + t.Fatal(err) + } + for _, e := range entries { + if strings.HasPrefix(e.Name(), pendingPrefix) { + t.Fatalf("dead writer's temporary file survived: %s", e.Name()) + } + } +} + +// TestJournalLockHolderHelper is the child of TestJournalLockHolderDies. It +// takes the lock, leaves a half-written temporary file as a dying writer +// would, reports, and blocks until killed. +func TestJournalLockHolderHelper(t *testing.T) { + dir := os.Getenv("XTCP_JOURNAL_HOLD_DIR") + if dir == "" { + t.Skip("helper for TestJournalLockHolderDies") + } + err := Journal{Dir: dir}.WithLock(context.Background(), func(*State, func() error) error { + f, err := os.CreateTemp(dir, pendingPrefix) + if err != nil { + return err + } + if _, err = f.WriteString("partial"); err != nil { + return err + } + if err = f.Close(); err != nil { + return err + } + fmt.Println("held") + select {} + }) + t.Fatal(err) +} + +func TestJournalSymlinkProtection(t *testing.T) { + for _, name := range []string{".lock", SnapshotFile} { + t.Run(name, func(t *testing.T) { + dir := t.TempDir() + target := filepath.Join(t.TempDir(), "unrelated") + if err := os.WriteFile(target, []byte("sentinel"), 0600); err != nil { + t.Fatal(err) + } + if err := os.Symlink(target, filepath.Join(dir, name)); err != nil { + t.Fatal(err) + } + called := false + err := (Journal{Dir: dir}).WithLock(context.Background(), func(*State, func() error) error { called = true; return nil }) + if err == nil || called { + t.Fatal("followed journal symlink") + } + if name == SnapshotFile { + if _, err = ReadSnapshot(dir); err == nil { + t.Fatal("lock-free reader followed symlink") + } + } + raw, err := os.ReadFile(target) + if err != nil || string(raw) != "sentinel" { + t.Fatal("modified symlink target") + } + }) + } +} + +func TestJournalSizeLimit(t *testing.T) { + dir := t.TempDir() + f, err := os.Create(filepath.Join(dir, SnapshotFile)) + if err != nil { + t.Fatal(err) + } + if err = f.Truncate(treatment.MaxStateBytes + 1); err != nil { + t.Fatal(err) + } + if err = f.Close(); err != nil { + t.Fatal(err) + } + err = (Journal{Dir: dir}).WithLock(context.Background(), func(*State, func() error) error { t.Fatal("oversized snapshot reached callback"); return nil }) + if err == nil || !strings.Contains(err.Error(), "too large") { + t.Fatalf("want size limit, got %v", err) + } + if _, err = ReadSnapshot(dir); err == nil || !strings.Contains(err.Error(), "too large") { + t.Fatalf("lock-free reader ignored size limit: %v", err) + } +} + +func TestJournalProjectionsFollowSnapshot(t *testing.T) { + j := Journal{Dir: t.TempDir()} + d := fixtures.Desired(time.Unix(1700000000, 0)) + err := j.WithLock(context.Background(), func(s *State, save func() error) error { + s.AgentID = "host-1" + s.Desired = d + s.Records = []Record{{ApplicationRecord: treatment.ApplicationRecord{Assignment: d.Assignments[0], Status: treatment.ApplyPending}, InstalledRoute: []byte{1, 2, 3}, InstalledBootID: "boot-1"}} + return save() + }) + if err != nil { + t.Fatal(err) + } + raw, err := os.ReadFile(filepath.Join(j.Dir, "assignment-trial-1.textproto")) + if err != nil { + t.Fatal(err) + } + var p jpb.Record + if err = prototext.Unmarshal(raw, &p); err != nil || p.Assignment.ExperimentId != "trial-1" || string(p.InstalledRoute) != "\x01\x02\x03" || p.InstalledBootId != "boot-1" { + t.Fatalf("projection does not mirror the record: %v %+v", err, &p) + } + if _, err = os.Lstat(filepath.Join(j.Dir, ".pending-")); !errors.Is(err, os.ErrNotExist) { + t.Fatal("temp file left behind") + } +} diff --git a/pkg/treatment/reconcile/journalpb.go b/pkg/treatment/reconcile/journalpb.go new file mode 100644 index 000000000..13f9e9f3c --- /dev/null +++ b/pkg/treatment/reconcile/journalpb.go @@ -0,0 +1,276 @@ +package reconcile + +import ( + "errors" + "fmt" + "net/netip" + "os" + "path/filepath" + "time" + + jpb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment_journal" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "golang.org/x/sys/unix" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// The journal file format is xtcp_treatment_journal.v1.Journal in prototext. +// It is converted to and from State here, and every load runs the domain +// validators so a hand-edited or truncated file fails closed before any +// kernel mutation. + +// SnapshotFile is the journal snapshot's name inside Journal.Dir. +const SnapshotFile = "state.textproto" + +var textOptions = prototext.MarshalOptions{Multiline: true, Indent: " "} + +func stamp(t time.Time) *timestamppb.Timestamp { + if t.IsZero() { + return nil + } + return timestamppb.New(t) +} + +func parseStamp(field string, t *timestamppb.Timestamp) (time.Time, error) { + if t == nil { + return time.Time{}, nil + } + if err := t.CheckValid(); err != nil { + return time.Time{}, fmt.Errorf("%s: %w", field, err) + } + return t.AsTime(), nil +} + +func clonePtr[T any](p *T) *T { + if p == nil { + return nil + } + v := *p + return &v +} + +func settingsToJournal(s treatment.TCPSettings) *jpb.TCPSettings { + return &jpb.TCPSettings{CongestionControl: clonePtr(s.CongestionControl), CongestionLock: s.CongestionLock, RtoMinMs: clonePtr(s.RTOMinMs), InitialCongestionWindow: clonePtr(s.InitialCongestionWindow), InitialReceiveWindow: clonePtr(s.InitialReceiveWindow), QuickAck: clonePtr(s.QuickAck), Ecn: clonePtr(s.ECN)} +} + +func settingsFromJournal(p *jpb.TCPSettings) treatment.TCPSettings { + if p == nil { + return treatment.TCPSettings{} + } + return treatment.TCPSettings{CongestionControl: clonePtr(p.CongestionControl), CongestionLock: p.CongestionLock, RTOMinMs: clonePtr(p.RtoMinMs), InitialCongestionWindow: clonePtr(p.InitialCongestionWindow), InitialReceiveWindow: clonePtr(p.InitialReceiveWindow), QuickAck: clonePtr(p.QuickAck), ECN: clonePtr(p.Ecn)} +} + +func treatmentToJournal(t *treatment.Treatment) *jpb.Treatment { + if t == nil { + return nil + } + out := &jpb.Treatment{Id: t.ID, Revision: t.Revision, Settings: settingsToJournal(t.Settings), EcnFabricVerified: t.ECNFabricVerified} + if t.Destination.IsValid() { + out.Destination = t.Destination.String() + } + return out +} + +func treatmentFromJournal(p *jpb.Treatment) treatment.Treatment { + if p == nil { + return treatment.Treatment{} + } + t := treatment.Treatment{ID: p.Id, Revision: p.Revision, Settings: settingsFromJournal(p.Settings), ECNFabricVerified: p.EcnFabricVerified} + if d, err := netip.ParsePrefix(p.Destination); err == nil { + t.Destination = d + } + return t +} + +func assignmentToJournal(a *treatment.Assignment) *jpb.Assignment { + return &jpb.Assignment{ExperimentId: a.ExperimentID, Treatment: treatmentToJournal(&a.Treatment), Mode: jpb.AssignmentMode(a.Mode), LeaseExpiresAt: stamp(a.LeaseExpiresAt), Predecessor: treatmentToJournal(a.Predecessor), Generation: a.Generation} +} + +func assignmentFromJournal(p *jpb.Assignment) (treatment.Assignment, error) { + if p == nil { + return treatment.Assignment{}, errors.New("missing assignment") + } + mode := treatment.AssignmentMode(p.Mode) + if _, ok := jpb.AssignmentMode_name[int32(p.Mode)]; !ok || !mode.Valid() { + return treatment.Assignment{}, fmt.Errorf("unknown assignment mode %d", p.Mode) + } + lease, err := parseStamp("lease_expires_at", p.LeaseExpiresAt) + if err != nil { + return treatment.Assignment{}, err + } + a := treatment.Assignment{ExperimentID: p.ExperimentId, Treatment: treatmentFromJournal(p.Treatment), Mode: mode, LeaseExpiresAt: lease, Generation: p.Generation} + if p.Predecessor != nil { + pred := treatmentFromJournal(p.Predecessor) + a.Predecessor = &pred + } + return a, nil +} + +func desiredToJournal(d *treatment.DesiredState) *jpb.Desired { + if d == nil { + return nil + } + out := &jpb.Desired{Revision: d.Revision, Suspended: d.Suspended, IssuedAt: stamp(d.IssuedAt)} + for i := range d.Assignments { + out.Assignments = append(out.Assignments, assignmentToJournal(&d.Assignments[i])) + } + return out +} + +func desiredFromJournal(agentID string, p *jpb.Desired) (*treatment.DesiredState, error) { + if p == nil { + return nil, nil + } + issued, err := parseStamp("issued_at", p.IssuedAt) + if err != nil { + return nil, err + } + d := &treatment.DesiredState{AgentID: agentID, Revision: p.Revision, Suspended: p.Suspended, IssuedAt: issued} + for _, a := range p.Assignments { + v, err := assignmentFromJournal(a) + if err != nil { + return nil, err + } + d.Assignments = append(d.Assignments, v) + } + return d, nil +} + +func recordToJournal(r *Record) *jpb.Record { + return &jpb.Record{Assignment: assignmentToJournal(&r.Assignment), DesiredRevision: r.DesiredRevision, Status: jpb.ApplyStatus(r.Status), ReceivedAt: stamp(r.ReceivedAt), AttemptedAt: stamp(r.AttemptedAt), AppliedAt: stamp(r.AppliedAt), VerifiedAt: stamp(r.VerifiedAt), RemovedAt: stamp(r.RemovedAt), Error: r.Error, InstalledRoute: append([]byte(nil), r.InstalledRoute...), InstalledBootId: r.InstalledBootID, ExpiredLatched: r.ExpiredLatched} +} + +func recordFromJournal(p *jpb.Record) (Record, error) { + if p == nil { + return Record{}, errors.New("missing record") + } + a, err := assignmentFromJournal(p.Assignment) + if err != nil { + return Record{}, err + } + status := treatment.ApplyStatus(p.Status) + if _, ok := jpb.ApplyStatus_name[int32(p.Status)]; !ok || !status.Valid() { + return Record{}, fmt.Errorf("unknown apply status %d", p.Status) + } + r := Record{ApplicationRecord: treatment.ApplicationRecord{Assignment: a, DesiredRevision: p.DesiredRevision, Status: status, Error: p.Error, ExpiredLatched: p.ExpiredLatched}, InstalledBootID: p.InstalledBootId} + if len(p.InstalledRoute) > 0 { + r.InstalledRoute = append([]byte(nil), p.InstalledRoute...) + } + for _, f := range []struct { + name string + src *timestamppb.Timestamp + dst *time.Time + }{{"received_at", p.ReceivedAt, &r.ReceivedAt}, {"attempted_at", p.AttemptedAt, &r.AttemptedAt}, {"applied_at", p.AppliedAt, &r.AppliedAt}, {"verified_at", p.VerifiedAt, &r.VerifiedAt}, {"removed_at", p.RemovedAt, &r.RemovedAt}} { + if *f.dst, err = parseStamp(f.name, f.src); err != nil { + return Record{}, err + } + } + return r, nil +} + +func toJournal(s *State) *jpb.Journal { + out := &jpb.Journal{AgentId: s.AgentID, Location: s.Location, BootId: s.BootID, CollectionId: s.CollectionID, Desired: desiredToJournal(s.Desired), LocallySuspended: s.LocallySuspended, SuspensionReason: s.SuspensionReason, UpdatedAt: stamp(s.UpdatedAt)} + for i := range s.Records { + out.Records = append(out.Records, recordToJournal(&s.Records[i])) + } + return out +} + +func fromJournal(p *jpb.Journal) (*State, error) { + s := &State{AgentID: p.AgentId, Location: p.Location, BootID: p.BootId, CollectionID: p.CollectionId, LocallySuspended: p.LocallySuspended, SuspensionReason: p.SuspensionReason} + var err error + if s.Desired, err = desiredFromJournal(p.AgentId, p.Desired); err != nil { + return nil, err + } + if s.UpdatedAt, err = parseStamp("updated_at", p.UpdatedAt); err != nil { + return nil, err + } + for _, r := range p.Records { + v, err := recordFromJournal(r) + if err != nil { + return nil, err + } + s.Records = append(s.Records, v) + } + return s, nil +} + +// validate is the fail-closed gate every loaded journal passes through. +func validate(s *State) error { + if s.AgentID != "" && !treatment.ValidID(s.AgentID) || s.Location != "" && !treatment.ValidID(s.Location) || s.CollectionID != "" && !treatment.ValidCollectionID(s.CollectionID) { + return errors.New("invalid journal identity") + } + if s.Desired != nil { + if err := treatment.ValidateDesired(s.Desired); err != nil { + return fmt.Errorf("invalid persisted desired state: %w", err) + } + } + if len(s.Records) > treatment.MaxAssignments*2 { + return errors.New("too many journal records") + } + seen := map[string]bool{} + for i := range s.Records { + r := &s.Records[i] + if !treatment.ValidID(r.Assignment.ExperimentID) { + return errors.New("invalid journal record") + } + if seen[r.Assignment.ExperimentID] { + return errors.New("duplicate journal record") + } + seen[r.Assignment.ExperimentID] = true + if err := treatment.ValidateTreatment(&r.Assignment.Treatment); err != nil { + return fmt.Errorf("invalid journal treatment: %w", err) + } + } + return nil +} + +// MarshalText renders the snapshot in the journal file format. +func MarshalText(s *State) ([]byte, error) { + if s == nil { + return nil, errors.New("nil state") + } + return textOptions.Marshal(toJournal(s)) +} + +// UnmarshalText parses and validates a journal snapshot. +func UnmarshalText(b []byte) (*State, error) { + if len(b) > treatment.MaxStateBytes { + return nil, errors.New("journal too large") + } + p := new(jpb.Journal) + if err := prototext.Unmarshal(b, p); err != nil { + return nil, fmt.Errorf("invalid treatment journal: %w", err) + } + s, err := fromJournal(p) + if err != nil { + return nil, fmt.Errorf("invalid treatment journal: %w", err) + } + if err = validate(s); err != nil { + return nil, err + } + return s, nil +} + +// recordText renders one record for its human-readable projection file. +func recordText(r *Record) ([]byte, error) { + return textOptions.Marshal(recordToJournal(r)) +} + +// ReadSnapshot loads the snapshot without taking the journal lock. The file +// is replaced atomically, so a reader always sees a complete snapshot; this +// is the path for status display and telemetry attribution, never for +// mutation. A missing snapshot is os.ErrNotExist. +func ReadSnapshot(dir string) (*State, error) { + f, err := os.OpenFile(filepath.Join(dir, SnapshotFile), os.O_RDONLY|unix.O_NOFOLLOW, 0) + if err != nil { + return nil, err + } + defer f.Close() + b, err := readLimited(f) + if err != nil { + return nil, err + } + return UnmarshalText(b) +} diff --git a/pkg/treatment/reconcile/journalpb_test.go b/pkg/treatment/reconcile/journalpb_test.go new file mode 100644 index 000000000..bd3d2f8b9 --- /dev/null +++ b/pkg/treatment/reconcile/journalpb_test.go @@ -0,0 +1,164 @@ +package reconcile + +import ( + "net/netip" + "reflect" + "strconv" + "strings" + "testing" + "time" + + jpb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment_journal" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "google.golang.org/protobuf/proto" +) + +func populatedState(now time.Time) *State { + d := fixtures.Desired(now) + pred := d.Assignments[0].Treatment + pred.ID = "old" + pred.Settings = treatment.TCPSettings{CongestionControl: ptr("bbr"), CongestionLock: true, RTOMinMs: ptr[uint32](20), InitialCongestionWindow: ptr[uint32](10), InitialReceiveWindow: ptr[uint32](2), QuickAck: ptr(false), ECN: ptr(true)} + d.Assignments[0].Predecessor = &pred + d.Assignments = append(d.Assignments, treatment.Assignment{ExperimentID: "stable-6", Generation: 2, Mode: treatment.ModeStable, Treatment: treatment.Treatment{ID: "v6", Revision: 3, Destination: netip.MustParsePrefix("2001:db8::1/128"), Settings: treatment.TCPSettings{QuickAck: ptr(true)}}}) + return &State{ + AgentID: "host-1", Location: "dc1", BootID: "boot-1", CollectionID: fixtures.CollectionID, Desired: d, LocallySuspended: true, SuspensionReason: "incident 7", UpdatedAt: now, + Records: []Record{ + {ApplicationRecord: treatment.ApplicationRecord{Assignment: d.Assignments[0], DesiredRevision: 1, Status: treatment.ApplyVerified, ReceivedAt: now, AttemptedAt: now.Add(time.Second), AppliedAt: now.Add(2 * time.Second), VerifiedAt: now.Add(3 * time.Second)}, InstalledRoute: []byte{0x18, 0, 0, 0, 1, 2, 3}, InstalledBootID: "boot-1"}, + {ApplicationRecord: treatment.ApplicationRecord{Assignment: d.Assignments[1], DesiredRevision: 1, Status: treatment.ApplyPending, ReceivedAt: now}}, + {ApplicationRecord: treatment.ApplicationRecord{Assignment: treatment.Assignment{ExperimentID: "gone", Generation: 3, Mode: treatment.ModeRetired, Treatment: fixtures.Treatment()}, Status: treatment.ApplyRemoved, RemovedAt: now, Error: "x", ExpiredLatched: true}}, + }, + } +} + +// TestJournalRoundTrip converts State -> journal text -> State and requires +// deep equality, and journal -> State -> journal and requires proto equality, +// so neither direction drops, smears or aliases a field. +func TestJournalRoundTrip(t *testing.T) { + now := time.Unix(1700000000, 123456789).UTC() + for _, tc := range []struct { + name, description string + state *State + }{ + {"populated", "positive: header, hold, predecessor, v4 and v6 destinations, installed route bytes and every timestamp survive", populatedState(now)}, + {"unset-optional", "boundary: a stable assignment without lease, predecessor or optional settings stays unset", func() *State { + d := fixtures.Desired(now) + d.Assignments[0].Mode = treatment.ModeStable + d.Assignments[0].LeaseExpiresAt = time.Time{} + return &State{AgentID: "host-1", Desired: d} + }()}, + {"empty", "boundary: a journal with no desired state and no records is the zero State", &State{}}, + {"tombstone-only", "corner: records without desired state (after a controller reset) survive", &State{AgentID: "host-1", Records: []Record{{ApplicationRecord: treatment.ApplicationRecord{Assignment: fixtures.Desired(now).Assignments[0], Status: treatment.ApplyRemoved, RemovedAt: now}}}}}, + } { + t.Run(tc.name, func(t *testing.T) { + b, err := MarshalText(tc.state) + if err != nil { + t.Fatal(err) + } + out, err := UnmarshalText(b) + if err != nil || !reflect.DeepEqual(tc.state, out) { + t.Fatalf("%s: %v\nin %+v\nout %+v", tc.description, err, tc.state, out) + } + again, err := MarshalText(out) + if err != nil || string(again) != string(b) { + t.Fatalf("%s: text differs after a second trip: %v", tc.description, err) + } + if !proto.Equal(toJournal(tc.state), toJournal(out)) { + t.Fatalf("%s: journal messages differ", tc.description) + } + if tc.state.Records != nil { + clone := out.Clone() + clone.Records[0].Assignment.Treatment.ID = "mutated" + if len(clone.Records[0].InstalledRoute) > 0 { + clone.Records[0].InstalledRoute[0] = 0xff + } + if out.Records[0].Assignment.Treatment.ID == "mutated" || len(out.Records[0].InstalledRoute) > 0 && out.Records[0].InstalledRoute[0] == 0xff { + t.Fatal("Clone aliases the original") + } + } + }) + } +} + +func TestJournalEnumsMirrorDomain(t *testing.T) { + _, modes, applies, _ := treatment.EnumCounts() + for _, tc := range []struct { + description string + journal map[int32]string + prefix string + domain int + name func(int32) string + }{ + {"assignment modes", jpb.AssignmentMode_name, "ASSIGNMENT_MODE_", modes, func(i int32) string { return treatment.AssignmentMode(i).String() }}, + {"apply statuses", jpb.ApplyStatus_name, "APPLY_STATUS_", applies, func(i int32) string { return treatment.ApplyStatus(i).String() }}, + } { + if len(tc.journal) != tc.domain { + t.Errorf("%s: journal defines %d values, domain defines %d", tc.description, len(tc.journal), tc.domain) + } + for i, name := range tc.journal { + want := strings.ToLower(strings.TrimPrefix(name, tc.prefix)) + if got := tc.name(i); got != want { + t.Errorf("%s %d: domain name %q, journal %q", tc.description, i, got, name) + } + } + } +} + +func TestUnmarshalTextLimits(t *testing.T) { + now := time.Unix(1700000000, 0).UTC() + for _, tc := range []struct { + name, description string + build func() []byte + expected string + }{ + {"max-records", "boundary: twice MaxAssignments records load", func() []byte { + s := &State{AgentID: "host-1"} + for i := range treatment.MaxAssignments * 2 { + tr := fixtures.Treatment() + tr.Destination = netip.PrefixFrom(netip.AddrFrom4([4]byte{192, 0, byte(i >> 8), byte(i)}), 32) + s.Records = append(s.Records, Record{ApplicationRecord: treatment.ApplicationRecord{Assignment: treatment.Assignment{ExperimentID: "e" + strconv.Itoa(i), Generation: 1, Mode: treatment.ModeStable, Treatment: tr}}}) + } + b, _ := MarshalText(s) + return b + }, ""}, + {"too-many-records", "boundary: one record over the cap is refused", func() []byte { + s := &State{AgentID: "host-1"} + for i := range treatment.MaxAssignments*2 + 1 { + tr := fixtures.Treatment() + tr.Destination = netip.PrefixFrom(netip.AddrFrom4([4]byte{10, byte(i >> 16), byte(i >> 8), byte(i)}), 32) + s.Records = append(s.Records, Record{ApplicationRecord: treatment.ApplicationRecord{Assignment: treatment.Assignment{ExperimentID: "e" + strconv.Itoa(i), Generation: 1, Mode: treatment.ModeStable, Treatment: tr}}}) + } + b, _ := MarshalText(s) + return b + }, "too many journal records"}, + {"oversized", "boundary: a byte over MaxStateBytes is refused before parsing", func() []byte { return make([]byte, treatment.MaxStateBytes+1) }, "too large"}, + {"bad-destination", "negative: an unparsable destination fails treatment validation, not decoding", func() []byte { + p := toJournal(&State{AgentID: "host-1", Records: []Record{{ApplicationRecord: treatment.ApplicationRecord{Assignment: fixtures.Desired(now).Assignments[0]}}}}) + p.Records[0].Assignment.Treatment.Destination = "nonsense" + b, _ := textOptions.Marshal(p) + return b + }, "invalid journal treatment"}, + {"bad-lease", "negative: an invalid lease timestamp names the field", func() []byte { + p := toJournal(&State{AgentID: "host-1", Desired: fixtures.Desired(now)}) + p.Desired.Assignments[0].LeaseExpiresAt.Nanos = -1 + b, _ := textOptions.Marshal(p) + return b + }, "lease_expires_at"}, + } { + t.Run(tc.name, func(t *testing.T) { + _, err := UnmarshalText(tc.build()) + if tc.expected == "" { + if err != nil { + t.Fatalf("%s: %v", tc.description, err) + } + return + } + if err == nil || !strings.Contains(err.Error(), tc.expected) { + t.Fatalf("%s: expected %q, got %v", tc.description, tc.expected, err) + } + }) + } + if _, err := MarshalText(nil); err == nil { + t.Fatal("nil state marshaled") + } +} diff --git a/pkg/treatment/reconcile/reconcile.go b/pkg/treatment/reconcile/reconcile.go new file mode 100644 index 000000000..58d418a60 --- /dev/null +++ b/pkg/treatment/reconcile/reconcile.go @@ -0,0 +1,401 @@ +// Package reconcile owns the host-side half of the treatment contract: the +// intent journal and the reconciler that drives a Backend from it. It is +// shared by the in-daemon/standalone agent and by the independent watchdog; +// it never speaks gRPC, never imports the RPC proto and never imports the +// controller. The journal file format is its own proto package +// (xtcp_treatment_journal.v1) converted to and from the domain types. +package reconcile + +import ( + "bytes" + "context" + "errors" + "fmt" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +// Mode selects how much a reconciliation pass may do. +type Mode uint8 + +const ( + // ModeFull installs, verifies, removes and toggles owned rules. Used by + // the agent and by the local reconcile command. + ModeFull Mode = iota + // ModeExpiryOnly may only withdraw: expired trials, suspended or retired + // assignments and tombstones. It cannot accept desired state, install a + // new treatment or clear a suspension. Used by the independent watchdog. + ModeExpiryOnly +) + +func (m Mode) String() string { + switch m { + case ModeFull: + return "full" + case ModeExpiryOnly: + return "expiry-only" + } + return "unknown" +} + +// Backend only accepts locally planned routes. Install must be create-exclusive +// or an idempotent match; Remove must refuse changed/foreign routes. Enable and +// Disable only touch the deployment's exact owned lookup rules. +type Backend interface { + // BeginReconcile marks the start of one pass so a backend may drop any + // per-pass caches (kernel route snapshots) before Plan/Verify read them. + BeginReconcile() + Plan(context.Context, *treatment.Treatment) ([]byte, error) + Install(context.Context, []byte) error + Verify(context.Context, []byte) error + Remove(context.Context, []byte) error + Enable(context.Context) error + Disable(context.Context) error +} + +// Reconciler drives one Backend from one Journal on behalf of one agent. +// AgentID, Location and BootID are written into the journal header on every +// save so the snapshot identifies its writer. CollectionID is written when +// set; a reconciler without one (the watchdog) keeps the journal's value, so +// only the agent process that owns the nonce can change it. +type Reconciler struct { + Journal Journal + Backend Backend + AgentID string + Location string + BootID string + CollectionID string + Now func() time.Time +} + +func (r *Reconciler) now() time.Time { + if r.Now != nil { + return r.Now() + } + return time.Now() +} + +func (r *Reconciler) header(s *State, now time.Time) { + s.AgentID = r.AgentID + s.Location = r.Location + s.BootID = r.BootID + if r.CollectionID != "" { + s.CollectionID = r.CollectionID + } + s.UpdatedAt = now +} + +// claimCollection writes the reconciler's collection nonce into the header +// when the journal holds another (or none), even if nothing else changed: a +// telemetry-only daemon stamps whatever the journal says, and the controller +// binds evidence to the nonce this process reports. +func (r *Reconciler) claimCollection(s *State, now time.Time, save func() error) error { + if r.CollectionID == "" || s.CollectionID == r.CollectionID { + return nil + } + r.header(s, now) + return save() +} + +// Run saves intent before touching the kernel and verifies before reporting +// success. See Mode for what ModeExpiryOnly may and may not do. The returned +// snapshot is a copy of the journal after the pass, even when it failed. +func (r *Reconciler) Run(ctx context.Context, in *treatment.DesiredState, mode Mode) (*State, error) { + if mode != ModeFull && mode != ModeExpiryOnly { + return nil, fmt.Errorf("unknown reconcile mode %d", mode) + } + var result *State + err := r.Journal.WithLock(ctx, func(s *State, save func() error) error { + defer func() { result = s.Clone() }() + r.Backend.BeginReconcile() + now := r.now() + if s.AgentID != "" && s.AgentID != r.AgentID { + return errors.New("journal belongs to another agent") + } + if in != nil { + if err := r.acceptDesired(s, in, mode, now, save); err != nil { + return err + } + } + if err := r.claimCollection(s, now, save); err != nil { + return err + } + if s.Desired == nil { + return nil + } + p := &pass{r: r, s: s, mode: mode, now: now, save: save, held: s.Held()} + return p.run(ctx) + }) + return result, err +} + +// acceptDesired validates in against the journal and persists it as the new +// desired state before anything touches the kernel. +func (r *Reconciler) acceptDesired(s *State, in *treatment.DesiredState, mode Mode, now time.Time, save func() error) error { + if mode == ModeExpiryOnly { + return errors.New("watchdog cannot accept desired state") + } + if err := treatment.ValidateDesired(in); err != nil { + return err + } + if in.AgentID != r.AgentID { + return errors.New("desired state is for another agent") + } + if s.Desired != nil { + if in.Revision < s.Desired.Revision { + return errors.New("stale desired revision") + } + if in.Revision == s.Desired.Revision && !in.Equal(s.Desired) { + return errors.New("conflicting desired state at same revision") + } + } + for i := range in.Assignments { + a := &in.Assignments[i] + if v := s.Record(a.ExperimentID); v != nil && a.Generation < v.Assignment.Generation { + return errors.New("stale assignment generation") + } + } + s.Desired = in.Clone() + r.header(s, now) + return save() +} + +// pass is one reconciliation of the journal's desired state against the +// kernel. Failures of individual assignments are recorded on their records +// and collected in errs; only journal and ordering faults abort the pass. +type pass struct { + r *Reconciler + s *State + mode Mode + now time.Time + save func() error + held bool + errs []error +} + +func (p *pass) run(ctx context.Context) error { + s := p.s + // Disable first: an interrupted cleanup must not leave suspended routes + // effective. Removal remains per-route and ownership checked. + if p.held { + if err := p.r.Backend.Disable(ctx); err != nil { + p.errs = append(p.errs, err) + } + } + active := map[string]bool{} + for i := range s.Desired.Assignments { + a := &s.Desired.Assignments[i] + if err := ctx.Err(); err != nil { + p.r.header(s, p.now) + return errors.Join(err, p.save()) + } + active[a.ExperimentID] = true + if err := p.assignment(ctx, a); err != nil { + return err + } + } + p.tombstones(ctx, active) + p.settle(ctx) + p.r.header(s, p.now) + if err := p.save(); err != nil { + return err + } + return errors.Join(p.errs...) +} + +// assignment brings one assignment's record and route in line with it. +func (p *pass) assignment(ctx context.Context, a *treatment.Assignment) error { + s, now := p.s, p.now + v := s.Record(a.ExperimentID) + if v == nil { + s.Records = append(s.Records, Record{ApplicationRecord: treatment.ApplicationRecord{Assignment: a.Clone(), ReceivedAt: now, Status: treatment.ApplyPending}}) + v = &s.Records[len(s.Records)-1] + } + if a.Generation < v.Assignment.Generation { + return errors.New("stale assignment generation") + } + if a.Generation > v.Assignment.Generation { + v.ExpiredLatched = false + v.ReceivedAt = now + } + v.Assignment = a.Clone() + v.DesiredRevision = s.Desired.Revision + if a.Mode == treatment.ModeTrial && !a.LeaseExpiresAt.After(now) { + v.ExpiredLatched = true + } + remove := p.held || a.Mode == treatment.ModeSuspended || a.Mode == treatment.ModeRetired || v.ExpiredLatched + if p.mode == ModeExpiryOnly && !remove { + return nil + } + var err error + switch { + case v.ExpiredLatched && !p.held && a.Mode == treatment.ModeTrial && a.Predecessor != nil: + if err = p.r.install(ctx, v, a.Predecessor, p.save, now); err == nil { + v.Status = treatment.ApplyExpired + } + case remove: + v.AttemptedAt = now + if len(v.InstalledRoute) > 0 { + if serr := p.save(); serr != nil { + return serr + } + } + err = p.withdraw(ctx, v) + default: + err = p.r.install(ctx, v, &a.Treatment, p.save, now) + } + if err != nil { + v.Status = treatment.ApplyFailed + v.Error = err.Error() + p.errs = append(p.errs, fmt.Errorf("%s: %w", a.ExperimentID, err)) + return nil + } + v.Error = "" + return nil +} + +// withdraw removes the record's route when this boot installed it and marks +// the record removed, or expired when its lease ran out. +func (p *pass) withdraw(ctx context.Context, v *Record) error { + if len(v.InstalledRoute) > 0 && v.InstalledBootID == p.r.BootID { + if err := p.r.Backend.Remove(ctx, v.InstalledRoute); err != nil { + return err + } + } + v.InstalledRoute = nil + v.RemovedAt = p.now + v.Status = treatment.ApplyRemoved + if v.ExpiredLatched { + v.Status = treatment.ApplyExpired + } + return nil +} + +// tombstones withdraws routes whose assignments are absent from the desired +// state. Such entries are never candidates for startup application. +func (p *pass) tombstones(ctx context.Context, active map[string]bool) { + for i := range p.s.Records { + v := &p.s.Records[i] + if active[v.Assignment.ExperimentID] || len(v.InstalledRoute) == 0 { + continue + } + if v.InstalledBootID == p.r.BootID { + if err := p.r.Backend.Remove(ctx, v.InstalledRoute); err != nil { + v.Error = err.Error() + v.Status = treatment.ApplyFailed + p.errs = append(p.errs, err) + continue + } + } + v.InstalledRoute = nil + v.Status = treatment.ApplyRemoved + v.RemovedAt = p.now + } +} + +// settle leaves the owned lookup rules consistent with the pass: disabled +// after any failure, enabled only when a clean full pass left routes +// installed, and disabled when nothing is installed. +func (p *pass) settle(ctx context.Context) { + if len(p.errs) > 0 { + // A failed withdrawal must not leave an expired/unknown override + // selected. Isolate the whole owned table until a clean pass. + if err := p.r.Backend.Disable(ctx); err != nil { + p.errs = append(p.errs, err) + } + p.failVerified("owned route lookup disabled after reconciliation failure") + return + } + if p.held || p.mode == ModeExpiryOnly { + return + } + hasRoutes := false + for i := range p.s.Records { + hasRoutes = hasRoutes || len(p.s.Records[i].InstalledRoute) > 0 + } + if !hasRoutes { + if err := p.r.Backend.Disable(ctx); err != nil { + p.errs = append(p.errs, err) + } + return + } + if err := p.r.Backend.Enable(ctx); err != nil { + p.errs = append(p.errs, err, p.r.Backend.Disable(ctx)) + p.failVerified(err.Error()) + } +} + +// failVerified demotes every verified record after the owned rules were +// disabled, so the report never claims a route the kernel cannot select. +func (p *pass) failVerified(reason string) { + for i := range p.s.Records { + if v := &p.s.Records[i]; v.Status == treatment.ApplyVerified { + v.Status = treatment.ApplyFailed + v.Error = reason + } + } +} + +func (r *Reconciler) install(ctx context.Context, v *Record, t *treatment.Treatment, save func() error, now time.Time) error { + b, err := r.Backend.Plan(ctx, t) + if err != nil { + // A forwarding change invalidates the override; remove it immediately. + if len(v.InstalledRoute) > 0 && v.InstalledBootID == r.BootID { + if e := r.Backend.Remove(ctx, v.InstalledRoute); e != nil { + return errors.Join(err, e) + } + v.InstalledRoute = nil + } + return err + } + if len(v.InstalledRoute) > 0 && v.InstalledBootID == r.BootID && !bytes.Equal(b, v.InstalledRoute) { + if err = r.Backend.Remove(ctx, v.InstalledRoute); err != nil { + return err + } + } + changed := !bytes.Equal(b, v.InstalledRoute) || v.InstalledBootID != r.BootID + if !changed && (v.Status == treatment.ApplyVerified || v.Status == treatment.ApplyExpired && v.ExpiredLatched) { + if err = r.Backend.Verify(ctx, b); err == nil { + v.VerifiedAt = now + return nil + } + } + v.AttemptedAt = now + v.InstalledRoute = b + v.InstalledBootID = r.BootID + v.Status = treatment.ApplyPending + if err = save(); err != nil { + return err + } + if err = r.Backend.Install(ctx, b); err != nil { + return err + } + if changed || v.AppliedAt.IsZero() { + v.AppliedAt = now + } + if err = r.Backend.Verify(ctx, b); err != nil { + return err + } + v.VerifiedAt = now + v.Status = treatment.ApplyVerified + return nil +} + +// SuspendLocal persists an offline hold (or lifts it) that controller +// requests cannot clear. A reason is required for the audit trail. ctx +// bounds the wait for the journal lock. +func (r *Reconciler) SuspendLocal(ctx context.Context, suspended bool, reason string) error { + if len(reason) == 0 || len(reason) > 1024 { + return errors.New("suspension/resume reason required (maximum 1024 bytes)") + } + return r.Journal.WithLock(ctx, func(s *State, save func() error) error { + if s.AgentID != "" && s.AgentID != r.AgentID { + return errors.New("journal belongs to another agent") + } + s.LocallySuspended = suspended + s.SuspensionReason = reason + r.header(s, r.now()) + return save() + }) +} diff --git a/pkg/treatment/reconcile/reconcile_test.go b/pkg/treatment/reconcile/reconcile_test.go new file mode 100644 index 000000000..71caf93f1 --- /dev/null +++ b/pkg/treatment/reconcile/reconcile_test.go @@ -0,0 +1,336 @@ +package reconcile + +import ( + "context" + "errors" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +func ptr[T any](v T) *T { return &v } + +type fakeBackend struct { + routes map[string]bool + enabled bool + failVerify bool + failRemove bool + installs int + onInstall func() +} + +func (f *fakeBackend) BeginReconcile() {} + +func (f *fakeBackend) Plan(_ context.Context, t *treatment.Treatment) ([]byte, error) { + return []byte(t.Destination.String() + ":" + t.Settings.Algorithm()), nil +} +func (f *fakeBackend) Install(_ context.Context, b []byte) error { + f.installs++ + if f.onInstall != nil { + f.onInstall() + } + f.routes[string(b)] = true + return nil +} +func (f *fakeBackend) Verify(_ context.Context, b []byte) error { + if f.failVerify || !f.routes[string(b)] { + return errors.New("readback failed") + } + return nil +} +func (f *fakeBackend) Remove(_ context.Context, b []byte) error { + if f.failRemove { + return errors.New("withdrawal failed") + } + delete(f.routes, string(b)) + return nil +} +func (f *fakeBackend) Enable(context.Context) error { f.enabled = true; return nil } +func (f *fakeBackend) Disable(context.Context) error { f.enabled = false; return nil } + +func newReconciler(t *testing.T, b Backend, now *time.Time) *Reconciler { + t.Helper() + r := &Reconciler{Journal: Journal{Dir: t.TempDir()}, Backend: b, AgentID: "host-1", Location: "dc1", BootID: "boot-1"} + if now != nil { + r.Now = func() time.Time { return *now } + } + return r +} + +func TestFailedWithdrawalDisablesOwnedLookup(t *testing.T) { + now := time.Now() + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + if _, e := r.Run(context.Background(), fixtures.Desired(now), ModeFull); e != nil { + t.Fatal(e) + } + if !b.enabled { + t.Fatal("lookup never enabled") + } + now = now.Add(61 * time.Minute) + b.failRemove = true + if _, e := r.Run(context.Background(), nil, ModeExpiryOnly); e == nil { + t.Fatal("withdrawal failure hidden") + } + if b.enabled { + t.Fatal("expired route still selected after failed withdrawal") + } + b.failRemove = false + if _, e := r.Run(context.Background(), nil, ModeFull); e != nil { + t.Fatal(e) + } + if len(b.routes) != 0 || b.enabled { + t.Fatal("failed withdrawal did not recover") + } +} + +func TestStableRouteSurvivesOfflineReboot(t *testing.T) { + now := time.Now() + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + d := fixtures.Desired(now) + d.Assignments[0].Mode = treatment.ModeStable + d.Assignments[0].LeaseExpiresAt = time.Time{} + if _, e := r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + now = now.Add(48 * time.Hour) + r.BootID = "boot-2" + b.routes = map[string]bool{} + b.enabled = false + s, e := r.Run(context.Background(), nil, ModeFull) + if e != nil || len(b.routes) != 1 || !b.enabled || s.Records[0].InstalledBootID != "boot-2" || s.BootID != "boot-2" { + t.Fatal("offline reboot did not restore stable treatment", e) + } +} + +func TestJournalIntentPrecedesKernelAndCrashRecovery(t *testing.T) { + now := time.Now() + b := &fakeBackend{routes: map[string]bool{}, failVerify: true} + r := newReconciler(t, b, &now) + dir := r.Journal.Dir + b.onInstall = func() { + raw, e := os.ReadFile(filepath.Join(dir, SnapshotFile)) + if e != nil || len(raw) == 0 { + t.Fatal("intent not durable before install", e) + } + } + s, e := r.Run(context.Background(), fixtures.Desired(now), ModeFull) + if e == nil || s.Records[0].Status != treatment.ApplyFailed { + t.Fatal("must report readback failure", s, e) + } + // The kernel changed before success was persisted. A fresh reconciler uses + // the journal to recover without needing a controller or another command. + b.failVerify = false + r2 := *r + s, e = r2.Run(context.Background(), nil, ModeFull) + if e != nil || s.Records[0].Status != treatment.ApplyVerified || len(b.routes) != 1 { + t.Fatal("restart did not converge", s, e) + } +} + +func TestTrialExpiryCannotBeResurrectedByRenewalOrRestart(t *testing.T) { + now := time.Now() + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + d := fixtures.Desired(now) + if _, e := r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + now = now.Add(61 * time.Minute) + s, e := r.Run(context.Background(), nil, ModeExpiryOnly) + if e != nil || len(b.routes) != 0 || s.Records[0].Status != treatment.ApplyExpired { + t.Fatal("watchdog expiry", s, e) + } + d.Revision++ + d.Assignments[0].LeaseExpiresAt = now.Add(time.Hour) + if _, e = r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + if len(b.routes) != 0 { + t.Fatal("lease renewal resurrected expired generation") + } + d.Revision++ + d.Assignments[0].Generation++ + if _, e = r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + if len(b.routes) != 1 { + t.Fatal("explicit approved generation did not activate") + } +} + +func TestPersistentHoldAndTombstones(t *testing.T) { + now := time.Now() + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, nil) + d := fixtures.Desired(now) + d.Assignments[0].Mode = treatment.ModeStable + if _, e := r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + if e := r.SuspendLocal(context.Background(), true, "incident test"); e != nil { + t.Fatal(e) + } + if _, e := r.Run(context.Background(), nil, ModeFull); e != nil { + t.Fatal(e) + } + if b.enabled || len(b.routes) != 0 { + t.Fatal("hold did not restore baseline") + } + d.Revision++ + if _, e := r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + if len(b.routes) != 0 { + t.Fatal("controller update cleared local hold") + } + if e := r.SuspendLocal(context.Background(), false, "test complete"); e != nil { + t.Fatal(e) + } + d.Revision++ + d.Assignments = nil + if _, e := r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + if _, e := r.Run(context.Background(), nil, ModeFull); e != nil { + t.Fatal(e) + } + if len(b.routes) != 0 { + t.Fatal("orphan projection resurrected treatment") + } + d.Revision-- + if _, e := r.Run(context.Background(), d, ModeFull); e == nil { + t.Fatal("accepted stale desired state") + } +} + +func TestCorruptJournalDoesNotInstall(t *testing.T) { + dir := t.TempDir() + if e := os.WriteFile(filepath.Join(dir, SnapshotFile), []byte("invalid!!"), 0600); e != nil { + t.Fatal(e) + } + b := &fakeBackend{routes: map[string]bool{}} + r := &Reconciler{Journal: Journal{Dir: dir}, Backend: b, AgentID: "host-1"} + if _, e := r.Run(context.Background(), fixtures.Desired(time.Now()), ModeFull); e == nil { + t.Fatal("corrupt journal overwritten") + } + if b.installs != 0 { + t.Fatal("kernel touched with corrupt state") + } +} + +func TestPredecessorExpiryAndGenerationRejectionPreserveJournal(t *testing.T) { + now := time.Now() + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + d := fixtures.Desired(now) + a := &d.Assignments[0] + a.ExperimentID = "state" + a.Generation = 2 + pred := a.Treatment + pred.Settings.CongestionControl = ptr("bbr") + a.Predecessor = &pred + if _, e := r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + now = now.Add(61 * time.Minute) + s, e := r.Run(context.Background(), nil, ModeExpiryOnly) + if e != nil || !b.routes["192.0.2.1/32:bbr"] || s.Records[0].Status != treatment.ApplyExpired { + t.Fatal("predecessor not restored", e) + } + installs := b.installs + if _, e = r.Run(context.Background(), nil, ModeExpiryOnly); e != nil { + t.Fatal(e) + } + if b.installs != installs { + t.Fatal("watchdog repeatedly reinstalled predecessor") + } + bad := d.Clone() + bad.Revision++ + bad.Assignments[0].Generation-- + if _, e = r.Run(context.Background(), bad, ModeFull); e == nil { + t.Fatal("stale generation accepted") + } + if e = r.Journal.WithLock(context.Background(), func(s *State, _ func() error) error { + if s.Desired.Revision != d.Revision { + t.Fatal("rejected generation poisoned persisted desired state") + } + return nil + }); e != nil { + t.Fatal(e) + } + d.Revision++ + a.Mode = treatment.ModeRetired + if _, e = r.Run(context.Background(), d, ModeFull); e != nil { + t.Fatal(e) + } + if len(b.routes) != 0 { + t.Fatal("retired assignment restored predecessor") + } +} + +func TestJournalHeaderIdentifiesWriter(t *testing.T) { + now := time.Unix(1700000000, 0) + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + s, e := r.Run(context.Background(), fixtures.Desired(now), ModeFull) + if e != nil || s.AgentID != "host-1" || s.Location != "dc1" || s.BootID != "boot-1" || !s.UpdatedAt.Equal(now) { + t.Fatalf("header not written: %+v %v", s, e) + } + other := *r + other.AgentID = "host-2" + if _, e = other.Run(context.Background(), nil, ModeFull); e == nil || !strings.Contains(e.Error(), "another agent") { + t.Fatalf("foreign journal accepted: %v", e) + } + if e = other.SuspendLocal(context.Background(), true, "x"); e == nil || !strings.Contains(e.Error(), "another agent") { + t.Fatalf("foreign journal suspended: %v", e) + } + if b.installs != 1 { + t.Fatal("foreign reconciler touched the kernel") + } +} + +// TestJournalCollectionIDOwnership: the agent's reconciler writes its nonce +// into the header; a reconciler without one (the watchdog) keeps whatever +// the journal holds, so only the owning agent process changes it. +func TestJournalCollectionIDOwnership(t *testing.T) { + const other = "fedcba9876543210fedcba9876543210" + for _, tc := range []struct { + name, description string + first, second string // CollectionID of the first and second writer + expected string + }{ + {"agent-writes", "positive: the agent's nonce lands in the header", fixtures.CollectionID, fixtures.CollectionID, fixtures.CollectionID}, + {"watchdog-preserves", "negative: a watchdog pass leaves the agent's nonce alone", fixtures.CollectionID, "", fixtures.CollectionID}, + {"agent-restart", "corner: a restarted agent replaces the nonce", fixtures.CollectionID, other, other}, + {"never-set", "boundary: a journal only the watchdog wrote has no nonce", "", "", ""}, + } { + t.Run(tc.name, func(t *testing.T) { + now := time.Unix(1700000000, 0) + b := &fakeBackend{routes: map[string]bool{}} + r := newReconciler(t, b, &now) + r.CollectionID = tc.first + if _, e := r.Run(context.Background(), fixtures.Desired(now), ModeFull); e != nil { + t.Fatal(e) + } + second := *r + second.CollectionID = tc.second + if _, e := second.Run(context.Background(), nil, ModeExpiryOnly); e != nil { + t.Fatal(e) + } + s, e := ReadSnapshot(r.Journal.Dir) + if e != nil { + t.Fatal(e) + } + if s.CollectionID != tc.expected { + t.Fatalf("%s: header nonce %q, want %q", tc.description, s.CollectionID, tc.expected) + } + }) + } +} diff --git a/pkg/treatment/reconcile/state.go b/pkg/treatment/reconcile/state.go new file mode 100644 index 000000000..ddcad037e --- /dev/null +++ b/pkg/treatment/reconcile/state.go @@ -0,0 +1,99 @@ +package reconcile + +import ( + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" +) + +// Record is one assignment as the host knows it: the report the controller +// receives plus the kernel-local facts that never leave the host. Only the +// embedded ApplicationRecord crosses the wire, so the local fields cannot +// leak by construction. +type Record struct { + treatment.ApplicationRecord + // InstalledRoute is the locally planned canonical netlink route body. + // Remove is only ever asked to withdraw exactly these bytes. + InstalledRoute []byte + // InstalledBootID is the boot that installed InstalledRoute. A route + // from another boot is a stale fingerprint, not a current installation. + InstalledBootID string +} + +// Clone copies the route bytes and the assignment's predecessor. +func (r Record) Clone() Record { + r.Assignment = r.Assignment.Clone() + if r.InstalledRoute != nil { + r.InstalledRoute = append([]byte(nil), r.InstalledRoute...) + } + return r +} + +// State is the journal snapshot: who wrote it, what the controller last +// asked for, the local hold and one record per assignment ever received. +// Entries missing from Desired are tombstones that are withdrawn and never +// re-applied. +type State struct { + AgentID string + Location string + // BootID is the boot that last wrote the journal. + BootID string + // CollectionID is the owning agent process's nonce; see + // treatment.ValidCollectionID. Empty until an agent has written it. + CollectionID string + Desired *treatment.DesiredState + LocallySuspended bool + SuspensionReason string + Records []Record + UpdatedAt time.Time +} + +// Clone deep-copies the snapshot so callers can keep it across passes. +func (s *State) Clone() *State { + if s == nil { + return nil + } + c := *s + c.Desired = s.Desired.Clone() + c.Records = make([]Record, len(s.Records)) + for i := range s.Records { + c.Records[i] = s.Records[i].Clone() + } + return &c +} + +// Record returns a pointer into s.Records for the experiment, or nil. +func (s *State) Record(experimentID string) *Record { + for i := range s.Records { + if s.Records[i].Assignment.ExperimentID == experimentID { + return &s.Records[i] + } + } + return nil +} + +// Reports strips the kernel-local fields for a check-in. +func (s *State) Reports() []treatment.ApplicationRecord { + if s == nil { + return nil + } + out := make([]treatment.ApplicationRecord, len(s.Records)) + for i := range s.Records { + out[i] = s.Records[i].ApplicationRecord + out[i].Assignment = out[i].Assignment.Clone() + } + return out +} + +// Held reports whether a local or controller hold is in force. +func (s *State) Held() bool { + return s != nil && (s.LocallySuspended || s.Desired != nil && s.Desired.Suspended) +} + +// Revision is the desired revision, zero before the first acceptance. +func (s *State) Revision() uint64 { + if s == nil || s.Desired == nil { + return 0 + } + return s.Desired.Revision +} diff --git a/pkg/treatment/validate.go b/pkg/treatment/validate.go new file mode 100644 index 000000000..2f40a6128 --- /dev/null +++ b/pkg/treatment/validate.go @@ -0,0 +1,233 @@ +// Package treatment is the route-treatment domain: the model, its +// enumerations, and the validation rules shared by the controller, the agent +// and the watchdog. It has no I/O and does not import the wire protocol. +package treatment + +import ( + "errors" + "fmt" + "math" + "net/netip" + "regexp" + "time" +) + +const MaxAssignments = 4096 +const MaxAgents = 10000 +const MaxStateBytes = 16 << 20 +const TrialLease = time.Hour +const LeaseRenewInterval = 5 * time.Minute + +var identifier = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$`) + +func ValidID(s string) bool { return identifier.MatchString(s) } + +// MinimumCohort is the smallest population an experiment may have. +const MinimumCohort = 3 + +// CollectionIDLength is the hex length of a collection nonce (16 bytes). +const CollectionIDLength = 32 + +// ValidCollectionID reports whether s is a collection nonce: 32 lowercase +// hex digits. An agent draws one per process, writes it to its journal and +// reports it at check-in; the daemon stamps it into every record so evidence +// can be bound to sessions the controller heard about over mTLS. +func ValidCollectionID(s string) bool { + if len(s) != CollectionIDLength { + return false + } + for _, c := range s { + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { + return false + } + } + return true +} + +// ValidDestination reports whether p is a canonical, globally routable /32 +// or /128 host prefix. +func ValidDestination(p netip.Prefix) bool { + return p.IsValid() && p == p.Masked() && p.Bits() == p.Addr().BitLen() && !p.Addr().Is4In6() && p.Addr().IsGlobalUnicast() && !p.Addr().IsLoopback() +} + +func ValidateTreatment(t *Treatment) error { + if t == nil || !ValidID(t.ID) || t.Revision == 0 { + return errors.New("treatment requires id, revision and settings") + } + if !ValidDestination(t.Destination) { + return errors.New("destination must be a canonical unicast /32 or /128 host prefix") + } + return ValidateTCPSettings(t.Settings, t.ECNFabricVerified) +} + +// ValidateTCPSettings also validates discovery templates before querying traffic. +func ValidateTCPSettings(s TCPSettings, ecnFabricVerified bool) error { + if s.CongestionControl != nil && !identifier.MatchString(*s.CongestionControl) { + return errors.New("invalid congestion algorithm") + } + if len(s.Algorithm()) > 15 { + return errors.New("congestion algorithm exceeds kernel name limit") + } + if s.CongestionLock && s.CongestionControl == nil { + return errors.New("congestion_lock requires an algorithm") + } + if s.Algorithm() == "dctcp" && (!ecnFabricVerified || s.ECN == nil || !*s.ECN) { + return errors.New("DCTCP requires independently verified ECN fabric and explicit ECN") + } + if s.RTOMinMs != nil && (*s.RTOMinMs < 1 || *s.RTOMinMs > 120000) { + return errors.New("rto_min_ms outside 1..120000") + } + for _, w := range []*uint32{s.InitialCongestionWindow, s.InitialReceiveWindow} { + if w != nil && (*w < 1 || *w > 1024) { + return errors.New("initial window outside 1..1024 segments") + } + } + if s.Empty() { + return errors.New("empty treatment") + } + return nil +} + +func ValidateDesired(d *DesiredState) error { + if d == nil || !ValidID(d.AgentID) || d.Revision == 0 || len(d.Assignments) > MaxAssignments || d.IssuedAt.IsZero() { + return errors.New("invalid desired-state header") + } + ids, destinations := map[string]bool{}, map[netip.Prefix]bool{} + for i := range d.Assignments { + a := &d.Assignments[i] + if !ValidID(a.ExperimentID) || a.Generation == 0 || ids[a.ExperimentID] { + return errors.New("invalid or duplicate assignment identity") + } + ids[a.ExperimentID] = true + if err := ValidateTreatment(&a.Treatment); err != nil { + return err + } + if !a.Mode.Valid() { + return errors.New("invalid assignment mode") + } + if a.Mode != ModeRetired { + if destinations[a.Treatment.Destination] { + return errors.New("overlapping treatments") + } + destinations[a.Treatment.Destination] = true + } + if a.Mode == ModeTrial && a.LeaseExpiresAt.IsZero() { + return errors.New("trial requires a valid expiry") + } + if a.Predecessor != nil { + if err := ValidateTreatment(a.Predecessor); err != nil { + return err + } + if a.Predecessor.Destination != a.Treatment.Destination { + return errors.New("predecessor destination differs") + } + } + } + return nil +} + +func DefaultPolicy() Policy { + return Policy{MinimumObservation: 30 * time.Minute, MaximumPhase: 24 * time.Hour, MaximumEvidenceAge: 2 * time.Minute, MinimumSocketsPerHost: 30, MinimumBytesPerHost: 1 << 20, MinimumTreatedHosts: 4, MinimumImprovement: .05, MaximumRetransmissionIncrease: .005, MaximumRTTIncrease: .1} +} + +func ValidatePolicy(p Policy) error { + for _, d := range []time.Duration{p.MinimumObservation, p.MaximumPhase, p.MaximumEvidenceAge} { + if d <= 0 || d > 7*24*time.Hour { + return errors.New("invalid policy duration") + } + } + if p.MinimumObservation > p.MaximumPhase || p.MinimumSocketsPerHost == 0 || p.MinimumBytesPerHost == 0 || p.MinimumTreatedHosts < 2 || p.MinimumTreatedHosts > MaxAgents { + return errors.New("invalid policy sample bounds") + } + for _, v := range []float64{p.MinimumImprovement, p.MaximumRetransmissionIncrease, p.MaximumRTTIncrease} { + if math.IsNaN(v) || math.IsInf(v, 0) || v < 0 || v > 1 { + return errors.New("invalid effect/guardrail bound") + } + } + return nil +} + +func ValidateEvidence(e *Evidence) error { + if e == nil || !ValidID(e.ID) || e.AnalyzedAt.IsZero() || e.WindowStart.IsZero() || e.WindowEnd.IsZero() || !e.WindowEnd.After(e.WindowStart) || e.AnalyzedAt.Before(e.WindowEnd) { + return errors.New("invalid evidence interval") + } + if e.QueryVersion == "" || len(e.QueryVersion) > 256 || len(e.EnrichmentVersion) > 256 || len(e.ArtifactSHA256) != 64 { + return errors.New("evidence provenance required") + } + for _, c := range e.ArtifactSHA256 { + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { + return errors.New("invalid evidence sha256") + } + } + if len(e.Hosts) == 0 || len(e.Hosts) > MaxAgents { + return errors.New("invalid evidence population") + } + seen := make(map[string]bool, len(e.Hosts)) + for i := range e.Hosts { + h := &e.Hosts[i] + if !ValidID(h.AgentID) || seen[h.AgentID] || h.ExposedSockets > h.Sockets { + return errors.New("invalid/duplicate evidence host") + } + seen[h.AgentID] = true + for _, v := range []float64{h.GoodputBps, h.RetransmissionRatio, h.RttP95Ms} { + if math.IsNaN(v) || math.IsInf(v, 0) || v < 0 { + return errors.New("invalid host measurement") + } + } + } + return nil +} + +func ValidateProposal(e *Experiment) error { + if e == nil || !ValidID(e.ID) || !ValidID(e.Location) || len(e.Hypothesis) == 0 || len(e.Hypothesis) > 8192 || len(e.CohortOrder) < MinimumCohort || len(e.CohortOrder) > MaxAgents { + return errors.New("invalid experiment identity or population (minimum three hosts)") + } + if err := ValidateTreatment(&e.Treatment); err != nil { + return err + } + if err := ValidatePolicy(e.Policy); err != nil { + return err + } + if err := ValidateEvidence(e.Baseline); err != nil { + return err + } + seen := map[string]bool{} + for _, id := range e.CohortOrder { + if !ValidID(id) || seen[id] { + return errors.New("invalid cohort") + } + seen[id] = true + } + for _, h := range e.Baseline.Hosts { + delete(seen, h.AgentID) + } + if len(seen) > 0 { + return fmt.Errorf("baseline missing %d cohort hosts", len(seen)) + } + return nil +} + +// ValidateReport checks a check-in before it is stored. Kernel bytes and boot +// IDs of installed routes are local to the host and must not be reported. +func ValidateReport(r *AgentReport) error { + if r == nil || !ValidID(r.AgentID) || !ValidID(r.Location) || !ValidID(r.Capabilities.BootID) || !ValidCollectionID(r.Capabilities.CollectionID) || len(r.Capabilities.KernelRelease) > 256 || len(r.Capabilities.CongestionAlgorithms) > 64 || len(r.Records) > MaxAssignments*2 { + return errors.New("invalid agent report") + } + for _, a := range r.Capabilities.CongestionAlgorithms { + if !ValidID(a) || len(a) > 15 { + return errors.New("invalid algorithm capability") + } + } + seen := map[string]bool{} + for i := range r.Records { + v := &r.Records[i] + if !ValidID(v.Assignment.ExperimentID) || seen[v.Assignment.ExperimentID] || len(v.Error) > 4096 || !v.Status.Valid() { + return errors.New("invalid application record") + } + seen[v.Assignment.ExperimentID] = true + if err := ValidateTreatment(&v.Assignment.Treatment); err != nil { + return err + } + } + return nil +} diff --git a/pkg/treatment/validate_test.go b/pkg/treatment/validate_test.go new file mode 100644 index 000000000..b41a0088e --- /dev/null +++ b/pkg/treatment/validate_test.go @@ -0,0 +1,377 @@ +package treatment_test + +import ( + "fmt" + "math" + "net/netip" + "strings" + "testing" + "time" + + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" +) + +func ptr[T any](v T) *T { return &v } + +// Each row states the contract, not just whether the implementation returned. +type validationCase[T any] struct { + name, description string + change func(*T) + wantError string // empty means acceptance; otherwise a required error substring +} + +func checkValidation[T any](t *testing.T, fresh func() T, validate func(T) error, cases []validationCase[T]) { + t.Helper() + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + input := fresh() + tc.change(&input) + err := validate(input) + if tc.wantError == "" { + if err != nil { + t.Fatalf("%s: expected acceptance, got %v", tc.description, err) + } + } else if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("%s: expected error containing %q, got %v", tc.description, tc.wantError, err) + } + }) + } +} + +func TestValidIDBoundaries(t *testing.T) { + for _, tc := range []struct { + name, description, input string + want bool + }{ + {"minimum", "one alphanumeric character is sufficient", "a", true}, + {"maximum", "128 characters are accepted", strings.Repeat("a", 128), true}, + {"too-long", "129 characters are rejected", strings.Repeat("a", 129), false}, + {"punctuation", "safe internal punctuation is accepted", "host-1.dc_2", true}, + {"empty", "empty identities are rejected", "", false}, + {"leading-dot", "identities must start with an alphanumeric", ".host", false}, + {"path", "path traversal is not an identity", "../host", false}, + {"newline", "a trailing newline is not ignored", "host\n", false}, + {"unicode", "identities are ASCII", "höst", false}, + } { + t.Run(tc.name, func(t *testing.T) { + if got := treatment.ValidID(tc.input); got != tc.want { + t.Fatalf("%s: got %t want %t", tc.description, got, tc.want) + } + }) + } +} + +func TestTreatmentValidation(t *testing.T) { + fixed := []validationCase[*treatment.Treatment]{ + {"valid", "the supported nearby profile is accepted", func(**treatment.Treatment) {}, ""}, + {"nil", "missing treatments are rejected", func(p **treatment.Treatment) { *p = nil }, "requires"}, + {"revision", "zero revision is invalid", func(p **treatment.Treatment) { (*p).Revision = 0 }, "requires"}, + {"empty-settings", "a treatment with no parameter set is rejected", func(p **treatment.Treatment) { (*p).Settings = treatment.TCPSettings{} }, "empty"}, + {"zero-destination", "the zero prefix is not a destination", func(p **treatment.Treatment) { (*p).Destination = netip.Prefix{} }, "canonical unicast"}, + } + cases := append(make([]validationCase[*treatment.Treatment], 0, len(fixed)+10), fixed...) + for _, tc := range []struct { + destination string + valid bool + }{ + {"192.168.1.1/32", true}, {"2001:db8::1/128", true}, {"192.0.2.0/24", false}, {"192.0.2.1/24", false}, {"::ffff:192.0.2.1/128", false}, {"127.0.0.1/32", false}, {"::1/128", false}, {"224.0.0.1/32", false}, {"fe80::1/128", false}, {"0.0.0.0/32", false}, + } { + want := "" + if !tc.valid { + want = "canonical unicast" + } + cases = append(cases, validationCase[*treatment.Treatment]{tc.destination, "destinations are canonical unicast host prefixes", func(p **treatment.Treatment) { (*p).Destination = netip.MustParsePrefix(tc.destination) }, want}) + } + checkValidation(t, func() *treatment.Treatment { + return &fixtures.Desired(time.Unix(1700000000, 0)).Assignments[0].Treatment + }, treatment.ValidateTreatment, cases) +} + +func TestTCPSettingsValidation(t *testing.T) { + type input struct { + s treatment.TCPSettings + verified bool + } + fixed := []validationCase[input]{ + {"cubic", "ordinary CUBIC is accepted", func(*input) {}, ""}, + {"empty", "at least one explicit metric is required", func(p *input) { p.s = treatment.TCPSettings{} }, "empty"}, + {"explicit-false", "false quickack is a real setting", func(p *input) { p.s = treatment.TCPSettings{QuickAck: ptr(false)} }, ""}, + {"lock-without-algorithm", "locking requires an algorithm", func(p *input) { p.s = treatment.TCPSettings{CongestionLock: true} }, "requires"}, + {"algorithm-max", "15 byte kernel name is accepted", func(p *input) { p.s.CongestionControl = ptr(strings.Repeat("a", 15)) }, ""}, + {"algorithm-long", "16 byte kernel name is rejected", func(p *input) { p.s.CongestionControl = ptr(strings.Repeat("a", 16)) }, "kernel name"}, + {"algorithm-empty", "explicit empty algorithm is invalid", func(p *input) { p.s.CongestionControl = ptr("") }, "invalid congestion"}, + {"dctcp-unverified", "ECN fabric verification is required", func(p *input) { p.s.CongestionControl = ptr("dctcp"); p.s.ECN = ptr(true) }, "DCTCP"}, + {"dctcp-no-ecn", "verification alone is insufficient", func(p *input) { p.s.CongestionControl = ptr("dctcp"); p.verified = true }, "DCTCP"}, + {"dctcp-ecn-false", "an explicit false ECN does not satisfy DCTCP", func(p *input) { + p.s.CongestionControl = ptr("dctcp") + p.s.ECN = ptr(false) + p.verified = true + }, "DCTCP"}, + {"dctcp-verified", "verified fabric and explicit ECN permit DCTCP", func(p *input) { + p.s.CongestionControl = ptr("dctcp") + p.s.ECN = ptr(true) + p.verified = true + }, ""}, + } + cases := append(make([]validationCase[input], 0, len(fixed)+3*4), fixed...) + for _, metric := range []string{"rto", "cwnd", "rwnd"} { + maximum := uint32(1024) + errorText := "initial window" + if metric == "rto" { + maximum = 120000 + errorText = "rto_min" + } + for _, value := range []uint32{0, 1, maximum, maximum + 1} { + want := "" + if value == 0 || value > maximum { + want = errorText + } + cases = append(cases, validationCase[input]{fmt.Sprintf("%s-%d", metric, value), "metric bounds are inclusive", func(p *input) { + switch metric { + case "rto": + p.s.RTOMinMs = ptr(value) + case "cwnd": + p.s.InitialCongestionWindow = ptr(value) + case "rwnd": + p.s.InitialReceiveWindow = ptr(value) + } + }, want}) + } + } + checkValidation(t, func() input { return input{s: treatment.TCPSettings{CongestionControl: ptr("cubic")}} }, func(p input) error { return treatment.ValidateTCPSettings(p.s, p.verified) }, cases) +} + +func TestPolicyValidation(t *testing.T) { + fixed := []validationCase[treatment.Policy]{ + {"default", "production defaults are valid", func(*treatment.Policy) {}, ""}, + {"zero", "the zero policy is rejected", func(p *treatment.Policy) { *p = treatment.Policy{} }, "duration"}, + {"observation-after-phase", "observation cannot exceed phase", func(p *treatment.Policy) { p.MaximumPhase = time.Minute }, "sample bounds"}, + {"zero-sockets", "sample count must be positive", func(p *treatment.Policy) { p.MinimumSocketsPerHost = 0 }, "sample bounds"}, + {"zero-bytes", "byte count must be positive", func(p *treatment.Policy) { p.MinimumBytesPerHost = 0 }, "sample bounds"}, + } + cases := append(make([]validationCase[treatment.Policy], 0, len(fixed)+4+3*4+3*7), fixed...) + for _, n := range []uint32{1, 2, treatment.MaxAgents, treatment.MaxAgents + 1} { + want := "" + if n < 2 || n > treatment.MaxAgents { + want = "sample bounds" + } + cases = append(cases, validationCase[treatment.Policy]{fmt.Sprintf("hosts-%d", n), "treated population bounds are inclusive", func(p *treatment.Policy) { p.MinimumTreatedHosts = n }, want}) + } + for _, field := range []string{"observation", "phase", "age"} { + for _, tc := range []struct { + name string + d time.Duration + want string + }{ + {"zero", 0, "duration"}, {"negative", -time.Second, "duration"}, {"maximum", 7 * 24 * time.Hour, ""}, {"over", 7*24*time.Hour + time.Nanosecond, "duration"}, + } { + cases = append(cases, validationCase[treatment.Policy]{field + "-" + tc.name, "durations must be positive and within seven days", func(p *treatment.Policy) { + p.MaximumPhase = 7 * 24 * time.Hour + switch field { + case "observation": + p.MinimumObservation = tc.d + case "phase": + p.MaximumPhase = tc.d + case "age": + p.MaximumEvidenceAge = tc.d + } + }, tc.want}) + } + } + for _, field := range []string{"effect", "loss", "rtt"} { + for _, v := range []float64{-1, 0, 1, 1.0001, math.NaN(), math.Inf(1), math.Inf(-1)} { + want := "" + if math.IsNaN(v) || math.IsInf(v, 0) || v < 0 || v > 1 { + want = "guardrail" + } + cases = append(cases, validationCase[treatment.Policy]{fmt.Sprintf("%s-%g", field, v), "effect bounds must be finite fractions in [0,1]", func(p *treatment.Policy) { + switch field { + case "effect": + p.MinimumImprovement = v + case "loss": + p.MaximumRetransmissionIncrease = v + case "rtt": + p.MaximumRTTIncrease = v + } + }, want}) + } + } + checkValidation(t, treatment.DefaultPolicy, treatment.ValidatePolicy, cases) +} + +func TestEvidenceValidation(t *testing.T) { + now := time.Unix(1700000000, 0) + fixed := []validationCase[*treatment.Evidence]{ + {"valid", "complete finite evidence is accepted", func(**treatment.Evidence) {}, ""}, + {"nil", "evidence is required", func(p **treatment.Evidence) { *p = nil }, "interval"}, + {"empty-window", "a zero length window is invalid", func(p **treatment.Evidence) { (*p).WindowStart = (*p).WindowEnd }, "interval"}, + {"analysis-before-end", "analysis cannot predate data", func(p **treatment.Evidence) { (*p).AnalyzedAt = (*p).WindowStart }, "interval"}, + {"missing-time", "all timestamps are required", func(p **treatment.Evidence) { (*p).WindowEnd = time.Time{} }, "interval"}, + {"analysis-equals-end", "analysis at the window end is the earliest valid instant", func(p **treatment.Evidence) { (*p).AnalyzedAt = (*p).WindowEnd }, ""}, + {"query-version", "query provenance is required", func(p **treatment.Evidence) { (*p).QueryVersion = "" }, "provenance"}, + {"long-version", "query version length is bounded", func(p **treatment.Evidence) { (*p).QueryVersion = strings.Repeat("v", 257) }, "provenance"}, + {"digest-length", "digest is exactly 64 characters", func(p **treatment.Evidence) { (*p).ArtifactSHA256 = "a" }, "provenance"}, + {"digest-hex", "digest is lower case hexadecimal", func(p **treatment.Evidence) { (*p).ArtifactSHA256 = strings.Repeat("z", 64) }, "sha256"}, + {"empty-hosts", "empty evidence is not healthy evidence", func(p **treatment.Evidence) { (*p).Hosts = nil }, "population"}, + {"zero-host", "a host without an identity is rejected", func(p **treatment.Evidence) { (*p).Hosts[0] = treatment.HostEvidence{} }, "host"}, + {"duplicate-host", "hosts are independent units", func(p **treatment.Evidence) { (*p).Hosts[1] = (*p).Hosts[0] }, "host"}, + {"overexposure", "exposed sockets cannot exceed total sockets", func(p **treatment.Evidence) { (*p).Hosts[0].ExposedSockets = 101 }, "host"}, + } + cases := append(make([]validationCase[*treatment.Evidence], 0, len(fixed)+3*5+2), fixed...) + for _, field := range []string{"goodput", "loss", "rtt"} { + for _, v := range []float64{0, -1, math.NaN(), math.Inf(1), math.Inf(-1)} { + want := "" + if v != 0 { + want = "measurement" + } + cases = append(cases, validationCase[*treatment.Evidence]{fmt.Sprintf("%s-%g", field, v), "measurements must be finite and nonnegative", func(p **treatment.Evidence) { + h := &(*p).Hosts[0] + switch field { + case "goodput": + h.GoodputBps = v + case "loss": + h.RetransmissionRatio = v + case "rtt": + h.RttP95Ms = v + } + }, want}) + } + } + for _, n := range []int{treatment.MaxAgents, treatment.MaxAgents + 1} { + want := "" + if n > treatment.MaxAgents { + want = "population" + } + cases = append(cases, validationCase[*treatment.Evidence]{fmt.Sprintf("population-%d", n), "fleet population is bounded", func(p **treatment.Evidence) { + (*p).Hosts = nil + for i := range n { + (*p).Hosts = append((*p).Hosts, treatment.HostEvidence{AgentID: fmt.Sprintf("host-%d", i)}) + } + }, want}) + } + checkValidation(t, func() *treatment.Evidence { _, v := fixtures.Experiment(now, treatment.DefaultPolicy()); return v }, treatment.ValidateEvidence, cases) +} + +func TestDesiredValidation(t *testing.T) { + now := time.Unix(1700000000, 0) + fixed := []validationCase[*treatment.DesiredState]{ + {"valid", "leased trials are accepted", func(**treatment.DesiredState) {}, ""}, + {"nil", "desired header is required", func(p **treatment.DesiredState) { *p = nil }, "header"}, + {"empty", "empty assignment set withdraws treatments", func(p **treatment.DesiredState) { (*p).Assignments = nil }, ""}, + {"zero-revision", "revisions start at one", func(p **treatment.DesiredState) { (*p).Revision = 0 }, "header"}, + {"missing-time", "issuance time is required", func(p **treatment.DesiredState) { (*p).IssuedAt = time.Time{} }, "header"}, + {"zero-assignment", "an assignment without identity is rejected", func(p **treatment.DesiredState) { (*p).Assignments[0] = treatment.Assignment{} }, "identity"}, + {"zero-generation", "generations start at one", func(p **treatment.DesiredState) { (*p).Assignments[0].Generation = 0 }, "identity"}, + {"duplicate-id", "assignment IDs must be unique", func(p **treatment.DesiredState) { + (*p).Assignments = append((*p).Assignments, (*p).Assignments[0]) + }, "identity"}, + {"duplicate-destination", "active routes cannot overlap", func(p **treatment.DesiredState) { + a := (*p).Assignments[0] + a.ExperimentID = "other" + (*p).Assignments = append((*p).Assignments, a) + }, "overlapping"}, + {"retired-overlap", "retired routes may overlap active routes", func(p **treatment.DesiredState) { + a := (*p).Assignments[0] + a.ExperimentID = "other" + a.Mode = treatment.ModeRetired + (*p).Assignments = append((*p).Assignments, a) + }, ""}, + {"invalid-mode", "unknown modes are rejected", func(p **treatment.DesiredState) { (*p).Assignments[0].Mode = 99 }, "mode"}, + {"unspecified-mode", "the zero mode is not an instruction", func(p **treatment.DesiredState) { (*p).Assignments[0].Mode = treatment.ModeUnspecified }, "mode"}, + {"missing-lease", "trials require an expiry", func(p **treatment.DesiredState) { (*p).Assignments[0].LeaseExpiresAt = time.Time{} }, "expiry"}, + {"stable-no-lease", "stable routes need no lease", func(p **treatment.DesiredState) { + a := &(*p).Assignments[0] + a.Mode = treatment.ModeStable + a.LeaseExpiresAt = time.Time{} + }, ""}, + {"predecessor", "matching predecessor is accepted", func(p **treatment.DesiredState) { + a := &(*p).Assignments[0] + pred := a.Treatment + a.Predecessor = &pred + }, ""}, + {"wrong-predecessor", "predecessor must cover the same destination", func(p **treatment.DesiredState) { + a := &(*p).Assignments[0] + pred := a.Treatment + pred.Destination = netip.MustParsePrefix("192.0.2.2/32") + a.Predecessor = &pred + }, "differs"}, + } + cases := append(make([]validationCase[*treatment.DesiredState], 0, len(fixed)+2), fixed...) + for _, n := range []int{treatment.MaxAssignments, treatment.MaxAssignments + 1} { + want := "" + if n > treatment.MaxAssignments { + want = "header" + } + cases = append(cases, validationCase[*treatment.DesiredState]{fmt.Sprintf("assignments-%d", n), "assignment count is bounded", func(p **treatment.DesiredState) { + base := (*p).Assignments[0] + (*p).Assignments = nil + for i := range n { + a := base + a.ExperimentID = fmt.Sprintf("a-%d", i) + a.Treatment.Destination = netip.MustParsePrefix(fmt.Sprintf("198.18.%d.%d/32", i/256, i%256)) + (*p).Assignments = append((*p).Assignments, a) + } + }, want}) + } + checkValidation(t, func() *treatment.DesiredState { return fixtures.Desired(now) }, treatment.ValidateDesired, cases) +} + +func TestProposalValidation(t *testing.T) { + now := time.Unix(1700000000, 0) + checkValidation(t, func() *treatment.Experiment { e, _ := fixtures.Experiment(now, treatment.DefaultPolicy()); return e }, treatment.ValidateProposal, []validationCase[*treatment.Experiment]{ + {"valid", "complete proposal is reviewable", func(**treatment.Experiment) {}, ""}, + {"nil", "proposal is required", func(p **treatment.Experiment) { *p = nil }, "identity"}, + {"no-hypothesis", "proposal must state a hypothesis", func(p **treatment.Experiment) { (*p).Hypothesis = "" }, "identity"}, + {"long-hypothesis", "hypothesis is bounded", func(p **treatment.Experiment) { (*p).Hypothesis = strings.Repeat("x", 8193) }, "identity"}, + {"three-hosts", "one canary and two controls suffice", func(p **treatment.Experiment) { (*p).CohortOrder = (*p).CohortOrder[:3] }, ""}, + {"two-hosts", "two hosts cannot provide a canary and two controls", func(p **treatment.Experiment) { (*p).CohortOrder = (*p).CohortOrder[:2] }, "population"}, + {"duplicate", "duplicate hosts cannot inflate the cohort", func(p **treatment.Experiment) { (*p).CohortOrder[1] = (*p).CohortOrder[0] }, "cohort"}, + {"missing-baseline-host", "every cohort member needs a baseline", func(p **treatment.Experiment) { (*p).CohortOrder[0] = "absent" }, "baseline missing"}, + {"invalid-treatment", "proposal validates treatment", func(p **treatment.Experiment) { (*p).Treatment = treatment.Treatment{} }, "requires"}, + {"invalid-policy", "proposal validates policy", func(p **treatment.Experiment) { (*p).Policy = treatment.Policy{} }, "policy"}, + {"invalid-evidence", "proposal validates evidence", func(p **treatment.Experiment) { (*p).Baseline = nil }, "interval"}, + }) +} + +func TestReportValidation(t *testing.T) { + now := time.Unix(1700000000, 0) + fresh := func() *treatment.AgentReport { + d := fixtures.Desired(now) + return &treatment.AgentReport{AgentID: "host-1", Location: "dc1", Capabilities: treatment.Capabilities{BootID: "boot-1", CollectionID: fixtures.CollectionID, KernelRelease: "6.12", CongestionAlgorithms: []string{"cubic", "bbr"}, SimpleHostRouting: true, ActuatorEnabled: true}, DesiredRevision: 1, Records: []treatment.ApplicationRecord{{Assignment: d.Assignments[0], DesiredRevision: 1, Status: treatment.ApplyVerified, AppliedAt: now}}} + } + fixed := []validationCase[*treatment.AgentReport]{ + {"valid", "a verified report is accepted", func(**treatment.AgentReport) {}, ""}, + {"nil", "a report is required", func(p **treatment.AgentReport) { *p = nil }, "agent report"}, + {"no-records", "a fresh host reports nothing", func(p **treatment.AgentReport) { (*p).Records = nil }, ""}, + {"bad-boot-id", "boot IDs are identifiers", func(p **treatment.AgentReport) { (*p).Capabilities.BootID = "" }, "agent report"}, + {"missing-collection-id", "a report must carry the agent's collection nonce", func(p **treatment.AgentReport) { (*p).Capabilities.CollectionID = "" }, "agent report"}, + {"short-collection-id", "a 31-digit nonce is refused", func(p **treatment.AgentReport) { (*p).Capabilities.CollectionID = fixtures.CollectionID[1:] }, "agent report"}, + {"upper-collection-id", "the nonce is lowercase hex, so it can never carry a quote", func(p **treatment.AgentReport) { + (*p).Capabilities.CollectionID = strings.ToUpper(fixtures.CollectionID) + }, "agent report"}, + {"long-kernel", "kernel release is bounded", func(p **treatment.AgentReport) { (*p).Capabilities.KernelRelease = strings.Repeat("k", 257) }, "agent report"}, + {"long-algorithm", "algorithm names respect the kernel limit", func(p **treatment.AgentReport) { + (*p).Capabilities.CongestionAlgorithms = []string{strings.Repeat("a", 16)} + }, "algorithm"}, + {"duplicate-record", "one record per experiment", func(p **treatment.AgentReport) { (*p).Records = append((*p).Records, (*p).Records[0]) }, "application record"}, + {"long-error", "error text is bounded", func(p **treatment.AgentReport) { (*p).Records[0].Error = strings.Repeat("e", 4097) }, "application record"}, + {"unknown-status", "an apply status this build does not know is rejected", func(p **treatment.AgentReport) { (*p).Records[0].Status = 200 }, "application record"}, + {"unspecified-status", "an unacted assignment may be reported", func(p **treatment.AgentReport) { (*p).Records[0].Status = treatment.ApplyUnspecified }, ""}, + {"bad-treatment", "records carry valid treatments", func(p **treatment.AgentReport) { (*p).Records[0].Assignment.Treatment.Revision = 0 }, "requires"}, + } + cases := append(make([]validationCase[*treatment.AgentReport], 0, len(fixed)+2), fixed...) + for _, n := range []int{64, 65} { + want := "" + if n > 64 { + want = "agent report" + } + cases = append(cases, validationCase[*treatment.AgentReport]{fmt.Sprintf("algorithms-%d", n), "advertised algorithm count is bounded", func(p **treatment.AgentReport) { + (*p).Capabilities.CongestionAlgorithms = nil + for i := range n { + (*p).Capabilities.CongestionAlgorithms = append((*p).Capabilities.CongestionAlgorithms, fmt.Sprintf("cc%d", i)) + } + }, want}) + } + checkValidation(t, fresh, treatment.ValidateReport, cases) +} diff --git a/pkg/treatment/wire/rules_test.go b/pkg/treatment/wire/rules_test.go new file mode 100644 index 000000000..93e7f011f --- /dev/null +++ b/pkg/treatment/wire/rules_test.go @@ -0,0 +1,191 @@ +package wire_test + +import ( + "errors" + "slices" + "strings" + "testing" + "time" + + "buf.build/go/protovalidate" + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// The buf.validate rules on proto/xtcp_treatment/v1 mirror the bounds in +// validate.go. These rows pin that mirror: a bound changed in one place and +// not the other fails here. Contextual checks (duplicate IDs, overlapping +// destinations, cohort/baseline agreement) stay Go-only and are covered by +// validate_test.go. +// +// go test ./pkg/treatment -run TestProtoRulesMirrorValidators +func TestProtoRulesMirrorValidators(t *testing.T) { + now := time.Unix(1700000000, 0) + id128 := strings.Repeat("a", 128) + experiment := func(mut func(*pb.Experiment)) proto.Message { + e, _ := fixtures.ExperimentWire(now, treatment.DefaultPolicy()) + mut(e) + return e + } + desired := func(mut func(*pb.DesiredState)) proto.Message { + d := fixtures.DesiredWire(now) + mut(d) + return d + } + control := func(mut func(*pb.ControlRequest)) proto.Message { + c := &pb.ControlRequest{ExperimentId: "exp", Action: pb.ControlAction_CONTROL_ACTION_PAUSE, Reason: "why", RequestId: "req-1"} + mut(c) + return c + } + tests := []struct { + description string + msg proto.Message + expected string // substring of the violation rule id, or "" for valid + }{ + {"positive: the desired-state fixture is valid", desired(func(*pb.DesiredState) {}), ""}, + {"positive: the experiment fixture is valid", experiment(func(*pb.Experiment) {}), ""}, + {"positive: a propose request wrapping the fixture is valid", &pb.ProposeRequest{Experiment: experiment(func(*pb.Experiment) {}).(*pb.Experiment), RequestId: "req-1"}, ""}, + {"positive: a minimal check-in is valid", &pb.CheckInRequest{AgentId: "host-1", Location: "dc1", Capabilities: &pb.Capabilities{BootId: "boot", CollectionId: fixtures.CollectionID}}, ""}, + {"positive: a control request with exactly one selector is valid", control(func(*pb.ControlRequest) {}), ""}, + {"positive: fleet control with no other selector is valid", control(func(c *pb.ControlRequest) { c.ExperimentId = ""; c.Fleet = true }), ""}, + + {"negative: identifier with a leading dash", desired(func(d *pb.DesiredState) { d.AgentId = "-host" }), "string.pattern"}, + {"negative: a check-in without a collection nonce", &pb.CheckInRequest{AgentId: "host-1", Location: "dc1", Capabilities: &pb.Capabilities{BootId: "boot"}}, "string.pattern"}, + {"negative: an uppercase collection nonce", &pb.CheckInRequest{AgentId: "host-1", Location: "dc1", Capabilities: &pb.Capabilities{BootId: "boot", CollectionId: strings.ToUpper(fixtures.CollectionID)}}, "string.pattern"}, + {"negative: revision zero", desired(func(d *pb.DesiredState) { d.Revision = 0 }), "uint64.gt"}, + {"negative: missing issued_at", desired(func(d *pb.DesiredState) { d.IssuedAt = nil }), "required"}, + {"negative: empty TCP settings", desired(func(d *pb.DesiredState) { d.Assignments[0].Treatment.Settings = &pb.TCPSettings{} }), "tcp_settings.non_empty"}, + {"negative: congestion_lock without an algorithm", desired(func(d *pb.DesiredState) { + d.Assignments[0].Treatment.Settings = &pb.TCPSettings{CongestionLock: true, QuickAck: proto.Bool(true)} + }), "tcp_settings.lock_requires_algorithm"}, + {"negative: DCTCP without verified ECN fabric", desired(func(d *pb.DesiredState) { + d.Assignments[0].Treatment.Settings.CongestionControl = proto.String("dctcp") + }), "treatment.dctcp_requires_ecn"}, + {"negative: destination that is not a prefix", desired(func(d *pb.DesiredState) { d.Assignments[0].Treatment.Destination = "192.0.2.1" }), "string.ip_prefix"}, + {"negative: trial without a lease", desired(func(d *pb.DesiredState) { d.Assignments[0].LeaseExpiresAt = nil }), "assignment.trial_requires_lease"}, + {"negative: unspecified assignment mode", desired(func(d *pb.DesiredState) { d.Assignments[0].Mode = pb.AssignmentMode_ASSIGNMENT_MODE_UNSPECIFIED }), "enum"}, + {"negative: predecessor on another destination", desired(func(d *pb.DesiredState) { + p := proto.Clone(d.Assignments[0].Treatment).(*pb.Treatment) + p.Destination = "192.0.2.2/32" + d.Assignments[0].Predecessor = p + }), "assignment.predecessor_destination"}, + {"negative: evidence window inverted", experiment(func(e *pb.Experiment) { + e.Baseline.WindowStart, e.Baseline.WindowEnd = e.Baseline.WindowEnd, e.Baseline.WindowStart + }), "evidence.interval"}, + {"negative: evidence analyzed before its window closed", experiment(func(e *pb.Experiment) { + e.Baseline.AnalyzedAt = timestamppb.New(e.Baseline.WindowEnd.AsTime().Add(-time.Second)) + }), "evidence.interval"}, + {"negative: artifact digest of the wrong length", experiment(func(e *pb.Experiment) { e.Baseline.ArtifactSha256 = "abc" }), "string.pattern"}, + {"negative: exposed sockets exceed sockets", experiment(func(e *pb.Experiment) { e.Baseline.Hosts[0].ExposedSockets = e.Baseline.Hosts[0].Sockets + 1 }), "host_evidence.exposed_within_sockets"}, + {"negative: observation longer than the phase", experiment(func(e *pb.Experiment) { + e.Policy.MinimumObservation = durationpb.New(25 * time.Hour) + }), "policy.observation_within_phase"}, + {"negative: too few cohort hosts", experiment(func(e *pb.Experiment) { e.CohortOrder = e.CohortOrder[:2] }), "repeated.min_items"}, + {"negative: duplicate cohort hosts", experiment(func(e *pb.Experiment) { e.CohortOrder[1] = e.CohortOrder[0] }), "repeated.unique"}, + {"negative: empty hypothesis", experiment(func(e *pb.Experiment) { e.Hypothesis = "" }), "string.min_len"}, + {"negative: two control selectors", control(func(c *pb.ControlRequest) { c.AgentId = "host-1" }), "control.one_selector"}, + {"negative: no control selector", control(func(c *pb.ControlRequest) { c.ExperimentId = "" }), "control.one_selector"}, + {"negative: unspecified control action", control(func(c *pb.ControlRequest) { c.Action = pb.ControlAction_CONTROL_ACTION_UNSPECIFIED }), "enum"}, + {"negative: empty control reason", control(func(c *pb.ControlRequest) { c.Reason = "" }), "string.min_len"}, + {"negative: request_id reserved suffix", control(func(c *pb.ControlRequest) { c.RequestId = "req.result" }), "control.request_id_suffix"}, + + {"boundary: identifier of exactly 128 bytes", desired(func(d *pb.DesiredState) { d.AgentId = id128 }), ""}, + {"boundary: identifier of 129 bytes", desired(func(d *pb.DesiredState) { d.AgentId = id128 + "a" }), "string.pattern"}, + {"boundary: rto_min_ms at the upper bound", desired(func(d *pb.DesiredState) { d.Assignments[0].Treatment.Settings.RtoMinMs = proto.Uint32(120000) }), ""}, + {"boundary: rto_min_ms one over the upper bound", desired(func(d *pb.DesiredState) { d.Assignments[0].Treatment.Settings.RtoMinMs = proto.Uint32(120001) }), "uint32.gte_lte"}, + {"boundary: initial window at the upper bound", desired(func(d *pb.DesiredState) { + d.Assignments[0].Treatment.Settings.InitialCongestionWindow = proto.Uint32(1024) + }), ""}, + {"boundary: initial window of zero", desired(func(d *pb.DesiredState) { + d.Assignments[0].Treatment.Settings.InitialCongestionWindow = proto.Uint32(0) + }), "uint32.gte"}, + {"boundary: reason of exactly 4096 bytes", control(func(c *pb.ControlRequest) { c.Reason = strings.Repeat("r", 4096) }), ""}, + {"boundary: reason of 4097 bytes", control(func(c *pb.ControlRequest) { c.Reason = strings.Repeat("r", 4097) }), "string.max_len"}, + {"boundary: policy duration at seven days", experiment(func(e *pb.Experiment) { e.Policy.MaximumPhase = durationpb.New(7 * 24 * time.Hour) }), ""}, + {"boundary: policy duration over seven days", experiment(func(e *pb.Experiment) { e.Policy.MaximumPhase = durationpb.New(7*24*time.Hour + time.Second) }), "duration.gt_lte"}, + {"boundary: minimum_treated_hosts of one", experiment(func(e *pb.Experiment) { e.Policy.MinimumTreatedHosts = 1 }), "uint32.gte"}, + + {"corner: inspect with no selectors is valid (ignore on zero value)", &pb.InspectRequest{}, ""}, + {"corner: inspect with a malformed selector is rejected", &pb.InspectRequest{AgentId: "bad id"}, "string.pattern"}, + {"corner: upper-case hex digest is rejected", experiment(func(e *pb.Experiment) { e.Baseline.ArtifactSha256 = strings.ToUpper(e.Baseline.ArtifactSha256) }), "string.pattern"}, + {"corner: a 15-byte congestion algorithm name is accepted, 16 is not", desired(func(d *pb.DesiredState) { + d.Assignments[0].Treatment.Settings.CongestionControl = proto.String(strings.Repeat("c", 16)) + }), "string.max_len"}, + {"corner: an IPv6 host prefix is accepted", desired(func(d *pb.DesiredState) { d.Assignments[0].Treatment.Destination = "2001:db8::1/128" }), ""}, + {"corner: NaN guardrail is rejected", experiment(func(e *pb.Experiment) { e.Policy.MaximumRttIncrease = nan() }), "double.finite"}, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + err := protovalidate.Validate(tc.msg) + if tc.expected == "" { + if err != nil { + t.Fatalf("expected valid, got %v", err) + } + return + } + if err == nil { + t.Fatalf("expected a violation matching %q", tc.expected) + } + var ve *protovalidate.ValidationError + if !errors.As(err, &ve) { + t.Fatalf("expected a ValidationError, got %T: %v", err, err) + } + var ids []string + for _, v := range ve.Violations { + ids = append(ids, v.Proto.GetRuleId()) + } + if !slices.ContainsFunc(ids, func(id string) bool { return strings.Contains(id, tc.expected) }) { + t.Fatalf("expected a violation of %q, got %v (%v)", tc.expected, ids, err) + } + }) + } +} + +func nan() float64 { + zero := 0.0 + return zero / zero +} + +// Every RPC must declare a role; a forgotten annotation is refused for all +// callers, so this test turns a silent outage into a build-time failure. +// +// go test ./pkg/treatment -run TestEveryRPCDeclaresARole +func TestEveryRPCDeclaresARole(t *testing.T) { + files := []protoreflect.FileDescriptor{pb.File_xtcp_treatment_v1_agent_proto, pb.File_xtcp_treatment_v1_operator_proto} + want := map[protoreflect.FullName]pb.Role{ + "xtcp_treatment.v1.AgentControlService": pb.Role_ROLE_AGENT, + "xtcp_treatment.v1.OperatorService": pb.Role_ROLE_OPERATOR, + } + seen := 0 + for _, f := range files { + services := f.Services() + for i := 0; i < services.Len(); i++ { + svc := services.Get(i) + expected, ok := want[svc.FullName()] + if !ok { + t.Errorf("service %s has no expected role in this test; add it", svc.FullName()) + continue + } + methods := svc.Methods() + for j := 0; j < methods.Len(); j++ { + m := methods.Get(j) + seen++ + role := proto.GetExtension(m.Options(), pb.E_Role).(pb.Role) + if role == pb.Role_ROLE_UNSPECIFIED { + t.Errorf("%s.%s declares no (xtcp_treatment.v1.role)", svc.FullName(), m.Name()) + } + if role != expected { + t.Errorf("%s.%s declares %s, expected %s", svc.FullName(), m.Name(), role, expected) + } + } + } + } + if seen != 8 { + t.Errorf("walked %d methods, expected 8; a service was added or removed", seen) + } +} diff --git a/pkg/treatment/wire/wire.go b/pkg/treatment/wire/wire.go new file mode 100644 index 000000000..afb820313 --- /dev/null +++ b/pkg/treatment/wire/wire.go @@ -0,0 +1,468 @@ +// Package wire converts between the treatment domain model and the +// xtcp_treatment.v1 protobuf messages. It is the only place that knows both +// shapes: the controller's gRPC handlers, the agent's journal and the CLIs +// call it at their edges and work on domain values everywhere else. +// +// Domain → wire functions never fail. Wire → domain functions are named +// Parse* and fail closed on unknown enum values, invalid timestamps and +// malformed durations so a newer or hostile peer cannot smuggle a value this +// build does not understand. +package wire + +import ( + "errors" + "fmt" + "net/netip" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func stamp(t time.Time) *timestamppb.Timestamp { + if t.IsZero() { + return nil + } + return timestamppb.New(t) +} + +func parseStamp(field string, t *timestamppb.Timestamp) (time.Time, error) { + if t == nil { + return time.Time{}, nil + } + if err := t.CheckValid(); err != nil { + return time.Time{}, fmt.Errorf("%s: %w", field, err) + } + return t.AsTime(), nil +} + +func parseDuration(field string, d *durationpb.Duration) (time.Duration, error) { + if d == nil { + return 0, nil + } + if err := d.CheckValid(); err != nil { + return 0, fmt.Errorf("%s: %w", field, err) + } + return d.AsDuration(), nil +} + +// Enumerations. The domain values mirror the wire values numerically; the +// range check is what makes the cast safe (TestEnumsMirrorWire pins it). + +func Status(s treatment.Status) pb.ExperimentStatus { return pb.ExperimentStatus(s) } + +func ParseStatus(w pb.ExperimentStatus) (treatment.Status, error) { + n, _, _, _ := treatment.EnumCounts() + if w < 0 || int(w) >= n { + return 0, fmt.Errorf("unknown wire experiment status %d", int32(w)) + } + return treatment.Status(w), nil +} + +func Mode(m treatment.AssignmentMode) pb.AssignmentMode { return pb.AssignmentMode(m) } + +func ParseMode(w pb.AssignmentMode) (treatment.AssignmentMode, error) { + _, n, _, _ := treatment.EnumCounts() + if w < 0 || int(w) >= n { + return 0, fmt.Errorf("unknown wire assignment mode %d", int32(w)) + } + return treatment.AssignmentMode(w), nil +} + +func ApplyStatus(a treatment.ApplyStatus) pb.ApplyStatus { return pb.ApplyStatus(a) } + +func ParseApplyStatus(w pb.ApplyStatus) (treatment.ApplyStatus, error) { + _, _, n, _ := treatment.EnumCounts() + if w < 0 || int(w) >= n { + return 0, fmt.Errorf("unknown wire apply status %d", int32(w)) + } + return treatment.ApplyStatus(w), nil +} + +func Outcome(o treatment.Outcome) pb.Outcome { return pb.Outcome(o) } + +func ParseOutcome(w pb.Outcome) (treatment.Outcome, error) { + _, _, _, n := treatment.EnumCounts() + if w < 0 || int(w) >= n { + return 0, fmt.Errorf("unknown wire outcome %d", int32(w)) + } + return treatment.Outcome(w), nil +} + +// Settings and treatments. + +func Settings(s treatment.TCPSettings) *pb.TCPSettings { + return &pb.TCPSettings{CongestionControl: s.CongestionControl, CongestionLock: s.CongestionLock, RtoMinMs: s.RTOMinMs, InitialCongestionWindow: s.InitialCongestionWindow, InitialReceiveWindow: s.InitialReceiveWindow, QuickAck: s.QuickAck, Ecn: s.ECN} +} + +// ParseSettings copies optional fields by value so later mutation of the +// message cannot alias the domain value. +func ParseSettings(p *pb.TCPSettings) treatment.TCPSettings { + if p == nil { + return treatment.TCPSettings{} + } + return treatment.TCPSettings{CongestionControl: clonePtr(p.CongestionControl), CongestionLock: p.CongestionLock, RTOMinMs: clonePtr(p.RtoMinMs), InitialCongestionWindow: clonePtr(p.InitialCongestionWindow), InitialReceiveWindow: clonePtr(p.InitialReceiveWindow), QuickAck: clonePtr(p.QuickAck), ECN: clonePtr(p.Ecn)} +} + +func clonePtr[T any](p *T) *T { + if p == nil { + return nil + } + v := *p + return &v +} + +func Treatment(t *treatment.Treatment) *pb.Treatment { + if t == nil { + return nil + } + destination := "" + if t.Destination.IsValid() { + destination = t.Destination.String() + } + return &pb.Treatment{Id: t.ID, Revision: t.Revision, Destination: destination, Settings: Settings(t.Settings), EcnFabricVerified: t.ECNFabricVerified} +} + +// ParseTreatment leaves an unparsable destination as the zero prefix so +// treatment.ValidateTreatment reports it with the same message as any other +// bad destination. +func ParseTreatment(p *pb.Treatment) treatment.Treatment { + if p == nil { + return treatment.Treatment{} + } + t := treatment.Treatment{ID: p.Id, Revision: p.Revision, Settings: ParseSettings(p.Settings), ECNFabricVerified: p.EcnFabricVerified} + if d, err := netip.ParsePrefix(p.Destination); err == nil { + t.Destination = d + } + return t +} + +func Assignment(a *treatment.Assignment) *pb.Assignment { + if a == nil { + return nil + } + return &pb.Assignment{ExperimentId: a.ExperimentID, Treatment: Treatment(&a.Treatment), Mode: Mode(a.Mode), LeaseExpiresAt: stamp(a.LeaseExpiresAt), Predecessor: Treatment(a.Predecessor), Generation: a.Generation} +} + +func ParseAssignment(p *pb.Assignment) (treatment.Assignment, error) { + if p == nil { + return treatment.Assignment{}, errors.New("missing assignment") + } + mode, err := ParseMode(p.Mode) + if err != nil { + return treatment.Assignment{}, err + } + lease, err := parseStamp("lease_expires_at", p.LeaseExpiresAt) + if err != nil { + return treatment.Assignment{}, err + } + a := treatment.Assignment{ExperimentID: p.ExperimentId, Treatment: ParseTreatment(p.Treatment), Mode: mode, LeaseExpiresAt: lease, Generation: p.Generation} + if p.Predecessor != nil { + pred := ParseTreatment(p.Predecessor) + a.Predecessor = &pred + } + return a, nil +} + +func Desired(d *treatment.DesiredState) *pb.DesiredState { + if d == nil { + return nil + } + out := &pb.DesiredState{AgentId: d.AgentID, Revision: d.Revision, Suspended: d.Suspended, IssuedAt: stamp(d.IssuedAt)} + for i := range d.Assignments { + out.Assignments = append(out.Assignments, Assignment(&d.Assignments[i])) + } + return out +} + +func ParseDesired(p *pb.DesiredState) (*treatment.DesiredState, error) { + if p == nil { + return nil, errors.New("missing desired state") + } + issued, err := parseStamp("issued_at", p.IssuedAt) + if err != nil { + return nil, err + } + d := &treatment.DesiredState{AgentID: p.AgentId, Revision: p.Revision, Suspended: p.Suspended, IssuedAt: issued} + for _, a := range p.Assignments { + v, err := ParseAssignment(a) + if err != nil { + return nil, err + } + d.Assignments = append(d.Assignments, v) + } + return d, nil +} + +// Agent reports. + +func Capabilities(c *treatment.Capabilities) *pb.Capabilities { + return &pb.Capabilities{BootId: c.BootID, KernelRelease: c.KernelRelease, CongestionAlgorithms: append([]string(nil), c.CongestionAlgorithms...), SimpleHostRouting: c.SimpleHostRouting, ActuatorEnabled: c.ActuatorEnabled, CollectionId: c.CollectionID} +} + +func ParseCapabilities(p *pb.Capabilities) treatment.Capabilities { + if p == nil { + return treatment.Capabilities{} + } + return treatment.Capabilities{BootID: p.BootId, KernelRelease: p.KernelRelease, CongestionAlgorithms: append([]string(nil), p.CongestionAlgorithms...), SimpleHostRouting: p.SimpleHostRouting, ActuatorEnabled: p.ActuatorEnabled, CollectionID: p.CollectionId} +} + +func Record(r *treatment.ApplicationRecord) *pb.ApplicationRecord { + return &pb.ApplicationRecord{Assignment: Assignment(&r.Assignment), DesiredRevision: r.DesiredRevision, Status: ApplyStatus(r.Status), ReceivedAt: stamp(r.ReceivedAt), AttemptedAt: stamp(r.AttemptedAt), AppliedAt: stamp(r.AppliedAt), VerifiedAt: stamp(r.VerifiedAt), RemovedAt: stamp(r.RemovedAt), Error: r.Error, ExpiredLatched: r.ExpiredLatched} +} + +// ParseRecord rejects records carrying kernel route bytes or an installed +// boot ID: those are local to the host and never cross the wire. +func ParseRecord(p *pb.ApplicationRecord) (treatment.ApplicationRecord, error) { + if p == nil { + return treatment.ApplicationRecord{}, errors.New("missing application record") + } + if len(p.InstalledRoute) > 0 || p.InstalledBootId != "" { + return treatment.ApplicationRecord{}, errors.New("application record carries local kernel state") + } + a, err := ParseAssignment(p.Assignment) + if err != nil { + return treatment.ApplicationRecord{}, err + } + st, err := ParseApplyStatus(p.Status) + if err != nil { + return treatment.ApplicationRecord{}, err + } + r := treatment.ApplicationRecord{Assignment: a, DesiredRevision: p.DesiredRevision, Status: st, Error: p.Error, ExpiredLatched: p.ExpiredLatched} + for _, f := range []struct { + name string + src *timestamppb.Timestamp + dst *time.Time + }{{"received_at", p.ReceivedAt, &r.ReceivedAt}, {"attempted_at", p.AttemptedAt, &r.AttemptedAt}, {"applied_at", p.AppliedAt, &r.AppliedAt}, {"verified_at", p.VerifiedAt, &r.VerifiedAt}, {"removed_at", p.RemovedAt, &r.RemovedAt}} { + if *f.dst, err = parseStamp(f.name, f.src); err != nil { + return treatment.ApplicationRecord{}, err + } + } + return r, nil +} + +func Report(r *treatment.AgentReport) *pb.CheckInRequest { + if r == nil { + return nil + } + out := &pb.CheckInRequest{AgentId: r.AgentID, Location: r.Location, Capabilities: Capabilities(&r.Capabilities), DesiredRevision: r.DesiredRevision, LocallySuspended: r.LocallySuspended} + for i := range r.Records { + out.Records = append(out.Records, Record(&r.Records[i])) + } + return out +} + +func ParseReport(p *pb.CheckInRequest) (*treatment.AgentReport, error) { + if p == nil { + return nil, errors.New("missing check-in") + } + r := &treatment.AgentReport{AgentID: p.AgentId, Location: p.Location, Capabilities: ParseCapabilities(p.Capabilities), DesiredRevision: p.DesiredRevision, LocallySuspended: p.LocallySuspended} + for _, v := range p.Records { + rec, err := ParseRecord(v) + if err != nil { + return nil, err + } + r.Records = append(r.Records, rec) + } + return r, nil +} + +// Evidence. + +func Host(h *treatment.HostEvidence) *pb.HostEvidence { + return &pb.HostEvidence{AgentId: h.AgentID, Sockets: h.Sockets, BytesAcked: h.BytesAcked, GoodputBps: h.GoodputBps, RetransmissionRatio: h.RetransmissionRatio, RttP95Ms: h.RttP95Ms, ExposedSockets: h.ExposedSockets, CollectionHealthy: h.CollectionHealthy, UnboundSockets: h.UnboundSockets} +} + +func ParseHost(p *pb.HostEvidence) treatment.HostEvidence { + if p == nil { + return treatment.HostEvidence{} + } + return treatment.HostEvidence{AgentID: p.AgentId, Sockets: p.Sockets, BytesAcked: p.BytesAcked, GoodputBps: p.GoodputBps, RetransmissionRatio: p.RetransmissionRatio, RttP95Ms: p.RttP95Ms, ExposedSockets: p.ExposedSockets, CollectionHealthy: p.CollectionHealthy, UnboundSockets: p.UnboundSockets} +} + +func Evidence(e *treatment.Evidence) *pb.Evidence { + if e == nil { + return nil + } + out := &pb.Evidence{Id: e.ID, AnalyzedAt: stamp(e.AnalyzedAt), WindowStart: stamp(e.WindowStart), WindowEnd: stamp(e.WindowEnd), QueryVersion: e.QueryVersion, EnrichmentVersion: e.EnrichmentVersion, ArtifactSha256: e.ArtifactSHA256} + for i := range e.Hosts { + out.Hosts = append(out.Hosts, Host(&e.Hosts[i])) + } + return out +} + +// ParseEvidence maps a nil message to nil evidence; validation decides +// whether evidence was required. +func ParseEvidence(p *pb.Evidence) (*treatment.Evidence, error) { + if p == nil { + return nil, nil + } + e := &treatment.Evidence{ID: p.Id, QueryVersion: p.QueryVersion, EnrichmentVersion: p.EnrichmentVersion, ArtifactSHA256: p.ArtifactSha256} + var err error + for _, f := range []struct { + name string + src *timestamppb.Timestamp + dst *time.Time + }{{"analyzed_at", p.AnalyzedAt, &e.AnalyzedAt}, {"window_start", p.WindowStart, &e.WindowStart}, {"window_end", p.WindowEnd, &e.WindowEnd}} { + if *f.dst, err = parseStamp(f.name, f.src); err != nil { + return nil, err + } + } + for _, h := range p.Hosts { + e.Hosts = append(e.Hosts, ParseHost(h)) + } + return e, nil +} + +// Experiments. + +func Policy(p treatment.Policy) *pb.ExperimentPolicy { + return &pb.ExperimentPolicy{MinimumObservation: durationpb.New(p.MinimumObservation), MaximumPhase: durationpb.New(p.MaximumPhase), MaximumEvidenceAge: durationpb.New(p.MaximumEvidenceAge), MinimumSocketsPerHost: p.MinimumSocketsPerHost, MinimumBytesPerHost: p.MinimumBytesPerHost, MinimumTreatedHosts: p.MinimumTreatedHosts, MinimumImprovement: p.MinimumImprovement, MaximumRetransmissionIncrease: p.MaximumRetransmissionIncrease, MaximumRttIncrease: p.MaximumRTTIncrease} +} + +func ParsePolicy(p *pb.ExperimentPolicy) (treatment.Policy, error) { + if p == nil { + return treatment.Policy{}, errors.New("policy required") + } + out := treatment.Policy{MinimumSocketsPerHost: p.MinimumSocketsPerHost, MinimumBytesPerHost: p.MinimumBytesPerHost, MinimumTreatedHosts: p.MinimumTreatedHosts, MinimumImprovement: p.MinimumImprovement, MaximumRetransmissionIncrease: p.MaximumRetransmissionIncrease, MaximumRTTIncrease: p.MaximumRttIncrease} + var err error + for _, f := range []struct { + name string + src *durationpb.Duration + dst *time.Duration + }{{"minimum_observation", p.MinimumObservation, &out.MinimumObservation}, {"maximum_phase", p.MaximumPhase, &out.MaximumPhase}, {"maximum_evidence_age", p.MaximumEvidenceAge, &out.MaximumEvidenceAge}} { + if *f.dst, err = parseDuration(f.name, f.src); err != nil { + return treatment.Policy{}, err + } + } + return out, nil +} + +func Phase(p *treatment.Phase) *pb.Phase { + return &pb.Phase{TargetHosts: p.TargetHosts, IssuedAt: stamp(p.IssuedAt), ObservationStartedAt: stamp(p.ObservationStartedAt), EvaluatedAt: stamp(p.EvaluatedAt), Evidence: Evidence(p.Evidence), Outcome: Outcome(p.Outcome), Reviewer: p.Reviewer, Reason: p.Reason} +} + +func ParsePhase(p *pb.Phase) (treatment.Phase, error) { + if p == nil { + return treatment.Phase{}, errors.New("missing phase") + } + outcome, err := ParseOutcome(p.Outcome) + if err != nil { + return treatment.Phase{}, err + } + ev, err := ParseEvidence(p.Evidence) + if err != nil { + return treatment.Phase{}, err + } + out := treatment.Phase{TargetHosts: p.TargetHosts, Evidence: ev, Outcome: outcome, Reviewer: p.Reviewer, Reason: p.Reason} + for _, f := range []struct { + name string + src *timestamppb.Timestamp + dst *time.Time + }{{"issued_at", p.IssuedAt, &out.IssuedAt}, {"observation_started_at", p.ObservationStartedAt, &out.ObservationStartedAt}, {"evaluated_at", p.EvaluatedAt, &out.EvaluatedAt}} { + if *f.dst, err = parseStamp(f.name, f.src); err != nil { + return treatment.Phase{}, err + } + } + return out, nil +} + +func Experiment(e *treatment.Experiment) *pb.Experiment { + if e == nil { + return nil + } + out := &pb.Experiment{Id: e.ID, Location: e.Location, Hypothesis: e.Hypothesis, Treatment: Treatment(&e.Treatment), Policy: Policy(e.Policy), Baseline: Evidence(e.Baseline), CohortOrder: append([]string(nil), e.CohortOrder...), Status: Status(e.Status), Revision: e.Revision, ProposedAt: stamp(e.ProposedAt), LatestEvidence: Evidence(e.LatestEvidence), LatestOutcome: Outcome(e.LatestOutcome), UpdatedAt: stamp(e.UpdatedAt)} + for i := range e.Phases { + out.Phases = append(out.Phases, Phase(&e.Phases[i])) + } + return out +} + +// ParseExperiment tolerates a missing policy (the zero policy fails +// validation) so a proposal with no policy is reported by the validator +// rather than as a decoding error. +func ParseExperiment(p *pb.Experiment) (*treatment.Experiment, error) { + if p == nil { + return nil, errors.New("missing experiment") + } + status, err := ParseStatus(p.Status) + if err != nil { + return nil, err + } + outcome, err := ParseOutcome(p.LatestOutcome) + if err != nil { + return nil, err + } + e := &treatment.Experiment{ID: p.Id, Location: p.Location, Hypothesis: p.Hypothesis, Treatment: ParseTreatment(p.Treatment), CohortOrder: append([]string(nil), p.CohortOrder...), Status: status, Revision: p.Revision, LatestOutcome: outcome} + if p.Policy != nil { + if e.Policy, err = ParsePolicy(p.Policy); err != nil { + return nil, err + } + } + if e.Baseline, err = ParseEvidence(p.Baseline); err != nil { + return nil, err + } + if e.LatestEvidence, err = ParseEvidence(p.LatestEvidence); err != nil { + return nil, err + } + if e.ProposedAt, err = parseStamp("proposed_at", p.ProposedAt); err != nil { + return nil, err + } + if e.UpdatedAt, err = parseStamp("updated_at", p.UpdatedAt); err != nil { + return nil, err + } + for _, ph := range p.Phases { + v, err := ParsePhase(ph) + if err != nil { + return nil, err + } + e.Phases = append(e.Phases, v) + } + return e, nil +} + +// Validators over wire messages, for callers that keep messages at rest (the +// agent's prototext journal). Each converts and then applies the domain rule +// so there is exactly one set of bounds. + +func ValidateTreatment(p *pb.Treatment) error { + if p == nil || p.Settings == nil { + return errors.New("treatment requires id, revision and settings") + } + t := ParseTreatment(p) + return treatment.ValidateTreatment(&t) +} + +func ValidateDesired(p *pb.DesiredState) error { + if p == nil { + return errors.New("invalid desired-state header") + } + for _, a := range p.Assignments { + if a == nil || a.Treatment == nil || a.Treatment.Settings == nil { + return errors.New("treatment requires id, revision and settings") + } + } + d, err := ParseDesired(p) + if err != nil { + return err + } + return treatment.ValidateDesired(d) +} + +func ValidateEvidence(p *pb.Evidence) error { + e, err := ParseEvidence(p) + if err != nil { + return err + } + return treatment.ValidateEvidence(e) +} + +func ValidatePolicy(p *pb.ExperimentPolicy) error { + v, err := ParsePolicy(p) + if err != nil { + return err + } + return treatment.ValidatePolicy(v) +} diff --git a/pkg/treatment/wire/wire_test.go b/pkg/treatment/wire/wire_test.go new file mode 100644 index 000000000..b4f109703 --- /dev/null +++ b/pkg/treatment/wire/wire_test.go @@ -0,0 +1,337 @@ +package wire_test + +import ( + "net/netip" + "reflect" + "strings" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/internal/fixtures" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func ptr[T any](v T) *T { return &v } + +// TestEnumsMirrorWire pins the one-to-one correspondence between each domain +// enumeration and its protobuf counterpart that the checked casts rely on. +func TestEnumsMirrorWire(t *testing.T) { + statuses, modes, applies, outcomes := treatment.EnumCounts() + for _, tc := range []struct { + description string + domain int + wire map[int32]string + prefix string + name func(int32) string + }{ + {"experiment status", statuses, pb.ExperimentStatus_name, "EXPERIMENT_STATUS_", func(i int32) string { return treatment.Status(i).String() }}, + {"assignment mode", modes, pb.AssignmentMode_name, "ASSIGNMENT_MODE_", func(i int32) string { return treatment.AssignmentMode(i).String() }}, + {"apply status", applies, pb.ApplyStatus_name, "APPLY_STATUS_", func(i int32) string { return treatment.ApplyStatus(i).String() }}, + {"outcome", outcomes, pb.Outcome_name, "OUTCOME_", func(i int32) string { return treatment.Outcome(i).String() }}, + } { + if len(tc.wire) != tc.domain { + t.Errorf("%s: proto defines %d values, Go defines %d", tc.description, len(tc.wire), tc.domain) + continue + } + for i := range int32(tc.domain) { + want := tc.prefix + strings.ToUpper(tc.name(i)) + if got := tc.wire[i]; got != want { + t.Errorf("%s %d: domain name %q mirrors wire %q", tc.description, i, tc.name(i), got) + } + } + } +} + +func TestEnumParsers(t *testing.T) { + statuses, modes, applies, outcomes := treatment.EnumCounts() + for _, tc := range []struct { + name, description string + run func() (any, error) + expected any + expectError bool + }{ + {"status-running", "positive: a defined status converts", func() (any, error) { return wire.ParseStatus(pb.ExperimentStatus_EXPERIMENT_STATUS_RUNNING) }, treatment.StatusRunning, false}, + {"mode-trial", "positive: a defined mode converts", func() (any, error) { return wire.ParseMode(pb.AssignmentMode_ASSIGNMENT_MODE_TRIAL) }, treatment.ModeTrial, false}, + {"apply-failed", "positive: the last apply status converts", func() (any, error) { return wire.ParseApplyStatus(pb.ApplyStatus_APPLY_STATUS_FAILED) }, treatment.ApplyFailed, false}, + {"outcome-observing", "positive: the newest outcome converts", func() (any, error) { return wire.ParseOutcome(pb.Outcome_OUTCOME_OBSERVING) }, treatment.OutcomeObserving, false}, + {"status-zero", "boundary: the zero status is the explicit unspecified value", func() (any, error) { return wire.ParseStatus(0) }, treatment.StatusUnspecified, false}, + {"status-sentinel", "boundary: the first undefined status is rejected", func() (any, error) { return wire.ParseStatus(pb.ExperimentStatus(statuses)) }, treatment.Status(0), true}, + {"mode-sentinel", "boundary: the first undefined mode is rejected", func() (any, error) { return wire.ParseMode(pb.AssignmentMode(modes)) }, treatment.AssignmentMode(0), true}, + {"apply-sentinel", "boundary: the first undefined apply status is rejected", func() (any, error) { return wire.ParseApplyStatus(pb.ApplyStatus(applies)) }, treatment.ApplyStatus(0), true}, + {"outcome-sentinel", "boundary: the first undefined outcome is rejected", func() (any, error) { return wire.ParseOutcome(pb.Outcome(outcomes)) }, treatment.Outcome(0), true}, + {"outcome-high", "corner: a value from a newer peer is rejected with its number", func() (any, error) { return wire.ParseOutcome(255) }, treatment.Outcome(0), true}, + {"outcome-negative", "corner: negative int32 enum values are rejected", func() (any, error) { return wire.ParseOutcome(-1) }, treatment.Outcome(0), true}, + {"status-negative", "corner: negative status values are rejected", func() (any, error) { return wire.ParseStatus(-1) }, treatment.Status(0), true}, + } { + t.Run(tc.name, func(t *testing.T) { + got, err := tc.run() + if (err != nil) != tc.expectError || got != tc.expected { + t.Fatalf("%s: got %v err=%v; expected %v error=%t", tc.description, got, err, tc.expected, tc.expectError) + } + }) + } +} + +func TestDomainEnumParsers(t *testing.T) { + for _, tc := range []struct { + name, description string + run func() (any, error) + expected any + expectError bool + }{ + {"status", "positive: snake_case status parses", func() (any, error) { return treatment.ParseStatus("rolled_back") }, treatment.StatusRolledBack, false}, + {"mode", "positive: snake_case mode parses", func() (any, error) { return treatment.ParseAssignmentMode("stable") }, treatment.ModeStable, false}, + {"apply", "positive: snake_case apply status parses", func() (any, error) { return treatment.ParseApplyStatus("verified") }, treatment.ApplyVerified, false}, + {"outcome", "positive: snake_case outcome parses", func() (any, error) { return treatment.ParseOutcome("beneficial") }, treatment.OutcomeBeneficial, false}, + {"legacy-free-text", "negative: a free string from the pre-enum format is an error, not unspecified", func() (any, error) { return treatment.ParseOutcome("promoted") }, treatment.OutcomeUnspecified, true}, + {"wire-spelling", "negative: the proto spelling is not accepted by the domain parser", func() (any, error) { return treatment.ParseOutcome("OUTCOME_BENEFICIAL") }, treatment.OutcomeUnspecified, true}, + {"empty", "boundary: empty string is an error", func() (any, error) { return treatment.ParseStatus("") }, treatment.StatusUnspecified, true}, + {"unspecified-name", "corner: the unspecified name parses to the zero value", func() (any, error) { return treatment.ParseAssignmentMode("unspecified") }, treatment.ModeUnspecified, false}, + } { + t.Run(tc.name, func(t *testing.T) { + got, err := tc.run() + if (err != nil) != tc.expectError || got != tc.expected { + t.Fatalf("%s: got %v err=%v; expected %v error=%t", tc.description, got, err, tc.expected, tc.expectError) + } + }) + } +} + +func TestOutcomeClassification(t *testing.T) { + _, _, _, outcomes := treatment.EnumCounts() + for _, tc := range []struct { + description string + outcome treatment.Outcome + promotable bool + withdraws bool + renews bool + valid bool + str string + }{ + {"positive: beneficial promotes and renews", treatment.OutcomeBeneficial, true, false, true, true, "beneficial"}, + {"positive: safety-only promotes small cohorts", treatment.OutcomeSafetyOnly, true, false, true, true, "safety_only"}, + {"positive: final safety promotes the 100% phase", treatment.OutcomeFinalSafety, true, false, true, true, "final_safety"}, + {"negative: harmful withdraws and never promotes", treatment.OutcomeHarmful, false, true, true, true, "harmful"}, + {"negative: expired withdraws", treatment.OutcomeExpired, false, true, true, true, "expired"}, + {"negative: stale evidence cannot renew a lease", treatment.OutcomeStale, false, false, false, true, "stale"}, + {"negative: missing data cannot renew a lease", treatment.OutcomeInsufficientData, false, false, false, true, "insufficient_data"}, + {"boundary: zero value is valid, inert, and renews nothing it decides", treatment.OutcomeUnspecified, false, false, true, true, "unspecified"}, + {"boundary: last defined value", treatment.OutcomeObserving, false, false, true, true, "observing"}, + {"corner: sentinel is invalid and prints its number", treatment.Outcome(outcomes), false, false, true, false, "outcome(19)"}, + {"corner: stable regression is a review flag, not an automatic withdrawal", treatment.OutcomeStableRegressionReviewRequired, false, false, true, true, "stable_regression_review_required"}, + } { + o := tc.outcome + if o.Promotable() != tc.promotable || o.Withdraws() != tc.withdraws || o.RenewsLease() != tc.renews || o.Valid() != tc.valid || o.String() != tc.str { + t.Errorf("%s: promotable=%t withdraws=%t renews=%t valid=%t str=%q", tc.description, o.Promotable(), o.Withdraws(), o.RenewsLease(), o.Valid(), o.String()) + } + } +} + +func populatedExperiment(now time.Time) *treatment.Experiment { + e, v := fixtures.Experiment(now, treatment.DefaultPolicy()) + e.Treatment.Settings = treatment.TCPSettings{CongestionControl: ptr("dctcp"), CongestionLock: true, RTOMinMs: ptr[uint32](20), InitialCongestionWindow: ptr[uint32](10), InitialReceiveWindow: ptr[uint32](0), QuickAck: ptr(false), ECN: ptr(true)} + e.Treatment.ECNFabricVerified = true + e.ProposedAt = now.Add(-3 * time.Hour) + e.UpdatedAt = now + e.LatestEvidence = v + e.LatestOutcome = treatment.OutcomeBeneficial + e.Phases[0].Evidence = v.Clone() + e.Phases[0].Outcome = treatment.OutcomeBeneficial + e.Phases[0].EvaluatedAt = now + e.Phases[0].Reviewer = "op" + e.Phases[0].Reason = "ok" + e.Phases = append(e.Phases, treatment.Phase{TargetHosts: 8, IssuedAt: now}) + e.Baseline.EnrichmentVersion = "xtcp-schema-2" + e.Baseline.Hosts[0].CollectionHealthy = false + return e +} + +func populatedReport(now time.Time) *treatment.AgentReport { + d := fixtures.Desired(now) + pred := d.Assignments[0].Treatment + pred.ID = "old" + d.Assignments[0].Predecessor = &pred + return &treatment.AgentReport{AgentID: "host-1", Location: "dc1", Capabilities: treatment.Capabilities{BootID: "b", CollectionID: fixtures.CollectionID, KernelRelease: "6.12", CongestionAlgorithms: []string{"cubic", "bbr"}, SimpleHostRouting: true, ActuatorEnabled: true}, DesiredRevision: 7, LocallySuspended: true, Records: []treatment.ApplicationRecord{{Assignment: d.Assignments[0], DesiredRevision: 7, Status: treatment.ApplyVerified, ReceivedAt: now, AttemptedAt: now.Add(time.Second), AppliedAt: now.Add(2 * time.Second), VerifiedAt: now.Add(3 * time.Second), ExpiredLatched: false}, {Assignment: treatment.Assignment{ExperimentID: "gone", Treatment: fixtures.Treatment(), Mode: treatment.ModeRetired, Generation: 3}, Status: treatment.ApplyRemoved, RemovedAt: now, Error: "x", ExpiredLatched: true}}} +} + +// TestRoundTrip converts domain → wire → domain and requires deep equality, +// and wire → domain → wire and requires proto equality, so neither direction +// drops or smears a field. +func TestRoundTrip(t *testing.T) { + now := time.Unix(1700000000, 123456789).UTC() + for _, tc := range []struct { + name, description string + run func(t *testing.T) + }{ + {"experiment", "positive: a populated experiment with phases, evidence and every optional setting survives", func(t *testing.T) { + in := populatedExperiment(now) + w := wire.Experiment(in) + out, err := wire.ParseExperiment(w) + if err != nil || !reflect.DeepEqual(in, out) { + t.Fatalf("round trip differs: %v\nin %+v\nout %+v", err, in, out) + } + if again := wire.Experiment(out); !proto.Equal(w, again) { + t.Fatal("wire form differs after a second trip") + } + }}, + {"report", "positive: a check-in with records, predecessor and every timestamp survives", func(t *testing.T) { + in := populatedReport(now) + w := wire.Report(in) + out, err := wire.ParseReport(w) + if err != nil || !reflect.DeepEqual(in, out) { + t.Fatalf("round trip differs: %v\nin %+v\nout %+v", err, in, out) + } + if again := wire.Report(out); !proto.Equal(w, again) { + t.Fatal("wire form differs after a second trip") + } + }}, + {"desired", "positive: desired state survives", func(t *testing.T) { + in := fixtures.Desired(now) + out, err := wire.ParseDesired(wire.Desired(in)) + if err != nil || !reflect.DeepEqual(in, out) { + t.Fatalf("round trip differs: %v", err) + } + }}, + {"unset-optional", "boundary: nil optional settings and zero timestamps stay unset rather than becoming zero values", func(t *testing.T) { + in := fixtures.Desired(now) + in.Assignments[0].Mode = treatment.ModeStable + in.Assignments[0].LeaseExpiresAt = time.Time{} + w := wire.Desired(in) + if w.Assignments[0].LeaseExpiresAt != nil { + t.Fatal("zero lease became a timestamp") + } + s := w.Assignments[0].Treatment.Settings + if s.RtoMinMs != nil || s.InitialCongestionWindow != nil || s.InitialReceiveWindow != nil || s.QuickAck != nil || s.Ecn != nil { + t.Fatal("unset settings became zero values on the wire") + } + out, err := wire.ParseDesired(w) + if err != nil || !reflect.DeepEqual(in, out) { + t.Fatalf("round trip differs: %v", err) + } + }}, + {"explicit-zero", "boundary: an explicit zero window and false flag are preserved as set", func(t *testing.T) { + s := treatment.TCPSettings{InitialReceiveWindow: ptr[uint32](0), QuickAck: ptr(false)} + out := wire.ParseSettings(wire.Settings(s)) + if out.InitialReceiveWindow == nil || *out.InitialReceiveWindow != 0 || out.QuickAck == nil || *out.QuickAck { + t.Fatalf("explicit zeros lost: %+v", out) + } + }}, + {"empty-collections", "boundary: an experiment with no phases, cohort or evidence survives", func(t *testing.T) { + in := &treatment.Experiment{ID: "e", Location: "dc1", Treatment: fixtures.Treatment(), Policy: treatment.DefaultPolicy(), Status: treatment.StatusProposed, Revision: 1} + out, err := wire.ParseExperiment(wire.Experiment(in)) + if err != nil || !reflect.DeepEqual(in, out) { + t.Fatalf("round trip differs: %v\nin %+v\nout %+v", err, in, out) + } + }}, + {"alias-free", "corner: parsed optional settings do not alias the message", func(t *testing.T) { + w := wire.Settings(treatment.TCPSettings{RTOMinMs: ptr[uint32](5)}) + out := wire.ParseSettings(w) + *w.RtoMinMs = 9 + if *out.RTOMinMs != 5 { + t.Fatal("domain value aliases the message") + } + }}, + {"bad-destination", "corner: an unparsable destination becomes the zero prefix and fails validation, not decoding", func(t *testing.T) { + tr := wire.ParseTreatment(&pb.Treatment{Id: "t", Revision: 1, Destination: "nonsense", Settings: &pb.TCPSettings{CongestionControl: ptr("cubic")}}) + if tr.Destination != (netip.Prefix{}) { + t.Fatal("destination should be unset") + } + if err := treatment.ValidateTreatment(&tr); err == nil || !strings.Contains(err.Error(), "canonical unicast") { + t.Fatalf("expected destination error, got %v", err) + } + }}, + } { + t.Run(tc.name, tc.run) + } +} + +func TestParseRejections(t *testing.T) { + now := time.Unix(1700000000, 0) + e, _ := fixtures.ExperimentWire(now, treatment.DefaultPolicy()) + for _, tc := range []struct { + name, description string + run func() error + expected string + }{ + {"invalid-timestamp", "negative: a malformed timestamp is a decoding error", func() error { + m := proto.Clone(e).(*pb.Experiment) + m.ProposedAt = ×tamppb.Timestamp{Nanos: 1e9} + _, err := wire.ParseExperiment(m) + return err + }, "proposed_at"}, + {"invalid-phase-outcome", "negative: an unknown phase outcome is rejected", func() error { + m := proto.Clone(e).(*pb.Experiment) + m.Phases[0].Outcome = 250 + _, err := wire.ParseExperiment(m) + return err + }, "unknown wire outcome 250"}, + {"unknown-mode", "negative: an unknown assignment mode is rejected", func() error { + d := fixtures.DesiredWire(now) + d.Assignments[0].Mode = 77 + _, err := wire.ParseDesired(d) + return err + }, "unknown wire assignment mode 77"}, + {"kernel-bytes", "negative: a record carrying kernel route bytes is rejected", func() error { + r := &pb.CheckInRequest{AgentId: "a", Location: "l", Records: []*pb.ApplicationRecord{{Assignment: fixtures.DesiredWire(now).Assignments[0], InstalledRoute: []byte{1}}}} + _, err := wire.ParseReport(r) + return err + }, "local kernel state"}, + {"nil-experiment", "boundary: nil is a decoding error", func() error { _, err := wire.ParseExperiment(nil); return err }, "missing experiment"}, + {"nil-policy", "corner: a missing policy decodes to the zero policy and is left to validation", func() error { + m := proto.Clone(e).(*pb.Experiment) + m.Policy = nil + out, err := wire.ParseExperiment(m) + if err != nil { + return err + } + return treatment.ValidatePolicy(out.Policy) + }, "policy duration"}, + } { + t.Run(tc.name, func(t *testing.T) { + err := tc.run() + if err == nil || !strings.Contains(err.Error(), tc.expected) { + t.Fatalf("%s: expected error containing %q, got %v", tc.description, tc.expected, err) + } + }) + } +} + +func TestWireValidatorsMatchDomain(t *testing.T) { + now := time.Unix(1700000000, 0) + for _, tc := range []struct { + name, description string + err error + expected string + }{ + {"desired-valid", "positive: the fixture passes the wire validator", wire.ValidateDesired(fixtures.DesiredWire(now)), ""}, + {"treatment-valid", "positive: the fixture treatment passes", wire.ValidateTreatment(fixtures.DesiredWire(now).Assignments[0].Treatment), ""}, + {"evidence-valid", "positive: fixture evidence passes", func() error { + _, v := fixtures.ExperimentWire(now, treatment.DefaultPolicy()) + return wire.ValidateEvidence(v) + }(), ""}, + {"policy-valid", "positive: the default policy passes", wire.ValidatePolicy(wire.Policy(treatment.DefaultPolicy())), ""}, + {"treatment-nil-settings", "negative: nil settings report the same message as the old validator", wire.ValidateTreatment(&pb.Treatment{Id: "t", Revision: 1, Destination: "192.0.2.1/32"}), "requires"}, + {"desired-nil-assignment", "negative: a nil assignment is rejected before conversion", wire.ValidateDesired(&pb.DesiredState{AgentId: "a", Revision: 1, IssuedAt: timestamppb.Now(), Assignments: []*pb.Assignment{nil}}), "requires"}, + {"policy-nil", "boundary: nil policy is rejected", wire.ValidatePolicy(nil), "policy required"}, + {"evidence-nil", "boundary: nil evidence is rejected", wire.ValidateEvidence(nil), "interval"}, + {"desired-bad-lease", "corner: an invalid lease timestamp is a decoding error", func() error { + d := fixtures.DesiredWire(now) + d.Assignments[0].LeaseExpiresAt = ×tamppb.Timestamp{Nanos: -1} + return wire.ValidateDesired(d) + }(), "lease_expires_at"}, + } { + t.Run(tc.name, func(t *testing.T) { + if tc.expected == "" { + if tc.err != nil { + t.Fatalf("%s: expected acceptance, got %v", tc.description, tc.err) + } + } else if tc.err == nil || !strings.Contains(tc.err.Error(), tc.expected) { + t.Fatalf("%s: expected error containing %q, got %v", tc.description, tc.expected, tc.err) + } + }) + } +} diff --git a/pkg/xtcp/deserialize.go b/pkg/xtcp/deserialize.go index d711d3b10..2838f5282 100644 --- a/pkg/xtcp/deserialize.go +++ b/pkg/xtcp/deserialize.go @@ -226,6 +226,9 @@ func (x *XTCP) processInetDiagRecord( // plus per-namespace container labels (Docker Engine API, keyed by netns // inode) and opt-in nsid. All O(1) and no-op when their enricher is off. x.applyEnrichment(xtcpRecord) + if x.treatmentStamp != nil { + x.treatmentStamp(xtcpRecord) + } // Fallback container resolution from the socket's cgroup id (populated by // DeserializeAttributes above). Only runs when the Docker index didn't diff --git a/pkg/xtcp/destinations_s3parquet.go b/pkg/xtcp/destinations_s3parquet.go index 39825dbb8..55fc7c735 100644 --- a/pkg/xtcp/destinations_s3parquet.go +++ b/pkg/xtcp/destinations_s3parquet.go @@ -828,8 +828,16 @@ func rowFromProto(r *xtcp_flat_record.XtcpFlatRecord) ParquetRow { TimestampNs: r.TimestampNs, - Hostname: r.Hostname, - Location: r.Location, + Hostname: r.Hostname, + Location: r.Location, + AgentId: r.AgentId, + HostBootId: r.HostBootId, + CollectionId: r.CollectionId, + TreatmentStateRevision: r.TreatmentStateRevision, + TreatmentAssignmentId: r.TreatmentAssignmentId, + TreatmentGeneration: r.TreatmentGeneration, + TreatmentAppliedTimestampNs: r.TreatmentAppliedTimestampNs, + TreatmentAlgorithmExposed: r.TreatmentAlgorithmExposed, Netns: r.Netns, NetnsInode: r.NetnsInode, diff --git a/pkg/xtcp/destinations_s3parquet_rowfromproto_test.go b/pkg/xtcp/destinations_s3parquet_rowfromproto_test.go index b1aec6fca..d162002dc 100644 --- a/pkg/xtcp/destinations_s3parquet_rowfromproto_test.go +++ b/pkg/xtcp/destinations_s3parquet_rowfromproto_test.go @@ -47,6 +47,8 @@ var rowFromProtoSkip = map[string]bool{"EventDate": true} func sentinelFor(t *testing.T, typ reflect.Type, seq int) reflect.Value { t.Helper() switch typ.Kind() { + case reflect.Bool: + return reflect.ValueOf(true).Convert(typ) case reflect.String: return reflect.ValueOf(fmt.Sprintf("v%d", seq)).Convert(typ) case reflect.Uint32, reflect.Uint64: @@ -71,6 +73,8 @@ func sentinelFor(t *testing.T, typ reflect.Type, seq int) reflect.Value { func extremeFor(t *testing.T, typ reflect.Type, low bool) reflect.Value { t.Helper() switch typ.Kind() { + case reflect.Bool: + return reflect.ValueOf(!low).Convert(typ) case reflect.String: if low { return reflect.ValueOf("").Convert(typ) diff --git a/pkg/xtcp/destinations_s3parquet_schema.go b/pkg/xtcp/destinations_s3parquet_schema.go index 69cecdfda..cbf6cd543 100644 --- a/pkg/xtcp/destinations_s3parquet_schema.go +++ b/pkg/xtcp/destinations_s3parquet_schema.go @@ -37,8 +37,16 @@ type ParquetRow struct { EventDate string `parquet:"event_date,zstd"` // ---- metadata: host identity (20s) - Hostname string `parquet:"hostname,zstd"` - Location string `parquet:"location,zstd"` + Hostname string `parquet:"hostname,zstd"` + Location string `parquet:"location,zstd"` + AgentId string `parquet:"agent_id,zstd"` + HostBootId string `parquet:"host_boot_id,zstd"` + CollectionId string `parquet:"collection_id,zstd"` + TreatmentStateRevision uint64 `parquet:"treatment_state_revision,snappy"` + TreatmentAssignmentId string `parquet:"treatment_assignment_id,zstd"` + TreatmentGeneration uint64 `parquet:"treatment_generation,snappy"` + TreatmentAppliedTimestampNs int64 `parquet:"treatment_applied_timestamp_ns,snappy"` + TreatmentAlgorithmExposed bool `parquet:"treatment_algorithm_exposed"` // ---- metadata: network namespace identity (30s) Netns string `parquet:"netns,zstd"` diff --git a/pkg/xtcp/treatment.go b/pkg/xtcp/treatment.go new file mode 100644 index 000000000..f4a51620d --- /dev/null +++ b/pkg/xtcp/treatment.go @@ -0,0 +1,9 @@ +package xtcp + +import "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" + +// SetTreatmentStamper attaches the optional controller provenance hook before +// RunWithPoller. The hook must be concurrency-safe and must not block on I/O. +func (x *XTCP) SetTreatmentStamper(fn func(*xtcp_flat_record.XtcpFlatRecord)) { + x.treatmentStamp = fn +} diff --git a/pkg/xtcp/xtcp.go b/pkg/xtcp/xtcp.go index f6b61e774..f057a3356 100644 --- a/pkg/xtcp/xtcp.go +++ b/pkg/xtcp/xtcp.go @@ -37,8 +37,9 @@ const ( ) type XTCP struct { - ctx context.Context - cancel context.CancelFunc + treatmentStamp func(*xtcp_flat_record.XtcpFlatRecord) + ctx context.Context + cancel context.CancelFunc config *xtcp_config.XtcpConfig diff --git a/pkg/xtcpnl/xtcp_writer_test.go b/pkg/xtcpnl/xtcp_writer_test.go index 468b9491f..d53a444da 100644 --- a/pkg/xtcpnl/xtcp_writer_test.go +++ b/pkg/xtcpnl/xtcp_writer_test.go @@ -129,16 +129,14 @@ func TestDeserializeXXXXTCP(t *testing.T) { }, }, { - // CongInfo writes only on a recognized "cub" / "bbr" / etc. - // prefix. Garbage 0x01 bytes fall through the switch with - // no observable side effect, which is the intended kernel- - // compatibility behavior. We only assert the parse succeeds. + // Names absent from our enum are retained as raw strings. name: "CongInfo", min: CongInfoSizeCst, parse: DeserializeCongInfoXTCP, verify: func(t *testing.T, x *xtcp_flat_record.XtcpFlatRecord) { - // No assertion — successful parse with unknown algorithm - // leaves all fields at zero, which is correct. + if x.InetDiagCong == "" || x.InetDiagCongEnum != xtcp_flat_record.XtcpFlatRecord_CONGESTION_ALGORITHM_UNSPECIFIED { + t.Error("unknown algorithm name must be retained without inventing an enum") + } }, }, { diff --git a/pkg/xtcpnl/xtcpnl_inet_diag_conginfo.go b/pkg/xtcpnl/xtcpnl_inet_diag_conginfo.go index da80b85c5..4711c2f3d 100644 --- a/pkg/xtcpnl/xtcpnl_inet_diag_conginfo.go +++ b/pkg/xtcpnl/xtcpnl_inet_diag_conginfo.go @@ -1,6 +1,7 @@ package xtcpnl import ( + "bytes" "errors" "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" @@ -81,6 +82,16 @@ func DeserializeCongInfoXTCP(data []byte, x *xtcp_flat_record.XtcpFlatRecord) (e return ErrCongInfoSmall } + // Preserve the actual kernel name, including algorithms absent from our + // enum (for example Reno). Controller exposure is based on this field. + // Copy out of the reused netlink buffer and exclude the NUL terminator. + name := data + if end := bytes.IndexByte(name, 0); end >= 0 { + name = name[:end] + } + x.InetDiagCong = string(name) + x.InetDiagCongEnum = xtcp_flat_record.XtcpFlatRecord_CONGESTION_ALGORITHM_UNSPECIFIED + // Match on the first 3 bytes — the kernel attribute is a null-terminated // algorithm name like "cubic", "bbr", "dctcp", "vegas". Comparing data[0:4] // against 3-char strings would never match, so we use the 3-char prefix. diff --git a/pkg/xtcpnl/xtcpnl_inet_diag_conginfo_test.go b/pkg/xtcpnl/xtcpnl_inet_diag_conginfo_test.go index f697b8845..5b19216a3 100644 --- a/pkg/xtcpnl/xtcpnl_inet_diag_conginfo_test.go +++ b/pkg/xtcpnl/xtcpnl_inet_diag_conginfo_test.go @@ -19,8 +19,37 @@ import ( "reflect" "strings" "testing" + + "github.com/randomizedcoder/xtcp2/gen/go/xtcp_flat_record" ) +func TestDeserializeCongInfoXTCPName(t *testing.T) { + // Reuse the same record to catch a stale enum after an unknown algorithm. + record := new(xtcp_flat_record.XtcpFlatRecord) + for _, tc := range []struct { + wire string + name string + algorithm xtcp_flat_record.XtcpFlatRecord_CongestionAlgorithm + }{ + {"cubic\x00\x00\x00", "cubic", xtcp_flat_record.XtcpFlatRecord_CONGESTION_ALGORITHM_CUBIC}, + {"reno\x00", "reno", xtcp_flat_record.XtcpFlatRecord_CONGESTION_ALGORITHM_UNSPECIFIED}, + {"bbr\x00", "bbr", xtcp_flat_record.XtcpFlatRecord_CONGESTION_ALGORITHM_BBR1}, + {"bbr2\x00", "bbr2", xtcp_flat_record.XtcpFlatRecord_CONGESTION_ALGORITHM_BBR2}, + {"bbr3\x00", "bbr3", xtcp_flat_record.XtcpFlatRecord_CONGESTION_ALGORITHM_BBR3}, + } { + t.Run(tc.name, func(t *testing.T) { + data := []byte(tc.wire) + if err := DeserializeCongInfoXTCP(data, record); err != nil { + t.Fatal(err) + } + data[0] = 'x' // The netlink receive buffer is reused after decoding. + if record.InetDiagCong != tc.name || record.InetDiagCongEnum != tc.algorithm { + t.Fatalf("algorithm = %q/%v, want %q/%v", record.InetDiagCong, record.InetDiagCongEnum, tc.name, tc.algorithm) + } + }) + } +} + type DeserializeCongInfoTest struct { description string filename string diff --git a/pkg/xtcpnl/xtcpnl_rule_write.go b/pkg/xtcpnl/xtcpnl_rule_write.go new file mode 100644 index 000000000..3007198b5 --- /dev/null +++ b/pkg/xtcpnl/xtcpnl_rule_write.go @@ -0,0 +1,129 @@ +package xtcpnl + +import ( + "errors" + + "golang.org/x/sys/unix" +) + +// This file encodes the request `ip rule add/delete` sends: the fib_rule_hdr +// and the FRA_* attributes. It is RouteWrite's counterpart for the routing +// policy database, so a library caller builds a rule from fields rather than +// from argv (internal/goip/actuate is the first; the CLI path in +// internal/goip/rule_write.go keeps parsing argv in iprule_modify's order). +// +// It encodes; it does not parse argv. iprule_modify (ip/iprule.c) writes each +// attribute as its keyword is read, so the order is argv order and that is +// internal/goip's business. A RuleWrite carries the attributes as an ordered +// list and this file writes them as given, after the one attribute the header +// forces: fib_rule_hdr.table is eight bits, so a table id past 255 travels as +// RT_TABLE_UNSPEC in the header and the real id in FRA_TABLE, which is +// written first. The argv `table N` keyword does the same at its own +// position, so `ip rule add table N …` and a RuleWrite with Table N agree +// byte for byte. +// +// Nothing here sends. BuildRuleWriteRequest goes through BuildWriteRequest, +// and goip writes the result to a file (link-write-path.md, decision 5) or, +// for the one opted-in actuator, to an acknowledged socket. + +// ruleWriteBufCst is iprule_modify's char buf[1024], the room after the +// nlmsghdr and fib_rule_hdr that addattr_l is given as maxlen. +const ruleWriteBufCst = 1024 + +// ErrRuleWriteType is a RuleWrite whose MsgType is not RTM_NEWRULE or +// RTM_DELRULE. BuildWriteRequest would admit route and link types too; a +// rule write must not carry one. +var ErrRuleWriteType = errors.New("xtcpnl: a rule write is RTM_NEWRULE or RTM_DELRULE") + +// RuleAttr is one FRA_* attribute of a rule write, payload already encoded. +type RuleAttr struct { + Type uint16 + Payload []byte +} + +// RuleAttrU8 is addattr8: FRA_IP_PROTO, FRA_PROTOCOL, FRA_L3MDEV. +func RuleAttrU8(atype uint16, v uint8) RuleAttr { + return RuleAttr{Type: atype, Payload: []byte{v}} +} + +// RuleAttrU32 is addattr32: FRA_PRIORITY, FRA_FWMARK, FRA_FWMASK, FRA_GOTO, +// FRA_SUPPRESS_PREFIXLEN. FRA_TABLE is RuleWrite.Table's business. +func RuleAttrU32(atype uint16, v uint32) RuleAttr { + return RuleAttr{Type: atype, Payload: RouteAttrU32(atype, v).Payload} +} + +// RuleAttrName is addattr_l of a NUL-terminated interface name: FRA_IIFNAME +// and FRA_OIFNAME. iprule_modify sends strlen+1, so the NUL is counted in +// rta_len and the padding after it is not. +func RuleAttrName(atype uint16, name string) RuleAttr { + return RuleAttr{Type: atype, Payload: append([]byte(name), 0)} +} + +// RuleAttrBytes is addattr_l of raw bytes: FRA_DST and FRA_SRC (the address +// bytes), FRA_UID_RANGE and the port ranges (their structs). +func RuleAttrBytes(atype uint16, b []byte) RuleAttr { + return RuleAttr{Type: atype, Payload: b} +} + +// RuleWrite is one rule write as iprule_modify assembles it. +type RuleWrite struct { + // MsgType is RTM_NEWRULE or RTM_DELRULE. + MsgType uint16 + // Flags are the NLM_F_* bits besides NLM_F_REQUEST: NLM_F_CREATE| + // NLM_F_EXCL for add, nothing for delete, and NLM_F_ACK, which + // rtnl_talk adds. + Flags uint16 + + // The struct fib_rule_hdr, field for field, except Table. + Family uint8 + DstLen uint8 + SrcLen uint8 + Tos uint8 + // Action is FR_ACT_TO_TBL for an add and FR_ACT_UNSPEC for a delete + // (iprule_modify sets it from the verb before the loop). + Action uint8 + // FrhFlags is fib_rule_hdr.flags: FIB_RULE_INVERT for `not`. + FrhFlags uint32 + + // Table is the routing table id. Zero sends none (a delete that does + // not select on table); 1..255 is the header byte; above that the + // header carries RT_TABLE_UNSPEC and FRA_TABLE carries the id. + Table uint32 + + // Attrs are the selectors in wire order, after FRA_TABLE when there + // is one. + Attrs []RuleAttr +} + +// EncodeFibRuleHdr lays out a struct fib_rule_hdr: family, dst_len, +// src_len, tos, table, two reserved bytes, action, flags. +func EncodeFibRuleHdr(w *RuleWrite) []byte { + table := uint8(unix.RT_TABLE_UNSPEC) + if w.Table < 256 { + table = uint8(w.Table) + } + b := make([]byte, 0, FibRuleHdrSizeCst) + b = append(b, w.Family, w.DstLen, w.SrcLen, w.Tos, table, 0, 0, w.Action) + return append(b, byte(w.FrhFlags), byte(w.FrhFlags>>8), byte(w.FrhFlags>>16), byte(w.FrhFlags>>24)) +} + +// BuildRuleWriteRequest lays out w: the fib_rule_hdr, FRA_TABLE when the id +// does not fit the header, then w.Attrs in order. +func BuildRuleWriteRequest(w RuleWrite, seq uint32) ([]byte, error) { + if w.MsgType != uint16(unix.RTM_NEWRULE) && w.MsgType != uint16(unix.RTM_DELRULE) { + return nil, ErrRuleWriteType + } + var raw [ruleWriteBufCst]byte + ab := NewAttrBuilder(raw[:]) + if w.Table >= 256 { + if err := ab.PutU32(uint16(unix.FRA_TABLE), w.Table); err != nil { + return nil, err + } + } + for _, a := range w.Attrs { + if err := ab.PutBytes(a.Type, a.Payload); err != nil { + return nil, err + } + } + return BuildWriteRequest(w.MsgType, w.Flags, seq, EncodeFibRuleHdr(&w), ab.Bytes()) +} diff --git a/pkg/xtcpnl/xtcpnl_rule_write_test.go b/pkg/xtcpnl/xtcpnl_rule_write_test.go new file mode 100644 index 000000000..7ea66a12f --- /dev/null +++ b/pkg/xtcpnl/xtcpnl_rule_write_test.go @@ -0,0 +1,175 @@ +package xtcpnl + +import ( + "bytes" + "errors" + "reflect" + "testing" + + "golang.org/x/sys/unix" +) + +// This file tests xtcpnl_rule_write.go, the typed counterpart of the argv +// path in internal/goip/rule_write.go. The hex is written out by hand from +// the layout rules of iprule_modify and lib/libnetlink.c, not produced by +// any encoder; ParseRule is the independent reader for the rest. The +// typed-equals-argv claim is internal/goip's test +// (TestRuleWriteTypedMatchesArgv), where both encoders are visible. + +// TestBuildRuleWriteRequest is the fib_rule_hdr, FRA_TABLE's placement and +// the plain attributes. +// +// go test ./pkg/xtcpnl/ -run TestBuildRuleWriteRequest +func TestBuildRuleWriteRequest(t *testing.T) { + const addAck = uint16(unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK) + v6dst := []byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + treatment := func(msgType, flags uint16, family, action uint8) RuleWrite { + return RuleWrite{ + MsgType: msgType, Flags: flags, Family: family, Action: action, Table: 10002, + Attrs: []RuleAttr{ + RuleAttrU32(unix.FRA_PRIORITY, 30000), RuleAttrU8(unix.FRA_IP_PROTO, unix.IPPROTO_TCP), + RuleAttrName(unix.FRA_IIFNAME, "lo"), RuleAttrU8(unix.FRA_PROTOCOL, 242), + }, + } + } + // Bytes 16: of the add below, so the delete and family rows can share it. + treatmentBody := `02000000 00000001 00000000 + 0800 0f00 12270000 + 0800 0600 30750000 + 0500 1600 06000000 + 0700 0300 6c6f0000 + 0500 1500 f2000000` + + tests := []struct { + description string + w RuleWrite + expected []byte + wantErr error + }{ + { + description: "positive: the treatment rule, `add table 10002 priority 30000 ipproto tcp iif lo protocol 242`, is FRA_TABLE first and 68 bytes", + w: treatment(unix.RTM_NEWRULE, addAck, unix.AF_INET, unix.FR_ACT_TO_TBL), + expected: hexBytes(t, `44000000 2000 0506 01000000 00000000 `+treatmentBody), + }, + { + description: "positive: the same rule's delete is RTM_DELRULE, NLM_F_ACK alone and FR_ACT_UNSPEC, selectors kept", + w: treatment(unix.RTM_DELRULE, unix.NLM_F_ACK, unix.AF_INET, unix.FR_ACT_UNSPEC), + expected: hexBytes(t, `44000000 2100 0500 01000000 00000000 + 02000000 00000000 00000000 + 0800 0f00 12270000 + 0800 0600 30750000 + 0500 1600 06000000 + 0700 0300 6c6f0000 + 0500 1500 f2000000`), + }, + { + description: "positive: `add to 2001:db8::1/128 table 10002` is AF_INET6, dst_len 128 and a 16-byte FRA_DST after FRA_TABLE", + w: RuleWrite{ + MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET6, DstLen: 128, Action: unix.FR_ACT_TO_TBL, Table: 10002, + Attrs: []RuleAttr{RuleAttrBytes(unix.FRA_DST, v6dst)}, + }, + expected: hexBytes(t, `38000000 2000 0506 01000000 00000000 + 0a800000 00000001 00000000 + 0800 0f00 12270000 + 1400 0100 20010db8 00000000 00000000 00000001`), + }, + { + description: "boundary: table 255 is the last id the header byte holds; no FRA_TABLE", + w: RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, Table: 255}, + expected: hexBytes(t, `1c000000 2000 0506 01000000 00000000 02000000 ff000001 00000000`), + }, + { + description: "boundary: table 256 is the first id that moves to FRA_TABLE, the header byte RT_TABLE_UNSPEC", + w: RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, Table: 256}, + expected: hexBytes(t, `24000000 2000 0506 01000000 00000000 02000000 00000001 00000000 0800 0f00 00010000`), + }, + { + description: "boundary: table 0 sends neither byte nor attribute, as `ip rule del pref 7` does", + w: RuleWrite{MsgType: unix.RTM_DELRULE, Flags: unix.NLM_F_ACK, Family: unix.AF_INET, Attrs: []RuleAttr{RuleAttrU32(unix.FRA_PRIORITY, 7)}}, + expected: hexBytes(t, `24000000 2100 0500 01000000 00000000 02000000 00000000 00000000 0800 0600 07000000`), + }, + { + description: "corner: `not` is FIB_RULE_INVERT in fib_rule_hdr.flags, little-endian", + w: RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, Table: 254, FrhFlags: unix.FIB_RULE_INVERT}, + expected: hexBytes(t, `1c000000 2000 0506 01000000 00000000 02000000 fe000001 02000000`), + }, + { + description: "negative: RTM_NEWROUTE is admitted by BuildWriteRequest but is not a rule write", + w: RuleWrite{MsgType: unix.RTM_NEWROUTE, Flags: addAck, Family: unix.AF_INET, Table: 10002}, + wantErr: ErrRuleWriteType, + }, + { + description: "negative: an attribute past iprule_modify's 1024-byte buffer is refused rather than truncated", + w: RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, Table: 254, + Attrs: []RuleAttr{RuleAttrBytes(unix.FRA_DST, make([]byte, ruleWriteBufCst))}}, + wantErr: ErrAttrNoSpace, + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + got, err := BuildRuleWriteRequest(tc.w, 1) + if tc.wantErr != nil { + if !errors.Is(err, tc.wantErr) { + t.Fatalf("%s: err=%v, want %v", tc.description, err, tc.wantErr) + } + return + } + if err != nil { + t.Fatalf("%s: %v", tc.description, err) + } + if !bytes.Equal(got, tc.expected) { + t.Fatalf("%s:\n got %x\nwant %x", tc.description, got, tc.expected) + } + }) + } +} + +// TestRuleWriteReadsBack closes the loop through ParseRule: what the builder +// writes, the decoder reports, including the table id above 255 that the +// header byte cannot hold. +// +// go test ./pkg/xtcpnl/ -run TestRuleWriteReadsBack +func TestRuleWriteReadsBack(t *testing.T) { + const addAck = uint16(unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK) + tests := []struct { + description string + w RuleWrite + expected RuleInfo + }{ + { + description: "positive: the treatment rule reads back as priority 30000, table 10002, tcp from lo, protocol 242", + w: RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, Table: 10002, + Attrs: []RuleAttr{RuleAttrU32(unix.FRA_PRIORITY, 30000), RuleAttrU8(unix.FRA_IP_PROTO, unix.IPPROTO_TCP), RuleAttrName(unix.FRA_IIFNAME, "lo"), RuleAttrU8(unix.FRA_PROTOCOL, 242)}}, + expected: RuleInfo{Family: unix.AF_INET, Action: unix.FR_ACT_TO_TBL, RawTable: unix.RT_TABLE_UNSPEC, Table: 10002, Priority: 30000, HasPriority: true, + IifName: "lo", HasIifName: true, IPProto: unix.IPPROTO_TCP, HasIPProto: true, Protocol: 242, HasProtocol: true}, + }, + { + description: "boundary: a header-byte table reads back from the byte, FRA_TABLE absent", + w: RuleWrite{MsgType: unix.RTM_NEWRULE, Flags: addAck, Family: unix.AF_INET6, Action: unix.FR_ACT_TO_TBL, Table: 200}, + expected: RuleInfo{Family: unix.AF_INET6, Action: unix.FR_ACT_TO_TBL, RawTable: 200, Table: 200}, + }, + { + description: "corner: a /128 destination keeps its full length and all sixteen bytes", + w: RuleWrite{MsgType: unix.RTM_DELRULE, Flags: unix.NLM_F_ACK, Family: unix.AF_INET6, DstLen: 128, + Attrs: []RuleAttr{RuleAttrBytes(unix.FRA_DST, bytes.Repeat([]byte{0xab}, 16))}}, + expected: RuleInfo{Family: unix.AF_INET6, DstLen: 128, Dst: bytes.Repeat([]byte{0xab}, 16)}, + }, + } + for _, tc := range tests { + t.Run(tc.description, func(t *testing.T) { + msg, err := BuildRuleWriteRequest(tc.w, 1) + if err != nil { + t.Fatalf("%s: %v", tc.description, err) + } + got, err := ParseRule(msg[NlMsgHdrSizeCst:]) + if err != nil { + t.Fatalf("%s: %v", tc.description, err) + } + if !ruleInfoEqual(got, tc.expected) { + t.Fatalf("%s:\n got %+v\nwant %+v", tc.description, got, tc.expected) + } + }) + } +} + +func ruleInfoEqual(a, b RuleInfo) bool { return reflect.DeepEqual(a, b) } diff --git a/proto/xtcp_flat_record/v1/xtcp_flat_record.proto b/proto/xtcp_flat_record/v1/xtcp_flat_record.proto index 9a0f67c8a..9894b9f0f 100644 --- a/proto/xtcp_flat_record/v1/xtcp_flat_record.proto +++ b/proto/xtcp_flat_record/v1/xtcp_flat_record.proto @@ -88,7 +88,7 @@ message XtcpFlatRecord { "class_id", "sock_opt", "c_group"; // ==== metadata (1-299) ===================================================== - // Free: 3-9, 11-19, 22-29, 33-39, 44-49, 52-59, 63-99, 108-119, 125-199, + // Free: 3-9, 11-19, 33-39, 44-49, 52-59, 63-99, 108-119, 125-199, // 208-219, 225-299. Uplink slots are fixed at two (100s, 200s); a third slot // would take 250-274, NOT 300 (that is the enrichment block). @@ -117,6 +117,17 @@ message XtcpFlatRecord { // -location flag or LOCATION env. Constant for every record from one // daemon instance. string location = 21; + // Controller provenance. Empty/zero means observation-only legacy producer. + string agent_id = 22; + string host_boot_id = 23; + string collection_id = 24; + uint64 treatment_state_revision = 25; + string treatment_assignment_id = 26; + uint64 treatment_generation = 27; + int64 treatment_applied_timestamp_ns = 28; + // True only when the observed socket algorithm matches a verified route + // assignment in this namespace. This does not prove initial-window exposure. + bool treatment_algorithm_exposed = 29; // ---- metadata: network namespace identity (30s) -------------------------- // network namespace — best-effort human name (bind-mount name, else a diff --git a/proto/xtcp_treatment/v1/agent.proto b/proto/xtcp_treatment/v1/agent.proto new file mode 100644 index 000000000..8d920a9c2 --- /dev/null +++ b/proto/xtcp_treatment/v1/agent.proto @@ -0,0 +1,58 @@ +// +// xTCP - treatment agent service +// +// The outbound-only RPC surface an agent uses: check in with observed state, +// fetch the authoritative desired state, and watch for revision hints. Every +// method requires an agent certificate whose SPIFFE id matches agent_id and +// whose location matches the request; see pkg/treatment/identity. + +syntax = "proto3"; + +package xtcp_treatment.v1; + +option go_package = "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment"; + +import "buf/validate/validate.proto"; +import "xtcp_treatment/v1/treatment.proto"; + +service AgentControlService { + rpc CheckIn(CheckInRequest) returns (CheckInResponse) { + option (xtcp_treatment.v1.role) = ROLE_AGENT; + } + rpc GetDesiredState(GetDesiredStateRequest) returns (GetDesiredStateResponse) { + option (xtcp_treatment.v1.role) = ROLE_AGENT; + } + rpc WatchDesiredState(WatchDesiredStateRequest) returns (stream WatchDesiredStateResponse) { + option (xtcp_treatment.v1.role) = ROLE_AGENT; + } +} + +message CheckInRequest { + string agent_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + string location = 2 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + Capabilities capabilities = 3 [(buf.validate.field).required = true]; + uint64 desired_revision = 4; + repeated ApplicationRecord records = 5 [(buf.validate.field).repeated.max_items = 8192]; + bool locally_suspended = 6; +} + +message CheckInResponse { + DesiredState desired = 1; +} + +message GetDesiredStateRequest { + string agent_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; +} + +message GetDesiredStateResponse { + DesiredState desired = 1; +} + +message WatchDesiredStateRequest { + string agent_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + uint64 after_revision = 2; +} + +message WatchDesiredStateResponse { + uint64 revision = 1; +} diff --git a/proto/xtcp_treatment/v1/operator.proto b/proto/xtcp_treatment/v1/operator.proto new file mode 100644 index 000000000..f4e0c8253 --- /dev/null +++ b/proto/xtcp_treatment/v1/operator.proto @@ -0,0 +1,122 @@ +// +// xTCP - treatment operator service +// +// The authenticated review surface. Every mutation carries a request_id; +// repeating one with the same body replays the original response, repeating +// it with a different body is refused. Reviews also fence on the experiment +// revision the operator last saw. + +syntax = "proto3"; + +package xtcp_treatment.v1; + +option go_package = "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment"; + +import "buf/validate/validate.proto"; +import "xtcp_treatment/v1/agent.proto"; +import "xtcp_treatment/v1/treatment.proto"; + +service OperatorService { + rpc Propose(ProposeRequest) returns (ProposeResponse) { + option (xtcp_treatment.v1.role) = ROLE_OPERATOR; + } + rpc Analyze(AnalyzeRequest) returns (AnalyzeResponse) { + option (xtcp_treatment.v1.role) = ROLE_OPERATOR; + } + rpc Review(ReviewRequest) returns (ReviewResponse) { + option (xtcp_treatment.v1.role) = ROLE_OPERATOR; + } + rpc Control(ControlRequest) returns (ControlResponse) { + option (xtcp_treatment.v1.role) = ROLE_OPERATOR; + } + rpc Inspect(InspectRequest) returns (InspectResponse) { + option (xtcp_treatment.v1.role) = ROLE_OPERATOR; + } +} + +message ProposeRequest { + option (buf.validate.message).cel = { + id: "propose.request_id_suffix" + message: "request_id must not end with .result (reserved for the paired response event)" + expression: "!this.request_id.endsWith('.result')" + }; + Experiment experiment = 1 [(buf.validate.field).required = true]; + string request_id = 2 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; +} + +message ProposeResponse { + Experiment experiment = 1; +} + +message AnalyzeRequest { + string experiment_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + uint64 expected_revision = 2; +} + +message AnalyzeResponse { + Evidence evidence = 1; + Outcome outcome = 2; +} + +message ReviewRequest { + option (buf.validate.message).cel = { + id: "review.request_id_suffix" + message: "request_id must not end with .result (reserved for the paired response event)" + expression: "!this.request_id.endsWith('.result')" + }; + string experiment_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + uint64 expected_revision = 2; + bool approve = 3; + string reason = 4 [(buf.validate.field).string = {min_len: 1, max_len: 4096}]; + string request_id = 5 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + // Initial review uses baseline; subsequent reviews require fresh evidence. + Evidence evidence = 6; +} + +message ReviewResponse { + Experiment experiment = 1; +} + +enum ControlAction { + CONTROL_ACTION_UNSPECIFIED = 0; + CONTROL_ACTION_PAUSE = 1; + CONTROL_ACTION_SUSPEND = 2; + CONTROL_ACTION_RESUME = 3; + CONTROL_ACTION_ROLLBACK = 4; + CONTROL_ACTION_RETIRE = 5; +} + +message ControlRequest { + option (buf.validate.message).cel = { + id: "control.request_id_suffix" + message: "request_id must not end with .result (reserved for the paired response event)" + expression: "!this.request_id.endsWith('.result')" + }; + option (buf.validate.message).cel = { + id: "control.one_selector" + message: "exactly one of experiment_id, agent_id, location or fleet is required" + expression: "(this.fleet ? 1 : 0) + (this.experiment_id != '' ? 1 : 0) + (this.agent_id != '' ? 1 : 0) + (this.location != '' ? 1 : 0) == 1" + }; + string experiment_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$", (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE]; + string agent_id = 2 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$", (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE]; + string location = 3 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$", (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE]; + bool fleet = 4; + ControlAction action = 5 [(buf.validate.field).enum = {defined_only: true, not_in: [0]}]; + string reason = 6 [(buf.validate.field).string = {min_len: 1, max_len: 4096}]; + string request_id = 7 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; +} + +message ControlResponse { + uint32 affected_agents = 1; +} + +message InspectRequest { + string experiment_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$", (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE]; + string agent_id = 2 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$", (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE]; +} + +message InspectResponse { + repeated Experiment experiments = 1; + repeated DesiredState desired = 2; + repeated CheckInRequest observed = 3; +} diff --git a/proto/xtcp_treatment/v1/treatment.proto b/proto/xtcp_treatment/v1/treatment.proto new file mode 100644 index 000000000..93456f4a8 --- /dev/null +++ b/proto/xtcp_treatment/v1/treatment.proto @@ -0,0 +1,336 @@ +// +// xTCP - treatment +// +// Shared message types for the TCP route treatment control plane: what a +// treatment is, how it is assigned to an agent, what an agent reports back, +// and how an experiment over a cohort of agents is described and evidenced. +// +// Wire contract only. The controller and the agent work on Go domain types +// and convert at the gRPC boundary; nothing here is a storage schema. +// +// Validation: every client-controlled field carries a buf.validate rule that +// mirrors the bound in pkg/treatment/validate.go, so a malformed request is +// rejected before any handler runs. The Go validators remain authoritative +// for contextual rules that need more than one message (duplicate assignment +// IDs, overlapping destinations, cohort/baseline agreement). +// +// See docs/tcp-controller.md. + +syntax = "proto3"; + +package xtcp_treatment.v1; + +option go_package = "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment"; + +import "buf/validate/validate.proto"; +import "google/protobuf/descriptor.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +// Role is the certificate class an RPC requires. The server resolves the +// caller's SPIFFE identity once per call and compares it with this option; +// a method without a declaration is refused for everyone (fail closed). +enum Role { + ROLE_UNSPECIFIED = 0; + // spiffe://xtcp/agent//; may only speak for its own agent_id. + ROLE_AGENT = 1; + // spiffe://xtcp/operator/; recorded as the audit actor. + ROLE_OPERATOR = 2; +} + +extend google.protobuf.MethodOptions { + // Field number from the 50000-99999 range reserved for internal use; + // 51001 is xtcp_auth.v1.access. + Role role = 51002; +} + +// Identifiers are bounded ASCII: a leading alphanumeric, then up to 127 of +// [A-Za-z0-9_.-]. This is the same regexp as treatment.ValidID. + +enum AssignmentMode { + ASSIGNMENT_MODE_UNSPECIFIED = 0; + ASSIGNMENT_MODE_TRIAL = 1; + ASSIGNMENT_MODE_STABLE = 2; + ASSIGNMENT_MODE_SUSPENDED = 3; + ASSIGNMENT_MODE_RETIRED = 4; +} + +enum ApplyStatus { + APPLY_STATUS_UNSPECIFIED = 0; + APPLY_STATUS_PENDING = 1; + APPLY_STATUS_VERIFIED = 2; + APPLY_STATUS_REMOVED = 3; + APPLY_STATUS_EXPIRED = 4; + APPLY_STATUS_FAILED = 5; +} + +// Outcome is the result of evaluating one evidence window against a phase, +// or the standing of a completed treatment under drift monitoring. Only +// BENEFICIAL, SAFETY_ONLY and FINAL_SAFETY can advance a phase, and only +// after an operator review; HARMFUL and EXPIRED withdraw automatically. +enum Outcome { + OUTCOME_UNSPECIFIED = 0; + // Analysis of a proposal that has no phase yet. + OUTCOME_BASELINE = 1; + // Not every treated host has verified the assignment. + OUTCOME_AWAITING_APPLICATION = 2; + // Treated hosts have not yet carried enough exposed sockets. + OUTCOME_AWAITING_EXPOSURE = 3; + OUTCOME_INSUFFICIENT_DURATION = 4; + OUTCOME_INSUFFICIENT_DATA = 5; + OUTCOME_INSUFFICIENT_CONTROLS = 6; + OUTCOME_STALE = 7; + // No evidence source was available for this maintenance pass. + OUTCOME_UNAVAILABLE = 8; + OUTCOME_INCONCLUSIVE = 9; + // Cohort too small for a causal estimate; no regression observed. + OUTCOME_SAFETY_ONLY = 10; + // Final 100% phase: no controls remain; no regression observed. + OUTCOME_FINAL_SAFETY = 11; + OUTCOME_BENEFICIAL = 12; + OUTCOME_HARMFUL = 13; + OUTCOME_EXPIRED = 14; + // Completed treatment under drift monitoring. + OUTCOME_STABLE_OBSERVED = 15; + OUTCOME_STABLE_EVIDENCE_INCOMPLETE = 16; + OUTCOME_STABLE_REGRESSION_REVIEW_REQUIRED = 17; + // Every treated host has verified the assignment; the observation window + // is open and no evidence has been evaluated yet. + OUTCOME_OBSERVING = 18; +} + +enum ExperimentStatus { + EXPERIMENT_STATUS_UNSPECIFIED = 0; + EXPERIMENT_STATUS_PROPOSED = 1; + EXPERIMENT_STATUS_RUNNING = 2; + EXPERIMENT_STATUS_PAUSED = 3; + EXPERIMENT_STATUS_SUSPENDED = 4; + EXPERIMENT_STATUS_COMPLETE = 5; + EXPERIMENT_STATUS_RETIRED = 6; + EXPERIMENT_STATUS_ROLLED_BACK = 7; +} + +// TCPSettings are the per-route TCP parameters a treatment installs. Every +// field is optional; at least one must be present. +message TCPSettings { + option (buf.validate.message).cel = { + id: "tcp_settings.non_empty" + message: "a treatment must set at least one TCP parameter" + expression: "has(this.congestion_control) || has(this.rto_min_ms) || has(this.initial_congestion_window) || has(this.initial_receive_window) || has(this.quick_ack) || has(this.ecn)" + }; + option (buf.validate.message).cel = { + id: "tcp_settings.lock_requires_algorithm" + message: "congestion_lock requires congestion_control" + expression: "!this.congestion_lock || has(this.congestion_control)" + }; + // Kernel algorithm name (TCP_CA_NAME_MAX is 16 including NUL). + optional string congestion_control = 1 [(buf.validate.field).string = { + max_len: 15 + pattern: "^[a-zA-Z0-9][a-zA-Z0-9_.-]*$" + }]; + bool congestion_lock = 2; + optional uint32 rto_min_ms = 3 [(buf.validate.field).uint32 = {gte: 1, lte: 120000}]; + optional uint32 initial_congestion_window = 4 [(buf.validate.field).uint32 = {gte: 1, lte: 1024}]; + optional uint32 initial_receive_window = 5 [(buf.validate.field).uint32 = {gte: 1, lte: 1024}]; + optional bool quick_ack = 6; + optional bool ecn = 7; +} + +message Treatment { + option (buf.validate.message).cel = { + id: "treatment.dctcp_requires_ecn" + message: "DCTCP requires independently verified ECN fabric and explicit ECN" + expression: "this.settings.congestion_control != 'dctcp' || (this.ecn_fabric_verified && this.settings.ecn)" + }; + string id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + uint64 revision = 2 [(buf.validate.field).uint64.gt = 0]; + // Canonical unicast host prefix (/32 or /128). Canonical form, unicast and + // not-loopback are checked by treatment.ValidateTreatment. + string destination = 3 [(buf.validate.field).string = {ip_prefix: true, max_len: 49}]; + TCPSettings settings = 4 [(buf.validate.field).required = true]; + bool ecn_fabric_verified = 5; +} + +message Assignment { + option (buf.validate.message).cel = { + id: "assignment.trial_requires_lease" + message: "a trial assignment requires lease_expires_at" + expression: "this.mode != 1 || has(this.lease_expires_at)" + }; + option (buf.validate.message).cel = { + id: "assignment.predecessor_destination" + message: "predecessor must cover the same destination" + expression: "!has(this.predecessor) || this.predecessor.destination == this.treatment.destination" + }; + // Field 1 was a separate assignment id that always equalled experiment_id. + // An agent holds at most one assignment per experiment, so the experiment + // is the identity; journals and telemetry key on experiment_id. + reserved 1; + reserved "id"; + string experiment_id = 2 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + Treatment treatment = 3 [(buf.validate.field).required = true]; + AssignmentMode mode = 4 [(buf.validate.field).enum = {defined_only: true, not_in: [0]}]; + google.protobuf.Timestamp lease_expires_at = 5; + // Previous approved stable treatment, restored on trial expiry/rollback. + Treatment predecessor = 6; + // Increment only on an explicitly approved reactivation, not lease renewal. + uint64 generation = 7 [(buf.validate.field).uint64.gt = 0]; +} + +// DesiredState is the complete revisioned snapshot an agent reconciles to. +// Duplicate assignment IDs and overlapping destinations are rejected by +// treatment.ValidateDesired. +message DesiredState { + string agent_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + uint64 revision = 2 [(buf.validate.field).uint64.gt = 0]; + bool suspended = 3; + repeated Assignment assignments = 4 [(buf.validate.field).repeated.max_items = 4096]; + google.protobuf.Timestamp issued_at = 5 [(buf.validate.field).required = true]; +} + +message Capabilities { + string boot_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + string kernel_release = 2 [(buf.validate.field).string.max_len = 256]; + repeated string congestion_algorithms = 3 [(buf.validate.field).repeated = { + max_items: 64 + items: {string: {max_len: 15}} + }]; + bool simple_host_routing = 4; + bool actuator_enabled = 5; + // Per-process nonce the agent writes into its journal header and the + // daemon stamps into every record as collection_id. Evidence counts only + // records whose (agent_id, host_boot_id, collection_id) an agent reported. + string collection_id = 6 [(buf.validate.field).string.pattern = "^[0-9a-f]{32}$"]; +} + +// ApplicationRecord is the agent's account of one assignment. Agents report +// these on check-in with installed_route and installed_boot_id cleared. +message ApplicationRecord { + Assignment assignment = 1 [(buf.validate.field).required = true]; + uint64 desired_revision = 2; + ApplyStatus status = 3 [(buf.validate.field).enum.defined_only = true]; + google.protobuf.Timestamp received_at = 4; + google.protobuf.Timestamp attempted_at = 5; + google.protobuf.Timestamp applied_at = 6; + google.protobuf.Timestamp verified_at = 7; + google.protobuf.Timestamp removed_at = 8; + string error = 9 [(buf.validate.field).string.max_len = 4096]; + // Locally generated canonical netlink route body, never accepted from RPC. + bytes installed_route = 10 [(buf.validate.field).bytes.max_len = 4096]; + string installed_boot_id = 11 [(buf.validate.field).string.max_len = 128]; + bool expired_latched = 12; +} + +// LocalState is the agent's journal snapshot. It is a file format for the +// host-side journal and the local tooling, not an RPC payload. +message LocalState { + DesiredState desired = 1; + bool locally_suspended = 2; + string suspension_reason = 3 [(buf.validate.field).string.max_len = 1024]; + repeated ApplicationRecord records = 4 [(buf.validate.field).repeated.max_items = 8192]; + google.protobuf.Timestamp updated_at = 5; +} + +message HostEvidence { + option (buf.validate.message).cel = { + id: "host_evidence.exposed_within_sockets" + message: "exposed_sockets cannot exceed sockets" + expression: "this.exposed_sockets <= this.sockets" + }; + string agent_id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + uint64 sockets = 2; + uint64 bytes_acked = 3; + double goodput_bps = 4 [(buf.validate.field).double = {gte: 0, finite: true}]; + double retransmission_ratio = 5 [(buf.validate.field).double = {gte: 0, finite: true}]; + double rtt_p95_ms = 6 [(buf.validate.field).double = {gte: 0, finite: true}]; + uint64 exposed_sockets = 7; + bool collection_healthy = 8; + // Sockets stamped with this agent_id whose boot and collection nonce + // match no session the agent reported. They are excluded from every other + // field and counted here so a reviewer can see them. + uint64 unbound_sockets = 9; +} + +message Evidence { + option (buf.validate.message).cel = { + id: "evidence.interval" + message: "window_end must follow window_start and analyzed_at must not precede window_end" + expression: "this.window_end > this.window_start && this.analyzed_at >= this.window_end" + }; + string id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + google.protobuf.Timestamp analyzed_at = 2 [(buf.validate.field).required = true]; + google.protobuf.Timestamp window_start = 3 [(buf.validate.field).required = true]; + google.protobuf.Timestamp window_end = 4 [(buf.validate.field).required = true]; + string query_version = 5 [(buf.validate.field).string = {min_len: 1, max_len: 256}]; + string enrichment_version = 6 [(buf.validate.field).string.max_len = 256]; + repeated HostEvidence hosts = 7 [(buf.validate.field).repeated = {min_items: 1, max_items: 10000}]; + // SHA-256 of the raw warehouse response bytes, as received, that this + // summary was decoded from. The response itself is not archived: the + // digest lets two controllers (or a later audit) confirm they decoded the + // same bytes, and reproducing it means re-running query_version over + // [window_start, window_end) against the same table. Archiving responses + // to object storage is a possible follow-up, not a current guarantee. + string artifact_sha256 = 8 [(buf.validate.field).string.pattern = "^[0-9a-f]{64}$"]; +} + +message ExperimentPolicy { + option (buf.validate.message).cel = { + id: "policy.observation_within_phase" + message: "minimum_observation cannot exceed maximum_phase" + expression: "this.minimum_observation <= this.maximum_phase" + }; + google.protobuf.Duration minimum_observation = 1 [ + (buf.validate.field).required = true, + (buf.validate.field).duration = {gt: {seconds: 0}, lte: {seconds: 604800}} + ]; + google.protobuf.Duration maximum_phase = 2 [ + (buf.validate.field).required = true, + (buf.validate.field).duration = {gt: {seconds: 0}, lte: {seconds: 604800}} + ]; + uint64 minimum_sockets_per_host = 3 [(buf.validate.field).uint64.gt = 0]; + uint64 minimum_bytes_per_host = 4 [(buf.validate.field).uint64.gt = 0]; + uint32 minimum_treated_hosts = 5 [(buf.validate.field).uint32 = {gte: 2, lte: 10000}]; + double minimum_improvement = 6 [(buf.validate.field).double = {gte: 0, lte: 1, finite: true}]; + double maximum_retransmission_increase = 7 [(buf.validate.field).double = {gte: 0, lte: 1, finite: true}]; + double maximum_rtt_increase = 8 [(buf.validate.field).double = {gte: 0, lte: 1, finite: true}]; + google.protobuf.Duration maximum_evidence_age = 9 [ + (buf.validate.field).required = true, + (buf.validate.field).duration = {gt: {seconds: 0}, lte: {seconds: 604800}} + ]; +} + +message Phase { + uint32 target_hosts = 1 [(buf.validate.field).uint32 = {gte: 1, lte: 10000}]; + google.protobuf.Timestamp issued_at = 2; + google.protobuf.Timestamp observation_started_at = 3; + google.protobuf.Timestamp evaluated_at = 4; + Evidence evidence = 5; + Outcome outcome = 6 [(buf.validate.field).enum.defined_only = true]; + string reviewer = 7 [(buf.validate.field).string.max_len = 128]; + string reason = 8 [(buf.validate.field).string.max_len = 4096]; +} + +message Experiment { + string id = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + string location = 2 [(buf.validate.field).string.pattern = "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"]; + string hypothesis = 3 [(buf.validate.field).string = {min_len: 1, max_len: 8192}]; + Treatment treatment = 4 [(buf.validate.field).required = true]; + ExperimentPolicy policy = 5 [(buf.validate.field).required = true]; + Evidence baseline = 6 [(buf.validate.field).required = true]; + // Randomised host order; phases treat a growing prefix of it. + repeated string cohort_order = 7 [(buf.validate.field).repeated = { + min_items: 3 + max_items: 10000 + unique: true + items: {string: {pattern: "^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$"}} + }]; + repeated Phase phases = 8 [(buf.validate.field).repeated.max_items = 64]; + ExperimentStatus status = 9 [(buf.validate.field).enum.defined_only = true]; + uint64 revision = 10; + google.protobuf.Timestamp proposed_at = 11; + Evidence latest_evidence = 12; + Outcome latest_outcome = 13 [(buf.validate.field).enum.defined_only = true]; + // When the controller last changed this experiment. Terminal experiments + // suppress rediscovery of their destination for a day after this instant. + google.protobuf.Timestamp updated_at = 14; +} diff --git a/proto/xtcp_treatment_journal/v1/journal.proto b/proto/xtcp_treatment_journal/v1/journal.proto new file mode 100644 index 000000000..9b24349e1 --- /dev/null +++ b/proto/xtcp_treatment_journal/v1/journal.proto @@ -0,0 +1,122 @@ +// +// xTCP - treatment journal +// +// The host-side intent journal of the route treatment agent: the desired +// state last accepted from the controller, the local hold, and one record per +// assignment with the exact kernel route bytes that were installed. It is a +// FILE FORMAT, read and written only on the host by the agent, the watchdog +// and the local treatmentctl commands, and never an RPC payload. +// +// It is a separate proto package from xtcp_treatment.v1 on purpose: the host +// side (pkg/treatment/reconcile, the watchdog) must be able to read and write +// the journal without linking the gRPC service stubs that share a Go package +// with the RPC messages. The messages below therefore repeat the treatment +// shape rather than importing it; pkg/treatment/reconcile converts them to +// and from the domain types, and the domain validators run on every load. +// +// Values of the two enums mirror xtcp_treatment.v1 one-for-one and the domain +// enums in pkg/treatment; reconcile's tests pin the correspondence. +// +// See docs/tcp-controller.md, "Persistence, restart and withdrawal". + +syntax = "proto3"; + +package xtcp_treatment_journal.v1; + +option go_package = "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment_journal"; + +import "google/protobuf/timestamp.proto"; + +enum AssignmentMode { + ASSIGNMENT_MODE_UNSPECIFIED = 0; + ASSIGNMENT_MODE_TRIAL = 1; + ASSIGNMENT_MODE_STABLE = 2; + ASSIGNMENT_MODE_SUSPENDED = 3; + ASSIGNMENT_MODE_RETIRED = 4; +} + +enum ApplyStatus { + APPLY_STATUS_UNSPECIFIED = 0; + APPLY_STATUS_PENDING = 1; + APPLY_STATUS_VERIFIED = 2; + APPLY_STATUS_REMOVED = 3; + APPLY_STATUS_EXPIRED = 4; + APPLY_STATUS_FAILED = 5; +} + +// TCPSettings mirrors xtcp_treatment.v1.TCPSettings; presence is meaningful. +message TCPSettings { + optional string congestion_control = 1; + bool congestion_lock = 2; + optional uint32 rto_min_ms = 3; + optional uint32 initial_congestion_window = 4; + optional uint32 initial_receive_window = 5; + optional bool quick_ack = 6; + optional bool ecn = 7; +} + +message Treatment { + string id = 1; + uint64 revision = 2; + // Canonical /32 or /128 host prefix. + string destination = 3; + TCPSettings settings = 4; + bool ecn_fabric_verified = 5; +} + +message Assignment { + string experiment_id = 1; + Treatment treatment = 2; + AssignmentMode mode = 3; + google.protobuf.Timestamp lease_expires_at = 4; + Treatment predecessor = 5; + uint64 generation = 6; +} + +// Desired is the controller's last accepted snapshot for this agent. The +// agent identity lives on the Journal header. +message Desired { + uint64 revision = 1; + bool suspended = 2; + google.protobuf.Timestamp issued_at = 3; + repeated Assignment assignments = 4; +} + +// Record is the agent's account of one assignment plus the kernel-local +// facts (installed route bytes, installing boot) that never leave the host. +message Record { + Assignment assignment = 1; + uint64 desired_revision = 2; + ApplyStatus status = 3; + google.protobuf.Timestamp received_at = 4; + google.protobuf.Timestamp attempted_at = 5; + google.protobuf.Timestamp applied_at = 6; + google.protobuf.Timestamp verified_at = 7; + google.protobuf.Timestamp removed_at = 8; + string error = 9; + // Locally planned canonical netlink route body, the only thing Remove will + // ever be asked to withdraw. + bytes installed_route = 10; + string installed_boot_id = 11; + bool expired_latched = 12; +} + +// Journal is the atomic snapshot in /state.textproto. The header +// identifies the writer so a journal can never be reconciled for another +// agent and so a telemetry-only daemon can attribute records from it. +message Journal { + string agent_id = 1; + string location = 2; + // Boot that last wrote the journal; per-record installed_boot_id says + // which boot installed each route. + string boot_id = 3; + Desired desired = 4; + bool locally_suspended = 5; + string suspension_reason = 6; + repeated Record records = 7; + google.protobuf.Timestamp updated_at = 8; + // Per-process nonce of the agent that owns the journal. The agent writes + // it; the watchdog preserves it; a telemetry-only daemon stamps it into + // records as collection_id. + string collection_id = 9; +} diff --git a/tools/tcp-controller-integration/main.go b/tools/tcp-controller-integration/main.go new file mode 100644 index 000000000..752dc228d --- /dev/null +++ b/tools/tcp-controller-integration/main.go @@ -0,0 +1,563 @@ +// Command tcp-controller-integration is a disposable-VM test fixture. It is not +// installed with xtcp2. Nix supplies the isolated network and the required marker. +package main + +import ( + "bytes" + "context" + "encoding/json" + "flag" + "fmt" + "io" + "log" + "net/http" + "net/netip" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + evport "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/evidence/clickhouse" + "github.com/randomizedcoder/xtcp2/pkg/treatment/controller/store/postgres" + "github.com/randomizedcoder/xtcp2/pkg/treatment/identity" + "github.com/randomizedcoder/xtcp2/pkg/treatment/reconcile" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/protobuf/types/known/durationpb" +) + +const pkiDir = "/var/lib/controller-test/pki" + +// controllerDSN is the controller's database on this guest; the driver reads +// the agents' sessions from it to bind its own baseline query. +const controllerDSN = "host=/run/postgresql dbname=xtcp user=root sslmode=disable" + +// agentUnit is the systemd unit running the treatment agent when xtcp2 does +// not embed it (-agentUnit=xtcp2-treatment-agent). Empty means the embedded +// arrangement, where the agent lives and dies with the xtcp2 unit. +var agentUnit string + +// agentProcess is the unit whose restart, stop and SIGHUP exercise the agent. +func agentProcess() string { + if agentUnit != "" { + return agentUnit + } + return "xtcp2" +} + +// treatmentUnits lists every unit that must be up for treatments to work. +func treatmentUnits() []string { + units := []string{"xtcp2", "xtcp2-treatment-watchdog"} + if agentUnit != "" { + units = append(units, agentUnit) + } + return units +} + +const statePath = "/var/lib/xtcp2/routes/state.textproto" +const evidenceDir = "/var/lib/controller-test/evidence" + +var hosts = []string{"agent1", "agent2", "agent3", "agent4", "agent5", "agent6"} +var client = &http.Client{Timeout: 30 * time.Second} + +type action struct { + Name string + CA, Certificate, Key []byte + Seconds int64 + Destination string +} +type snapshot struct { + Routes, Main, State, Journal, Rules, Qdisc, Services, DefaultCC string + Projection string +} + +func must[T any](v T, err error) T { + if err != nil { + panic(err) + } + return v +} +func check(err error) { + if err != nil { + panic(err) + } +} +func require(ok bool, format string, args ...any) { + if !ok { + panic(fmt.Sprintf(format, args...)) + } +} + +// command runs a fixture command bounded by ctx and 25 seconds. +func command(ctx context.Context, name string, args ...string) string { + ctx, cancel := context.WithTimeout(ctx, 25*time.Second) + defer cancel() + out, err := exec.CommandContext(ctx, name, args...).CombinedOutput() + if err != nil { + panic(fmt.Sprintf("%s %v: %v: %s", name, args, err, out)) + } + return string(out) +} +func read(path string) []byte { return must(os.ReadFile(path)) } +func write(path string, data []byte) { + check(os.MkdirAll(filepath.Dir(path), 0700)) + check(os.WriteFile(path, data, 0600)) +} + +// host runs a command on the controller side, which has no caller context: +// each fixture step is bounded by command's own timeout. +func host(name string, args ...string) string { + return command(context.Background(), name, args...) +} +func systemctl(ctx context.Context, args ...string) string { return command(ctx, "systemctl", args...) } +func agentReady(ctx context.Context) { + probe := &http.Client{Timeout: time.Second} + eventually("local daemon ready", 15*time.Second, func() bool { + request := must(http.NewRequestWithContext(ctx, http.MethodGet, "http://127.0.0.1:9088/readyz", http.NoBody)) + response := must(probe.Do(request)) + closeBody(response) + return response.StatusCode == http.StatusOK + }) +} + +// closeBody discards a response body; a failed close only loses the +// connection for reuse. +func closeBody(response *http.Response) { + if err := response.Body.Close(); err != nil { + log.Printf("response body close: %v", err) + } +} +func routeTable(ctx context.Context) string { + // Before the first assignment the private table does not exist. + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + out, err := exec.CommandContext(ctx, "ip", "-j", "route", "show", "table", "10002").CombinedOutput() + if err != nil && strings.Contains(string(out), "FIB table does not exist") { + return "[]" + } + check(err) + return string(out) +} +func localSnapshot(ctx context.Context) snapshot { + s := snapshot{Routes: routeTable(ctx), Main: command(ctx, "ip", "-j", "route", "show", "table", "main"), DefaultCC: strings.TrimSpace(command(ctx, "sysctl", "-n", "net.ipv4.tcp_congestion_control"))} + b, err := os.ReadFile(statePath) + if err == nil { + s.State = string(b) + } else if !os.IsNotExist(err) { + panic(err) + } + b, err = os.ReadFile("/var/lib/xtcp2/routes/assignment-netem-canary.textproto") + if err == nil { + s.Projection = string(b) + } else if !os.IsNotExist(err) { + panic(err) + } + return s +} +func serveAgent(address string) { + mux := http.NewServeMux() + mux.HandleFunc("POST /action", func(w http.ResponseWriter, r *http.Request) { + defer func() { + if p := recover(); p != nil { + http.Error(w, fmt.Sprint(p), 500) + } + }() + ctx := r.Context() + var a action + check(json.NewDecoder(http.MaxBytesReader(w, r.Body, 64<<10)).Decode(&a)) + var result any = "ok" + switch a.Name { + case "ready": + case "setup": + require(len(a.CA) > 0 && len(a.Certificate) > 0 && len(a.Key) > 0, "missing fixture credentials") + write(pkiDir+"/ca.crt", a.CA) + write(pkiDir+"/agent.crt", a.Certificate) + write(pkiDir+"/agent.key", a.Key) + write("/var/lib/controller-test/load.env", []byte("TCP_TEST_DESTINATION=198.18.0.1\n")) + command(ctx, "tc", "qdisc", "replace", "dev", "eth0", "root", "handle", "1:", "prio", "bands", "3", "priomap", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0") + command(ctx, "tc", "qdisc", "add", "dev", "eth0", "parent", "1:2", "handle", "20:", "netem", "delay", "80ms") + command(ctx, "tc", "qdisc", "add", "dev", "eth0", "parent", "1:3", "handle", "30:", "netem", "delay", "5ms") + command(ctx, "tc", "filter", "add", "dev", "eth0", "parent", "1:", "protocol", "ip", "prio", "1", "u32", "match", "ip", "dst", "198.18.0.2/32", "flowid", "1:2") + command(ctx, "tc", "filter", "add", "dev", "eth0", "parent", "1:", "protocol", "ip", "prio", "2", "u32", "match", "ip", "dst", "198.18.0.0/24", "flowid", "1:3") + systemctl(ctx, append([]string{"start", "load-near", "load-far"}, treatmentUnits()...)...) + case "status": + result = localSnapshot(ctx) + case "restart-agent": + systemctl(ctx, "restart", agentProcess()) + agentReady(ctx) + case "stop-agent": + systemctl(ctx, "stop", agentProcess()) + systemctl(ctx, "is-active", "xtcp2-treatment-watchdog") + case "start-agent": + systemctl(ctx, "start", agentProcess()) + agentReady(ctx) + case "restart-load": + systemctl(ctx, "restart", "load-near") + case "destination": + require(validSoakDestination(a.Destination), "invalid fixture destination") + write("/var/lib/controller-test/load.env", []byte("TCP_TEST_DESTINATION="+a.Destination+"\n")) + systemctl(ctx, "restart", "load-near") + case "hup": + agentReady(ctx) + systemctl(ctx, "kill", "-s", "HUP", agentProcess()) + case "suspend", "resume": + command(ctx, "xtcp2-treatmentctl", "-mode="+a.Name, "-reason=integration-local-"+a.Name) + case "delay": + require(a.Seconds == 5 || a.Seconds == 180, "invalid fixture delay") + command(ctx, "tc", "qdisc", "change", "dev", "eth0", "parent", "1:3", "handle", "30:", "netem", "delay", fmt.Sprintf("%dms", a.Seconds)) + case "expire": + command(ctx, "date", "-s", fmt.Sprintf("@%d", time.Now().Unix()+3700)) + case "restore-clock": + require(a.Seconds > 0, "invalid clock") + command(ctx, "date", "-s", fmt.Sprintf("@%d", a.Seconds)) + case "healthy": + result = systemctl(ctx, append([]string{"is-active", "load-near", "load-far"}, treatmentUnits()...)...) + case "evidence": + s := localSnapshot(ctx) + units := treatmentUnits() + args := make([]string, 0, 6+2*len(units)) + args = append(args, "-b", "--no-pager", "-n", "500", "-u", "controller-test-agent") + for _, u := range units { + args = append(args, "-u", u) + } + s.Journal = command(ctx, "journalctl", args...) + s.Rules = command(ctx, "ip", "-j", "rule") + s.Qdisc = command(ctx, "tc", "-s", "qdisc", "show") + result = s + default: + panic("unknown fixture action") + } + w.Header().Set("Content-Type", "application/json") + check(json.NewEncoder(w).Encode(result)) + }) + server := &http.Server{Addr: address, Handler: mux, ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 10 * time.Second, WriteTimeout: 120 * time.Second} + log.Fatal(server.ListenAndServe()) +} +func remote(host string, a action, result any) { + index := 0 + for i, h := range hosts { + if h == host { + index = i + 11 + } + } + require(index != 0, "unknown agent %q", host) + body := must(json.Marshal(a)) + request := must(http.NewRequestWithContext(context.Background(), http.MethodPost, fmt.Sprintf("http://192.168.1.%d:9009/action", index), bytes.NewReader(body))) + request.Header.Set("Content-Type", "application/json") + response := must(client.Do(request)) + defer closeBody(response) + data := must(io.ReadAll(io.LimitReader(response.Body, 2<<20))) + require(response.StatusCode == 200, "%s %s: %s", host, a.Name, data) + if result != nil { + check(json.Unmarshal(data, result)) + } +} +func act(host, name string) { remote(host, action{Name: name}, nil) } +func status(host string) snapshot { var s snapshot; remote(host, action{Name: "status"}, &s); return s } +func hasRoute(host string) bool { return strings.Contains(status(host).Routes, "198.18.0.1") } +func routeCount() int { + n := 0 + for _, h := range hosts { + if hasRoute(h) { + n++ + } + } + return n +} +func eventually(label string, timeout time.Duration, fn func() bool) { + log.Print(label) + deadline := time.Now().Add(timeout) + var last any + for time.Now().Before(deadline) { + ok := func() (ok bool) { + defer func() { + if p := recover(); p != nil { + last = p + } + }() + return fn() + }() + if ok { + return + } + time.Sleep(3 * time.Second) + } + panic(fmt.Sprintf("%s: timed out after %s (last error: %v)", label, timeout, last)) +} +func sql(query string) string { return host("clickhouse-client", "--query", query) } +func count(query string) int { return must(strconv.Atoi(strings.TrimSpace(sql(query)))) } +func pass(stage string) { fmt.Println("TCP_CONTROLLER_" + stage + "_PASS") } +func rpcContext() (context.Context, context.CancelFunc) { + return context.WithTimeout(context.Background(), 20*time.Second) +} +func inspect(op pb.OperatorServiceClient, id string) *pb.Experiment { + ctx, cancel := rpcContext() + defer cancel() + response := must(op.Inspect(ctx, &pb.InspectRequest{ExperimentId: id})) + require(len(response.Experiments) == 1, "expected one experiment") + return response.Experiments[0] +} +func review(op pb.OperatorServiceClient, e *pb.Experiment, id string, evidence *pb.Evidence) *pb.Experiment { + ctx, cancel := rpcContext() + defer cancel() + return must(op.Review(ctx, &pb.ReviewRequest{ExperimentId: e.Id, ExpectedRevision: e.Revision, Approve: true, Reason: "Integration: reviewed measured evidence and destination scope", RequestId: id, Evidence: evidence})).Experiment +} +func propose(op pb.OperatorServiceClient, id string) *pb.Experiment { + ch := clickhouse.Client{URL: "http://127.0.0.1:8123", Table: "xtcp.xtcp_flat_records_v2"} + var baseline *pb.Evidence + eventually("fresh six-host baseline", 3*time.Minute, func() bool { + end := time.Now().Add(-20 * time.Second) + ctx, cancel := rpcContext() + defer cancel() + start := end.Add(-60 * time.Second) + baseline = wire.Evidence(must(ch.Evidence(ctx, evport.Window{Location: "test-dc", Destination: netip.MustParsePrefix("198.18.0.1/32"), ExperimentID: id, Agents: hosts, Sessions: sessions(ctx, start, end), Start: start, End: end}))) + require(len(baseline.Hosts) == 6, "baseline needs six hosts: %v", baseline.Hosts) + for _, h := range baseline.Hosts { + require(h.CollectionHealthy && h.Sockets >= 8 && h.BytesAcked >= 4096, "baseline not ready: %v", h) + } + return true + }) + e := &pb.Experiment{Id: id, Location: "test-dc", Hypothesis: "Integration: review CUBIC on measured low-RTT destination", CohortOrder: hosts, Baseline: baseline, + Treatment: &pb.Treatment{Id: "cubic-near", Revision: 1, Destination: "198.18.0.1/32", Settings: nearbySettings()}, + Policy: &pb.ExperimentPolicy{MinimumObservation: durationpb.New(20 * time.Second), MaximumPhase: durationpb.New(15 * time.Minute), MaximumEvidenceAge: durationpb.New(2 * time.Minute), MinimumSocketsPerHost: 8, MinimumBytesPerHost: 4096, MinimumTreatedHosts: 4, MinimumImprovement: 1, MaximumRetransmissionIncrease: .1, MaximumRttIncrease: 1}, + } + ctx, cancel := rpcContext() + defer cancel() + e = must(op.Propose(ctx, &pb.ProposeRequest{Experiment: e, RequestId: id + "-propose"})).Experiment + require(len(e.Phases) == 0 && routeCount() == 0, "unapproved proposal applied") + return review(op, e, id+"-initial", nil) +} + +// sessions reads the sessions the agents reported over a window, widened +// the way the controller widens it, from the controller's own store. +func sessions(ctx context.Context, from, to time.Time) []treatment.Session { + db := must(postgres.Open(ctx, controllerDSN)) + defer func() { + if cerr := db.Close(); cerr != nil { + log.Printf("controller database close: %v", cerr) + } + }() + return must(db.Repos().Agents.Sessions(ctx, hosts, from.Add(-15*time.Minute), to.Add(15*time.Minute))) +} + +// binding copies a cohort host's recent records under a boot and nonce that +// host never reported, as a host spoofing its agent_id would, and checks the +// controller counts them as unbound instead of as that host's evidence. +func binding(op pb.OperatorServiceClient, e *pb.Experiment) { + spoofed := e.CohortOrder[len(e.CohortOrder)-1] + sql(fmt.Sprintf(`INSERT INTO xtcp.xtcp_flat_records_v2 SELECT * REPLACE ('spoofed-boot' AS host_boot_id, 'ffffffffffffffffffffffffffffffff' AS collection_id, + inet_diag_msg_socket_cookie + 1000000000 AS inet_diag_msg_socket_cookie) + FROM xtcp.xtcp_flat_records_v2 WHERE agent_id='%s' AND timestamp_ns > now() - INTERVAL 2 MINUTE`, spoofed)) + eventually("spoofed records counted as unbound, not as evidence", 2*time.Minute, func() bool { + e = inspect(op, e.Id) + ctx, cancel := rpcContext() + defer cancel() + a := must(op.Analyze(ctx, &pb.AnalyzeRequest{ExperimentId: e.Id, ExpectedRevision: e.Revision})) + for _, h := range a.Evidence.Hosts { + if h.AgentId == spoofed { + require(h.UnboundSockets > 0, "spoofed records were not counted as unbound: %v", h) + write(evidenceDir+"/binding.json", must(json.MarshalIndent(a.Evidence, "", " "))) + return true + } + } + panic(fmt.Sprintf("no evidence row for %s", spoofed)) + }) +} + +func control(op pb.OperatorServiceClient, id string, a pb.ControlAction) { + ctx, cancel := rpcContext() + defer cancel() + must(op.Control(ctx, &pb.ControlRequest{RequestId: id, Action: a, Reason: "Integration withdrawal comparison", Fleet: true})) +} +func evidence() { + // A failed assertion must still leave useful diagnostics, without replacing + // the original failure if a crashed guest cannot answer. + attempt := func(name string, fn func() []byte) { + defer func() { + if p := recover(); p != nil { + log.Printf("evidence %s: %v", name, p) + } + }() + write(evidenceDir+"/"+name, fn()) + } + for _, h := range hosts { + attempt(h+".json", func() []byte { + var s snapshot + remote(h, action{Name: "evidence"}, &s) + return must(json.MarshalIndent(s, "", " ")) + }) + } + attempt("controller.log", func() []byte { return []byte(host("journalctl", "-b", "--no-pager", "-n", "1500")) }) + attempt("controller.sql", func() []byte { return []byte(host("pg_dump", "-h", "/run/postgresql", "-U", "root", "xtcp")) }) + attempt("telemetry.jsonl", func() []byte { + return []byte(sql("SELECT * FROM xtcp.xtcp_flat_records_v2 ORDER BY timestamp_ns DESC LIMIT 2000 FORMAT JSONEachRow")) + }) +} +func runController(soak bool) { + defer evidence() + eventually("ClickHouse ready", 3*time.Minute, func() bool { return strings.TrimSpace(sql("SELECT 1")) == "1" }) + sql("CREATE DATABASE xtcp") + schemaCtx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + cmd := exec.CommandContext(schemaCtx, "clickhouse-client", "--multiquery") + cmd.Stdin = bytes.NewReader(read("/etc/xtcp-test/schema.sql")) + out, err := cmd.CombinedOutput() + require(err == nil, "schema: %v: %s", err, out) + sql("CREATE TABLE xtcp.ingest ENGINE=Null AS SELECT toInt64(0) AS timestamp_ns, * EXCEPT(timestamp_ns) FROM xtcp.xtcp_flat_records_v2 WHERE 0") + sql("CREATE MATERIALIZED VIEW xtcp.ingest_mv TO xtcp.xtcp_flat_records_v2 AS SELECT fromUnixTimestamp64Nano(timestamp_ns) AS timestamp_ns, * EXCEPT(timestamp_ns) FROM xtcp.ingest") + host("systemctl", "start", "xtcp-controller") + for _, h := range hosts { + eventually(h+" fixture ready", 3*time.Minute, func() bool { act(h, "ready"); return true }) + remote(h, action{Name: "setup", CA: read(pkiDir + "/ca.crt"), Certificate: read(pkiDir + "/" + h + ".crt"), Key: read(pkiDir + "/" + h + ".key")}, nil) + } + tls := must(identity.TLSConfig(pkiDir+"/operator.crt", pkiDir+"/operator.key", pkiDir+"/ca.crt", "controller", false)) + conn := must(grpc.NewClient("127.0.0.1:9443", grpc.WithTransportCredentials(credentials.NewTLS(tls)))) + defer func() { + if cerr := conn.Close(); cerr != nil { + log.Printf("operator connection close: %v", cerr) + } + }() + op := pb.NewOperatorServiceClient(conn) + if soak { + runSoak(op) + return + } + eventually("both latency bands in real socket telemetry", 3*time.Minute, func() bool { + rows := strings.Split(strings.TrimSpace(sql("SELECT hex(inet_diag_msg_socket_destination), uniqExact(agent_id), quantileExact(0.5)(tcp_info_rtt)/1000 FROM xtcp.xtcp_flat_records_v2 WHERE timestamp_ns>now()-INTERVAL 30 SECOND AND inet_diag_msg_state=1 AND inet_diag_msg_socket_destination IN (unhex('C6120001000000000000000000000000'),unhex('C6120002000000000000000000000000')) GROUP BY inet_diag_msg_socket_destination ORDER BY inet_diag_msg_socket_destination FORMAT TabSeparated")), "\n") + require(len(rows) == 2, "expected two RTT bands: %q", rows) + a, b := strings.Fields(rows[0]), strings.Fields(rows[1]) + require(len(a) == 3 && len(b) == 3 && a[1] == "6" && b[1] == "6", "expected six hosts per RTT band: %q", rows) + near, far := must(strconv.ParseFloat(a[2], 64)), must(strconv.ParseFloat(b[2], 64)) + require(far > near+35, "RTT bands not separated: %q", rows) + write(evidenceDir+"/rtt-bands.tsv", []byte(strings.Join(rows, "\n"))) + return true + }) + pass("RTT") + mainRoutes := map[string]string{} + for _, h := range hosts { + mainRoutes[h] = status(h).Main + } + e := propose(op, "netem-canary") + canary := e.CohortOrder[0] + eventually("single assigned CUBIC route", 2*time.Minute, func() bool { + return hasRoute(canary) && routeCount() == 1 && strings.Contains(status(canary).Routes, "cubic") + }) + assertNearbyRoute(canary, "198.18.0.1") + eventually("existing sockets retain Reno", time.Minute, func() bool { + return count(fmt.Sprintf("SELECT count() FROM xtcp.xtcp_flat_records_v2 WHERE agent_id='%s' AND treatment_assignment_id='netem-canary' AND inet_diag_cong='reno' AND NOT treatment_algorithm_exposed", canary)) > 0 + }) + act(canary, "restart-load") + eventually("new sockets expose actual CUBIC", time.Minute, func() bool { + return count(fmt.Sprintf("SELECT count() FROM xtcp.xtcp_flat_records_v2 WHERE agent_id='%s' AND treatment_assignment_id='netem-canary' AND inet_diag_cong='cubic' AND treatment_algorithm_exposed", canary)) >= 8 + }) + pass("CANARY") + act(canary, "restart-agent") + eventually("journal replay", time.Minute, func() bool { s := status(canary); return hasRoute(canary) && s.State != "" && s.Projection != "" }) + assertNearbyRoute(canary, "198.18.0.1") + host("systemctl", "restart", "xtcp-controller") + eventually("controller state survived restart", time.Minute, func() bool { return inspect(op, e.Id).Revision == e.Revision }) + pass("PERSIST") + act(canary, "suspend") + require(!hasRoute(canary), "local hold retained route") + act(canary, "restart-agent") + control(op, "cannot-clear-local", pb.ControlAction_CONTROL_ACTION_RESUME) + act(canary, "hup") + time.Sleep(5 * time.Second) + s := status(canary) + state := must(reconcile.UnmarshalText([]byte(s.State))) + require(state.LocallySuspended && !hasRoute(canary), "remote resume cleared local hold") + act(canary, "resume") + eventually("local resume", time.Minute, func() bool { return hasRoute(canary) }) + control(op, "fleet-hold", pb.ControlAction_CONTROL_ACTION_SUSPEND) + eventually("fleet withdrawal", time.Minute, func() bool { return routeCount() == 0 }) + control(op, "fleet-resume", pb.ControlAction_CONTROL_ACTION_RESUME) + eventually("fleet resume", time.Minute, func() bool { return hasRoute(canary) }) + assertNearbyRoute(canary, "198.18.0.1") + act(canary, "restart-load") + pass("HOLD") + // The safety analysis below then runs with the spoofed rows present, so + // its outcome shows they did not count. + binding(op, e) + pass("BINDING") + var analysis *pb.AnalyzeResponse + eventually("measured first-canary safety", 4*time.Minute, func() bool { + e = inspect(op, e.Id) + ctx, cancel := rpcContext() + defer cancel() + analysis = must(op.Analyze(ctx, &pb.AnalyzeRequest{ExperimentId: e.Id, ExpectedRevision: e.Revision})) + log.Printf("analysis: %s", analysis.Outcome) + return analysis.Outcome == pb.Outcome_OUTCOME_SAFETY_ONLY + }) + eventually("approve second host with current check-ins", time.Minute, func() bool { e = review(op, inspect(op, e.Id), "approve-second", analysis.Evidence); return true }) + require(e.Phases[len(e.Phases)-1].TargetHosts == 2, "wrong phase target") + second := e.CohortOrder[1] + eventually("exactly two treated hosts", time.Minute, func() bool { return routeCount() == 2 && hasRoute(second) }) + assertNearbyRoute(second, "198.18.0.1") + remote(second, action{Name: "delay", Seconds: 180}, nil) + act(second, "restart-load") + eventually("automatic rollback on measured netem harm", 5*time.Minute, func() bool { return inspect(op, e.Id).Status == pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK }) + eventually("all overrides withdrawn", time.Minute, func() bool { return routeCount() == 0 }) + e = inspect(op, e.Id) + require(e.Phases[len(e.Phases)-1].Outcome == pb.Outcome_OUTCOME_HARMFUL, "wrong rollback reason") + pass("ROLLBACK") + remote(second, action{Name: "delay", Seconds: 5}, nil) + for _, h := range hosts { + act(h, "restart-load") + } + time.Sleep(85 * time.Second) + e = propose(op, "watchdog-outage") + victim := e.CohortOrder[0] + eventually("outage trial installed", time.Minute, func() bool { return hasRoute(victim) }) + host("systemctl", "stop", "xtcp-controller") + act(victim, "stop-agent") + act(victim, "expire") + eventually("independent watchdog expires unchanged one-hour lease", 90*time.Second, func() bool { + return !hasRoute(victim) && strings.Contains(status(victim).State, "APPLY_STATUS_EXPIRED") + }) + act(victim, "start-agent") + time.Sleep(5 * time.Second) + require(!hasRoute(victim), "restart resurrected expired trial") + remote(victim, action{Name: "restore-clock", Seconds: time.Now().Unix()}, nil) + host("systemctl", "start", "xtcp-controller") + act(victim, "hup") + time.Sleep(5 * time.Second) + require(!hasRoute(victim), "reconnect resurrected expired generation") + pass("WATCHDOG") + for _, h := range hosts { + s := status(h) + require(s.Main == mainRoutes[h], "%s main routes changed", h) + require(s.DefaultCC == "reno", "%s default CC changed", h) + act(h, "healthy") + } + fmt.Println("TCP_CONTROLLER_PASS") +} +func main() { + role := flag.String("role", "", "controller or agent") + listen := flag.String("listen", "", "isolated guest fixture address") + soak := flag.Bool("soak", false, "run repeated RTT/discovery/rollback cycles from the shared soak-config.json") + flag.StringVar(&agentUnit, "agentUnit", "", "agent role: systemd unit of a standalone xtcp2-treatment-agent; empty when xtcp2 embeds the agent") + flag.Parse() + if _, err := os.Stat("/etc/xtcp-controller-integration"); err != nil { + log.Fatal("requires disposable integration VM marker") + } + if *role == "agent" { + serveAgent(*listen) + return + } + if *role != "controller" { + log.Fatal("invalid role") + } + defer func() { + if p := recover(); p != nil { + fmt.Printf("TCP_CONTROLLER_FAIL: %v\n", p) + os.Exit(1) + } + }() + runController(*soak) +} diff --git a/tools/tcp-controller-integration/nearby.go b/tools/tcp-controller-integration/nearby.go new file mode 100644 index 000000000..7527f7ef6 --- /dev/null +++ b/tools/tcp-controller-integration/nearby.go @@ -0,0 +1,43 @@ +package main + +import ( + "encoding/json" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "google.golang.org/protobuf/proto" +) + +func nearbySettings() *pb.TCPSettings { + return &pb.TCPSettings{ + CongestionControl: proto.String("cubic"), RtoMinMs: proto.Uint32(5), + QuickAck: proto.Bool(true), InitialCongestionWindow: proto.Uint32(100), + InitialReceiveWindow: proto.Uint32(100), + } +} + +// Check the kernel's installed metrics, not just the controller's desired state. +func assertNearbyRoute(host, destination string) { + raw := status(host).Routes + var routes []struct { + Destination string `json:"dst"` + Metrics []struct { + Congestion string `json:"congestion"` + RtoMin uint32 `json:"rto_min"` + QuickAck uint32 `json:"quickack"` + InitCwnd uint32 `json:"initcwnd"` + InitRwnd uint32 `json:"initrwnd"` + } `json:"metrics"` + } + check(json.Unmarshal([]byte(raw), &routes)) + for _, r := range routes { + if r.Destination != destination && r.Destination != destination+"/32" { + continue + } + require(len(r.Metrics) == 1, "%s missing route metrics: %s", host, raw) + m := r.Metrics[0] + require(m.Congestion == "cubic" && m.RtoMin == 5 && m.QuickAck == 1 && m.InitCwnd == 100 && m.InitRwnd == 100, "%s incorrect nearby route: %s", host, raw) + write(evidenceDir+"/"+host+"-nearby-route.json", []byte(raw)) + return + } + panic("missing nearby route on " + host) +} diff --git a/tools/tcp-controller-integration/soak.go b/tools/tcp-controller-integration/soak.go new file mode 100644 index 000000000..5d86b694f --- /dev/null +++ b/tools/tcp-controller-integration/soak.go @@ -0,0 +1,330 @@ +package main + +import ( + "encoding/csv" + "encoding/json" + "fmt" + "log" + "os" + "strings" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/experiment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +type soakConfig struct { + Cycles int `json:"cycles"` + IntervalSeconds int `json:"interval_seconds"` +} + +func (c soakConfig) validate() error { + if c.Cycles < 2 || c.Cycles > 6 || c.IntervalSeconds < 180 || c.IntervalSeconds > 300 { + return fmt.Errorf("soak requires 2..6 cycles and 180..300 seconds per RTT phase") + } + return nil +} +func validSoakDestination(s string) bool { + for i := 101; i <= 106; i++ { + if s == fmt.Sprintf("198.18.0.%d", i) { + return true + } + } + return false +} + +type soakRun struct { + op pb.OperatorServiceClient + config soakConfig + started time.Time + cycle int + phase, destination string + delay int64 + events *os.File + samples *csv.Writer + sampleFile *os.File +} + +func (s *soakRun) event(name string, e *pb.Experiment) { + row := map[string]any{"at": time.Now().UTC(), "elapsed_seconds": time.Since(s.started).Seconds(), "cycle": s.cycle, "phase": s.phase, "destination": s.destination, "delay_ms": s.delay, "event": name} + if e != nil { + row["experiment"] = json.RawMessage(must(protojson.Marshal(e))) + } + check(json.NewEncoder(s.events).Encode(row)) + check(s.events.Sync()) + log.Printf("SOAK cycle=%d phase=%s destination=%s delay=%dms event=%s", s.cycle, s.phase, s.destination, s.delay, name) +} +func (s *soakRun) experiments() []*pb.Experiment { + ctx, cancel := rpcContext() + defer cancel() + return must(s.op.Inspect(ctx, &pb.InspectRequest{})).Experiments +} +func (s *soakRun) current() *pb.Experiment { + var found *pb.Experiment + for _, e := range s.experiments() { + if e.Treatment.Destination == s.destination+"/32" { + require(found == nil, "duplicate proposal for %s", s.destination) + found = e + } + } + return found +} +func destinationRoutes(destination string) int { + n := 0 + for _, h := range hosts { + var rows []struct { + Destination string `json:"dst"` + } + check(json.Unmarshal([]byte(status(h).Routes), &rows)) + for _, r := range rows { + if r.Destination == destination || r.Destination == destination+"/32" { + n++ + } + } + } + return n +} +func ownedRoutes() int { + n := 0 + for _, h := range hosts { + var routes []json.RawMessage + check(json.Unmarshal([]byte(status(h).Routes), &routes)) + n += len(routes) + } + return n +} +func (s *soakRun) sample() { + // Restrict to the active destination. Read actual SRTT, not the lifetime + // minimum used by discovery. Keep each host's values instead of pooling it. + query := fmt.Sprintf(`SELECT agent_id, quantileExact(0.5)(tcp_info_rtt)/1000, + countIf(inet_diag_cong='reno'), countIf(inet_diag_cong='cubic'), countIf(treatment_algorithm_exposed) + FROM xtcp.xtcp_flat_records_v2 WHERE timestamp_ns>now()-INTERVAL 20 SECOND + AND inet_diag_msg_state=1 AND hex(inet_diag_msg_socket_destination)=concat(hex(IPv4StringToNum('%s')),'000000000000000000000000') + GROUP BY agent_id ORDER BY agent_id FORMAT TabSeparated`, s.destination) + raw := strings.TrimSpace(sql(query)) + e := s.current() + id, st := "", "none" + if e != nil { + id = e.Id + st = e.Status.String() + } + if raw != "" { + for _, line := range strings.Split(raw, "\n") { + fields := strings.Split(line, "\t") + require(len(fields) == 5, "invalid RTT sample: %q", line) + row := []string{time.Now().UTC().Format(time.RFC3339Nano), fmt.Sprint(s.cycle), s.phase, s.destination, fmt.Sprint(s.delay), id, st} + check(s.samples.Write(append(row, fields...))) + } + } + s.samples.Flush() + check(s.samples.Error()) + check(s.sampleFile.Sync()) +} +func (s *soakRun) setPhase(phase string, delay int64, newDestination bool) time.Time { + s.phase, s.delay = phase, delay + for _, h := range hosts { + remote(h, action{Name: "delay", Seconds: delay}, nil) + } + if newDestination { + for _, h := range hosts { + remote(h, action{Name: "destination", Destination: s.destination}, nil) + } + } + s.event("netem_changed", nil) + return time.Now().Add(time.Duration(s.config.IntervalSeconds) * time.Second) +} +func (s *soakRun) until(end time.Time, inspectState func()) { + for time.Now().Before(end) { + inspectState() + s.sample() + remaining := time.Until(end) + if remaining > 15*time.Second { + remaining = 15 * time.Second + } + if remaining > 0 { + time.Sleep(remaining) + } + } + inspectState() + s.sample() +} +func (s *soakRun) assertMeasuredRTT() { + // Last twenty seconds must contain all six agents at the injected RTT. + query := fmt.Sprintf(`SELECT uniqExact(agent_id), quantileExact(0.5)(tcp_info_rtt)/1000 + FROM xtcp.xtcp_flat_records_v2 WHERE timestamp_ns>now()-INTERVAL 20 SECOND + AND inet_diag_msg_state=1 AND hex(inet_diag_msg_socket_destination)=concat(hex(IPv4StringToNum('%s')),'000000000000000000000000') FORMAT TabSeparated`, s.destination) + fields := strings.Fields(sql(query)) + require(len(fields) == 2 && fields[0] == "6", "missing RTT population: %v", fields) + var rtt float64 + _, err := fmt.Sscan(fields[1], &rtt) + check(err) + require(rtt >= float64(s.delay)*.8 && rtt <= float64(s.delay)*1.5+3, "RTT %.3fms does not match netem %dms", rtt, s.delay) +} + +// A low netem delay does not guarantee this aggressive profile is beneficial. +// Accept an early safety withdrawal only with valid, exposed, harmful evidence. +func validateSoakRollback(e *pb.Experiment, injectedLatency bool) error { + if e == nil || e.Status != pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK || len(e.Phases) != 1 || e.Phases[0].Outcome != pb.Outcome_OUTCOME_HARMFUL || len(e.CohortOrder) == 0 || e.Policy == nil || e.Baseline == nil || e.LatestEvidence == nil { + return fmt.Errorf("rollback is missing its harmful phase or evidence") + } + d, err := wire.ParseExperiment(e) + if err != nil { + return err + } + if err := treatment.ValidateEvidence(d.Baseline); err != nil { + return err + } + if err := treatment.ValidateEvidence(d.LatestEvidence); err != nil { + return err + } + if err := treatment.ValidatePolicy(d.Policy); err != nil { + return err + } + _, harmful := experiment.HealthyEvidence(d, d.LatestEvidence, d.LatestEvidence.AnalyzedAt) + if !harmful { + return fmt.Errorf("rollback evidence does not cross a safety guard") + } + for _, h := range e.LatestEvidence.Hosts { + if h.AgentId == e.CohortOrder[0] && h.ExposedSockets > 0 { + if injectedLatency && h.RttP95Ms < 90 { + return fmt.Errorf("rollback evidence did not observe injected latency on the canary") + } + return nil + } + } + return fmt.Errorf("rollback evidence has no exposed canary sockets") +} + +func injectedLatencyRollback(e *pb.Experiment, changedAt time.Time) bool { + return validateSoakRollback(e, true) == nil && e.LatestEvidence.WindowEnd.AsTime().After(changedAt) +} + +func runSoak(op pb.OperatorServiceClient) { + var config soakConfig + check(json.Unmarshal(read(evidenceDir+"/soak-config.json"), &config)) + check(config.validate()) + events := must(os.OpenFile(evidenceDir+"/soak-events.jsonl", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)) + defer events.Close() + samples := must(os.OpenFile(evidenceDir+"/soak-rtt.csv", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)) + defer samples.Close() + s := &soakRun{op: op, config: config, started: time.Now(), events: events, sampleFile: samples, samples: csv.NewWriter(samples)} + check(s.samples.Write([]string{"at", "cycle", "phase", "destination", "netem_ms", "experiment", "status", "agent", "median_rtt_ms", "reno_samples", "cubic_samples", "exposed_samples"})) + mainRoutes := map[string]string{} + for _, h := range hosts { + mainRoutes[h] = status(h).Main + } + latencyRollbacks, lowRTTRollbacks := 0, 0 + for cycle := 1; cycle <= config.Cycles; cycle++ { + s.cycle = cycle + s.destination = fmt.Sprintf("198.18.0.%d", 100+cycle) + end := s.setPhase("high_no_candidate", 180, true) + s.until(end, func() { + require(s.current() == nil, "high-RTT destination incorrectly proposed") + require(ownedRoutes() == 0, "unapproved route installed") + }) + s.assertMeasuredRTT() + s.event("high_rtt_filtered", nil) + // New connections reset TCP_INFO's lifetime minimum RTT. The discovery + // window and 20-second ingest watermark must both age out the high phase. + end = s.setPhase("low_discovery", 5, true) + var approved *pb.Experiment + rolledBack := false + s.until(end, func() { + e := s.current() + if e == nil { + return + } + if approved == nil { + require(e.Status == pb.ExperimentStatus_EXPERIMENT_STATUS_PROPOSED && len(e.Phases) == 0 && ownedRoutes() == 0, "discovery bypassed operator approval") + require(e.Treatment.Id == "soak-nearby-cubic" && strings.HasPrefix(e.Hypothesis, "Template soak-nearby-cubic:"), "candidate was not created by discovery") + require(proto.Equal(e.Treatment.Settings, nearbySettings()), "discovery lost nearby route settings: %v", e.Treatment.Settings) + require(e.GetPolicy().GetMaximumRttIncrease() == 1, "soak discovery did not use the fixture RTT tolerance") + s.event("controller_proposed", e) + approved = review(op, e, fmt.Sprintf("soak-review-%d", cycle), nil) + s.event("test_operator_approved", approved) + eventually("soak canary route installed", time.Minute, func() bool { return destinationRoutes(s.destination) == 1 }) + assertNearbyRoute(approved.CohortOrder[0], s.destination) + act(approved.CohortOrder[0], "restart-load") + } + e = inspect(op, approved.Id) + if e.Status == pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK { + if !rolledBack { + s.event("low_rtt_rollback_observed", e) + check(validateSoakRollback(e, false)) + eventually("early safety overrides withdrawn", time.Minute, func() bool { return ownedRoutes() == 0 }) + s.event("low_rtt_safety_rollback", e) + lowRTTRollbacks++ + rolledBack = true + } + require(ownedRoutes() == 0, "early safety withdrawal was reversed") + return + } + require(!rolledBack, "early rolled-back experiment was revived") + if e.Status != pb.ExperimentStatus_EXPERIMENT_STATUS_RUNNING || len(e.Phases) != 1 { + s.event("unexpected_low_rtt_state", e) + panic(fmt.Sprintf("low-RTT phase: status=%s outcome=%s; full evidence in soak-events.jsonl", e.Status, e.LatestOutcome)) + } + require(destinationRoutes(s.destination) == 1 && ownedRoutes() == 1, "unapproved expansion") + }) + require(approved != nil, "no controller proposal after low RTT") + s.assertMeasuredRTT() + if !rolledBack { + require(count(fmt.Sprintf("SELECT count() FROM xtcp.xtcp_flat_records_v2 WHERE timestamp_ns>now()-INTERVAL 20 SECOND AND treatment_assignment_id='%s' AND inet_diag_cong='cubic' AND treatment_algorithm_exposed", approved.Id)) >= 8, "missing actual CUBIC exposure") + s.event("canary_exposed", inspect(op, approved.Id)) + } + // Keep existing connections so maintenance sees the RTT regression on + // the treated sockets; the harness never requests a rollback. + highStarted := time.Now() + end = s.setPhase("high_automatic_rollback", 180, false) + s.until(end, func() { + e := inspect(op, approved.Id) + require(len(e.Phases) == 1, "controller promoted without review") + if e.Status == pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK && !rolledBack { + s.event("controller_rollback_observed", e) + check(validateSoakRollback(e, false)) + eventually("soak overrides withdrawn", time.Minute, func() bool { return ownedRoutes() == 0 }) + // Maintenance may deliver a low-RTT safety decision after the + // phase boundary. Classify its evidence, not its arrival time. + if injectedLatencyRollback(e, highStarted) { + s.event("controller_automatic_rollback", e) + latencyRollbacks++ + } else { + s.event("low_rtt_safety_rollback", e) + lowRTTRollbacks++ + } + rolledBack = true + } + if rolledBack { + require(e.Status == pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK, "rolled-back experiment was revived") + require(ownedRoutes() == 0, "rolled-back treatment restored") + } + }) + require(rolledBack, "controller did not roll back the impaired trial") + s.assertMeasuredRTT() + pass(fmt.Sprintf("SOAK_CYCLE_%d", cycle)) + } + require(latencyRollbacks > 0, "all %d trials withdrew at low RTT; injected-latency rollback was not exercised (see soak-events.jsonl)", lowRTTRollbacks) + // Restore a previously failed destination. A fresh low-RTT window must not + // bypass the unchanged 24-hour cooldown or revive the old assignment. + s.destination = "198.18.0.101" + end := s.setPhase("low_cooldown", 5, true) + s.until(end, func() { + e := s.current() + require(e != nil && e.Status == pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK, "cooldown state changed") + require(len(s.experiments()) == config.Cycles && ownedRoutes() == 0, "cooldown allowed a new action") + }) + s.assertMeasuredRTT() + s.event("cooldown_verified", s.current()) + pass("SOAK_COOLDOWN") + for _, h := range hosts { + st := status(h) + require(st.Main == mainRoutes[h] && st.DefaultCC == "reno", "%s baseline routing changed", h) + act(h, "healthy") + } + write(evidenceDir+"/soak-summary.json", must(json.MarshalIndent(map[string]any{"cycles": config.Cycles, "interval_seconds": config.IntervalSeconds, "elapsed_seconds": time.Since(s.started).Seconds(), "proposals": len(s.experiments()), "automatic_rollbacks": latencyRollbacks + lowRTTRollbacks, "injected_latency_rollbacks": latencyRollbacks, "low_rtt_safety_rollbacks": lowRTTRollbacks, "cooldown_verified": true}, "", " "))) + pass("SOAK") +} diff --git a/tools/tcp-controller-integration/soak_test.go b/tools/tcp-controller-integration/soak_test.go new file mode 100644 index 000000000..4ec5e4ac1 --- /dev/null +++ b/tools/tcp-controller-integration/soak_test.go @@ -0,0 +1,77 @@ +package main + +import ( + "strings" + "testing" + "time" + + pb "github.com/randomizedcoder/xtcp2/gen/go/xtcp_treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment" + "github.com/randomizedcoder/xtcp2/pkg/treatment/wire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestSoakRollbackEvidence(t *testing.T) { + now := time.Now() + baseline := &pb.Evidence{Id: "baseline", AnalyzedAt: timestamppb.New(now.Add(-3 * time.Minute)), WindowStart: timestamppb.New(now.Add(-4 * time.Minute)), WindowEnd: timestamppb.New(now.Add(-3 * time.Minute)), QueryVersion: "test", ArtifactSha256: strings.Repeat("a", 64), Hosts: []*pb.HostEvidence{{AgentId: "canary", Sockets: 32, BytesAcked: 1 << 25, GoodputBps: 4e6, RttP95Ms: 5.305, CollectionHealthy: true}}} + latest := proto.Clone(baseline).(*pb.Evidence) + latest.Id = "latest" + latest.AnalyzedAt = timestamppb.New(now) + latest.WindowStart = timestamppb.New(now.Add(-time.Minute)) + latest.WindowEnd = timestamppb.New(now.Add(-20 * time.Second)) + latest.Hosts[0].ExposedSockets = 32 + policy := wire.Policy(treatment.DefaultPolicy()) + policy.MaximumRttIncrease = 1 + fixture := &pb.Experiment{Status: pb.ExperimentStatus_EXPERIMENT_STATUS_ROLLED_BACK, CohortOrder: []string{"canary"}, Policy: policy, Baseline: baseline, LatestEvidence: latest, Phases: []*pb.Phase{{Outcome: pb.Outcome_OUTCOME_HARMFUL}}} + for _, tc := range []struct { + name string + injected, valid bool + change func(*pb.Experiment) + }{ + {"observed-early-loss", false, true, func(e *pb.Experiment) { e.LatestEvidence.Hosts[0].RetransmissionRatio = .010227199171467409 }}, + {"early-loss-is-not-latency-coverage", true, false, func(e *pb.Experiment) { e.LatestEvidence.Hosts[0].RetransmissionRatio = .010227199171467409 }}, + {"injected-latency", true, true, func(e *pb.Experiment) { e.LatestEvidence.Hosts[0].RttP95Ms = 180 }}, + {"healthy-evidence", false, false, func(e *pb.Experiment) {}}, + {"unexposed", false, false, func(e *pb.Experiment) { + e.LatestEvidence.Hosts[0].RttP95Ms = 180 + e.LatestEvidence.Hosts[0].ExposedSockets = 0 + }}, + {"missing-evidence", false, false, func(e *pb.Experiment) { e.LatestEvidence = nil }}, + {"wrong-outcome", false, false, func(e *pb.Experiment) { e.Phases[0].Outcome = pb.Outcome_OUTCOME_EXPIRED }}, + } { + t.Run(tc.name, func(t *testing.T) { + e := proto.Clone(fixture).(*pb.Experiment) + tc.change(e) + if err := validateSoakRollback(e, tc.injected); (err == nil) != tc.valid { + t.Fatalf("valid=%t err=%v", tc.valid, err) + } + if tc.name == "injected-latency" { + if !injectedLatencyRollback(e, now.Add(-time.Minute)) { + t.Fatal("lost injected latency coverage") + } + if injectedLatencyRollback(e, now.Add(-5*time.Second)) { + t.Fatal("pre-change evidence counted as injected latency") + } + } + }) + } +} + +func TestSoakConfigBounds(t *testing.T) { + for _, c := range []soakConfig{{3, 180}, {2, 180}, {6, 300}} { + if err := c.validate(); err != nil { + t.Fatal(err) + } + } + for _, c := range []soakConfig{{0, 180}, {1, 180}, {7, 180}, {3, 0}, {3, 179}, {3, 301}} { + if c.validate() == nil { + t.Fatalf("accepted unsafe/vacuous run: %+v", c) + } + } + for _, destination := range []string{"198.18.0.1", "192.168.1.254", "198.18.0.107", "198.18.0.101\nOTHER=value"} { + if validSoakDestination(destination) { + t.Fatalf("accepted %q", destination) + } + } +}