diff --git a/dgraph/cmd/alpha/admin.go b/dgraph/cmd/alpha/admin.go index 32f498853d4..62e1f248377 100644 --- a/dgraph/cmd/alpha/admin.go +++ b/dgraph/cmd/alpha/admin.go @@ -83,8 +83,6 @@ func getAdminMux() *http.ServeMux { http.MethodPut: true, http.MethodPost: true, }, adminAuthHandler(http.HandlerFunc(drainingHandler)))) - adminMux.Handle("/admin/export", allowedMethodsHandler(allowedMethods{http.MethodGet: true}, - adminAuthHandler(http.HandlerFunc(exportHandler)))) adminMux.Handle("/admin/config/cache_mb", allowedMethodsHandler(allowedMethods{ http.MethodGet: true, http.MethodPut: true, @@ -160,46 +158,6 @@ func shutDownHandler(w http.ResponseWriter, r *http.Request) { x.Check2(w.Write([]byte(`{"code": "Success", "message": "Server is shutting down"}`))) } -func exportHandler(w http.ResponseWriter, r *http.Request) { - if err := r.ParseForm(); err != nil { - x.SetHttpStatus(w, http.StatusBadRequest, "Parse of export request failed.") - return - } - - format := worker.DefaultExportFormat - if vals, ok := r.Form["format"]; ok { - if len(vals) > 1 { - x.SetHttpStatus(w, http.StatusBadRequest, - "Only one export format may be specified.") - return - } - format = worker.NormalizeExportFormat(vals[0]) - if format == "" { - x.SetHttpStatus(w, http.StatusBadRequest, "Invalid export format.") - return - } - } - - gqlReq := &schema.Request{ - Query: ` - mutation export($format: String) { - export(input: {format: $format}) { - response { - code - } - } - }`, - Variables: map[string]interface{}{}, - } - - if resp := resolveWithAdminServer(gqlReq, r, adminServer); len(resp.Errors) != 0 { - x.SetStatus(w, resp.Errors[0].Message, "Export failed.") - return - } - w.Header().Set("Content-Type", "application/json") - x.Check2(w.Write([]byte(`{"code": "Success", "message": "Export completed."}`))) -} - func memoryLimitHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: diff --git a/dgraph/cmd/alpha/admin_backup.go b/dgraph/cmd/alpha/admin_backup.go deleted file mode 100644 index ba6b5e62192..00000000000 --- a/dgraph/cmd/alpha/admin_backup.go +++ /dev/null @@ -1,68 +0,0 @@ -// +build !oss - -/* - * Copyright 2018 Dgraph Labs, Inc. and Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package alpha - -import ( - "net/http" - - "github.com/dgraph-io/dgraph/graphql/schema" - - "github.com/dgraph-io/dgraph/x" - "github.com/golang/glog" -) - -func init() { - http.Handle("/admin/backup", allowedMethodsHandler(allowedMethods{http.MethodPost: true}, - adminAuthHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - backupHandler(w, r) - })))) -} - -// backupHandler handles backup requests coming from the HTTP endpoint. -func backupHandler(w http.ResponseWriter, r *http.Request) { - gqlReq := &schema.Request{ - Query: ` - mutation backup($input: BackupInput!) { - backup(input: $input) { - response { - code - } - } - }`, - Variables: map[string]interface{}{"input": map[string]interface{}{ - "destination": r.FormValue("destination"), - "accessKey": r.FormValue("access_key"), - "secretKey": r.FormValue("secret_key"), - "sessionToken": r.FormValue("session_token"), - "anonymous": r.FormValue("anonymous") == "true", - "forceFull": r.FormValue("force_full") == "true", - }}, - } - glog.Infof("gqlReq %+v, r %+v adminServer %+v", gqlReq, r, adminServer) - resp := resolveWithAdminServer(gqlReq, r, adminServer) - if resp.Errors != nil { - x.SetStatus(w, resp.Errors.Error(), "Backup failed.") - return - } - - w.Header().Set("Content-Type", "application/json") - x.Check2(w.Write([]byte(`{` + - `"code": "Success", ` + - `"message": "Backup queued successfully, please check /health for status."}`))) -} diff --git a/dgraph/cmd/alpha/run.go b/dgraph/cmd/alpha/run.go index 881f3fff6cb..761ee81ef14 100644 --- a/dgraph/cmd/alpha/run.go +++ b/dgraph/cmd/alpha/run.go @@ -749,6 +749,7 @@ func run() { glog.Infof("worker.Config: %+v", worker.Config) worker.InitServerState() + worker.InitTasks() if Alpha.Conf.GetBool("expose_trace") { // TODO: Remove this once we get rid of event logs. diff --git a/dgraph/cmd/bulk/mapper.go b/dgraph/cmd/bulk/mapper.go index 442bbe027c9..604c05080ce 100644 --- a/dgraph/cmd/bulk/mapper.go +++ b/dgraph/cmd/bulk/mapper.go @@ -57,10 +57,10 @@ type shardState struct { func newMapperBuffer(opt *options) *z.Buffer { sz := float64(opt.MapBufSize) * 1.1 - buf, err := z.NewBufferWithDir(int(sz), 2*int(opt.MapBufSize), z.UseMmap, - filepath.Join(opt.TmpDir, bufferDir), "Mapper.Buffer") + tmpDir := filepath.Join(opt.TmpDir, bufferDir) + buf, err := z.NewBufferTmp(tmpDir, int(sz)) x.Check(err) - return buf + return buf.WithMaxSize(2 * int(opt.MapBufSize)) } func newMapper(st *state) *mapper { diff --git a/dgraph/cmd/bulk/reduce.go b/dgraph/cmd/bulk/reduce.go index 6bc714633c9..a898149fd27 100644 --- a/dgraph/cmd/bulk/reduce.go +++ b/dgraph/cmd/bulk/reduce.go @@ -434,11 +434,9 @@ func bufferStats(cbuf *z.Buffer) { } func getBuf(dir string) *z.Buffer { - cbuf, err := z.NewBufferWithDir(64<<20, 64<<30, z.UseCalloc, - filepath.Join(dir, bufferDir), "Reducer.GetBuf") - x.Check(err) - cbuf.AutoMmapAfter(1 << 30) - return cbuf + return z.NewBuffer(64<<20, "Reducer.GetBuf"). + WithAutoMmap(1<<30, filepath.Join(dir, bufferDir)). + WithMaxSize(64 << 30) } func (r *reducer) reduce(partitionKeys [][]byte, mapItrs []*mapIterator, ci *countIndexer) { diff --git a/dgraph/cmd/zero/oracle.go b/dgraph/cmd/zero/oracle.go index c1c0b424437..4df2de2af37 100644 --- a/dgraph/cmd/zero/oracle.go +++ b/dgraph/cmd/zero/oracle.go @@ -59,15 +59,16 @@ func (o *Oracle) Init() { o.commits = make(map[uint64]uint64) // Remove the older btree file, before creating NewTree, as it may contain stale data leading // to wrong results. - o.keyCommit = z.NewTree() + o.keyCommit = z.NewTree("oracle") o.subscribers = make(map[int]chan pb.OracleDelta) o.updates = make(chan *pb.OracleDelta, 100000) // Keeping 1 second worth of updates. o.doneUntil.Init(nil) go o.sendDeltasToSubscribers() } -// oracle close releases the memory associated with btree used for keycommit. +// close releases the memory associated with btree used for keycommit. func (o *Oracle) close() { + o.keyCommit.Close() } func (o *Oracle) updateStartTxnTs(ts uint64) { diff --git a/dgraph/cmd/zero/run.go b/dgraph/cmd/zero/run.go index 4d72952c8f8..0bdd3a9974b 100644 --- a/dgraph/cmd/zero/run.go +++ b/dgraph/cmd/zero/run.go @@ -127,7 +127,7 @@ instances to achieve high-availability. Head("Audit options"). Flag("output", `[stdout, /path/to/dir] This specifies where audit logs should be output to. - "stdout" is for standard output. You can also specify the directory where audit logs + "stdout" is for standard output. You can also specify the directory where audit logs will be saved. When stdout is specified as output other fields will be ignored.`). Flag("compress", "Enables the compression of old audit logs."). diff --git a/go.mod b/go.mod index 2f3d0b462ea..d098a0f0bf0 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/dgraph-io/gqlgen v0.13.2 github.com/dgraph-io/gqlparser/v2 v2.2.0 github.com/dgraph-io/graphql-transport-ws v0.0.0-20210223074046-e5b8b80bb4ed - github.com/dgraph-io/ristretto v0.0.4-0.20210310100713-a4346e5d1f90 + github.com/dgraph-io/ristretto v0.0.4-0.20210504190834-0bf2acd73aa3 github.com/dgraph-io/simdjson-go v0.3.0 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 diff --git a/go.sum b/go.sum index e043e8f4ba5..722f7ca814a 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= @@ -129,8 +131,8 @@ github.com/dgraph-io/gqlparser/v2 v2.2.0/go.mod h1:MYS4jppjyx8b9tuUtjV7jU1UFZK6P github.com/dgraph-io/graphql-transport-ws v0.0.0-20210223074046-e5b8b80bb4ed h1:pgGMBoTtFhR+xkyzINaToLYRurHn+6pxMYffIGmmEPc= github.com/dgraph-io/graphql-transport-ws v0.0.0-20210223074046-e5b8b80bb4ed/go.mod h1:7z3c/5w0sMYYZF5bHsrh8IH4fKwG5O5Y70cPH1ZLLRQ= github.com/dgraph-io/ristretto v0.0.4-0.20210309073149-3836124cdc5a/go.mod h1:MIonLggsKgZLUSt414ExgwNtlOL5MuEoAJP514mwGe8= -github.com/dgraph-io/ristretto v0.0.4-0.20210310100713-a4346e5d1f90 h1:arWVlUO9NhZ/2vWprIqpe825GISUPpgJhU/b0ep3j/M= -github.com/dgraph-io/ristretto v0.0.4-0.20210310100713-a4346e5d1f90/go.mod h1:MIonLggsKgZLUSt414ExgwNtlOL5MuEoAJP514mwGe8= +github.com/dgraph-io/ristretto v0.0.4-0.20210504190834-0bf2acd73aa3 h1:jU/wpYsEL+8JPLf/QcjkQKI5g0dOjSuwcMjkThxt5x0= +github.com/dgraph-io/ristretto v0.0.4-0.20210504190834-0bf2acd73aa3/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgraph-io/simdjson-go v0.3.0 h1:h71LO7vR4LHMPUhuoGN8bqGm1VNfGOlAG8BI6iDUKw0= github.com/dgraph-io/simdjson-go v0.3.0/go.mod h1:Otpysdjaxj9OGaJusn4pgQV7OFh2bELuHANq0I78uvY= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= diff --git a/graphql/admin/admin.go b/graphql/admin/admin.go index 33ef7068491..203c6c5a914 100644 --- a/graphql/admin/admin.go +++ b/graphql/admin/admin.go @@ -55,9 +55,9 @@ const ( """ The UInt64 scalar type represents an unsigned 64‐bit numeric non‐fractional value. UInt64 can represent values in range [0,(2^64 - 1)]. - """ + """ scalar UInt64 - + """ The DateTime scalar type represents date and time as a string in RFC3339 format. For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC. @@ -243,14 +243,19 @@ const ( anonymous: Boolean } + input TaskInput { + id: String! + } + type Response { code: String message: String } type ExportPayload { - response: Response exportedFiles: [String] + response: Response + taskId: String } type DrainingPayload { @@ -261,6 +266,26 @@ const ( response: Response } + type TaskPayload { + kind: TaskKind + status: TaskStatus + lastUpdated: DateTime + } + + enum TaskStatus { + Queued + Running + Failed + Success + Unknown + } + + enum TaskKind { + Backup + Export + Unknown + } + input ConfigInput { """ Estimated memory the caches can take. Actual usage by the process would be @@ -367,6 +392,7 @@ const ( health: [NodeState] state: MembershipState config: Config + task(input: TaskInput!): TaskPayload ` + adminQueries + ` } @@ -718,7 +744,6 @@ func newAdminResolver( } func newAdminResolverFactory() resolve.ResolverFactory { - adminMutationResolvers := map[string]resolve.MutationResolverFunc{ "addNamespace": resolveAddNamespace, "backup": resolveBackup, @@ -751,18 +776,21 @@ func newAdminResolverFactory() resolve.ResolverFactory { WithQueryResolver("listBackups", func(q schema.Query) resolve.QueryResolver { return resolve.QueryResolverFunc(resolveListBackups) }). - WithMutationResolver("updateGQLSchema", func(m schema.Mutation) resolve.MutationResolver { - return resolve.MutationResolverFunc( - func(ctx context.Context, m schema.Mutation) (*resolve.Resolved, bool) { - return &resolve.Resolved{Err: errors.Errorf(errMsgServerNotReady), Field: m}, - false - }) + WithQueryResolver("task", func(q schema.Query) resolve.QueryResolver { + return resolve.QueryResolverFunc(resolveTask) }). WithQueryResolver("getGQLSchema", func(q schema.Query) resolve.QueryResolver { return resolve.QueryResolverFunc( func(ctx context.Context, query schema.Query) *resolve.Resolved { return &resolve.Resolved{Err: errors.Errorf(errMsgServerNotReady), Field: q} }) + }). + WithMutationResolver("updateGQLSchema", func(m schema.Mutation) resolve.MutationResolver { + return resolve.MutationResolverFunc( + func(ctx context.Context, m schema.Mutation) (*resolve.Resolved, bool) { + return &resolve.Resolved{Err: errors.Errorf(errMsgServerNotReady), Field: m}, + false + }) }) for gqlMut, resolver := range adminMutationResolvers { // gotta force go to evaluate the right function at each loop iteration diff --git a/graphql/admin/backup.go b/graphql/admin/backup.go index 02d1812726f..959515c6d74 100644 --- a/graphql/admin/backup.go +++ b/graphql/admin/backup.go @@ -19,6 +19,7 @@ package admin import ( "context" "encoding/json" + "fmt" "github.com/dgraph-io/dgraph/graphql/resolve" "github.com/dgraph-io/dgraph/graphql/schema" @@ -34,29 +35,39 @@ type backupInput struct { func resolveBackup(ctx context.Context, m schema.Mutation) (*resolve.Resolved, bool) { glog.Info("Got backup request") + if !worker.EnterpriseEnabled() { + err := fmt.Errorf("you must enable enterprise features first. " + + "Supply the appropriate license file to Dgraph Zero using the HTTP endpoint.") + return resolve.EmptyResult(m, err), false + } input, err := getBackupInput(m) if err != nil { return resolve.EmptyResult(m, err), false } + if input.Destination == "" { + err := fmt.Errorf("you must specify a 'destination' value") + return resolve.EmptyResult(m, err), false + } - err = worker.ProcessBackupRequest(context.Background(), &pb.BackupRequest{ + req := &pb.BackupRequest{ Destination: input.Destination, AccessKey: input.AccessKey, SecretKey: input.SecretKey, SessionToken: input.SessionToken, Anonymous: input.Anonymous, - }, input.ForceFull) - + } + taskId, err := worker.Tasks.Enqueue(req) if err != nil { return resolve.EmptyResult(m, err), false } + msg := fmt.Sprintf("Backup queued with ID %#x", taskId) + data := response("Success", msg) + data["taskId"] = fmt.Sprintf("%#x", taskId) return resolve.DataResult( m, - map[string]interface{}{ - m.Name(): response("Success", "Backup queued successfully, please check /health for status."), - }, + map[string]interface{}{m.Name(): data}, nil, ), true } diff --git a/graphql/admin/endpoints_ee.go b/graphql/admin/endpoints_ee.go index 819caa93da4..9618461d192 100644 --- a/graphql/admin/endpoints_ee.go +++ b/graphql/admin/endpoints_ee.go @@ -48,6 +48,7 @@ const adminTypes = ` type BackupPayload { response: Response + taskId: String } input RestoreInput { diff --git a/graphql/admin/export.go b/graphql/admin/export.go index f778c18d6a4..742e86b9582 100644 --- a/graphql/admin/export.go +++ b/graphql/admin/export.go @@ -19,6 +19,7 @@ package admin import ( "context" "encoding/json" + "fmt" "math" "github.com/dgraph-io/dgraph/graphql/resolve" @@ -39,7 +40,6 @@ type exportInput struct { } func resolveExport(ctx context.Context, m schema.Mutation) (*resolve.Resolved, bool) { - glog.Info("Got export request through GraphQL admin API") input, err := getExportInput(m) @@ -83,7 +83,7 @@ func resolveExport(ctx context.Context, m schema.Mutation) (*resolve.Resolved, b return resolve.EmptyResult(m, err), false } - files, err := worker.ExportOverNetwork(ctx, &pb.ExportRequest{ + req := &pb.ExportRequest{ Format: format, Namespace: exportNs, Destination: input.Destination, @@ -91,30 +91,22 @@ func resolveExport(ctx context.Context, m schema.Mutation) (*resolve.Resolved, b SecretKey: input.SecretKey, SessionToken: input.SessionToken, Anonymous: input.Anonymous, - }) + } + taskId, err := worker.Tasks.Enqueue(req) if err != nil { return resolve.EmptyResult(m, err), false } - responseData := response("Success", "Export completed.") - responseData["exportedFiles"] = toInterfaceSlice(files) - + msg := fmt.Sprintf("Export queued with ID %#x", taskId) + data := response("Success", msg) + data["taskId"] = fmt.Sprintf("%#x", taskId) return resolve.DataResult( m, - map[string]interface{}{m.Name(): responseData}, + map[string]interface{}{m.Name(): data}, nil, ), true } -// toInterfaceSlice converts []string to []interface{} -func toInterfaceSlice(in []string) []interface{} { - out := make([]interface{}, 0, len(in)) - for _, s := range in { - out = append(out, s) - } - return out -} - func getExportInput(m schema.Mutation) (*exportInput, error) { inputArg := m.ArgValue(schema.InputArgName) inputByts, err := json.Marshal(inputArg) diff --git a/graphql/admin/task.go b/graphql/admin/task.go new file mode 100644 index 00000000000..e8d09296ce9 --- /dev/null +++ b/graphql/admin/task.go @@ -0,0 +1,82 @@ +/* + * Copyright 2021 Dgraph Labs, Inc. and Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package admin + +import ( + "context" + "encoding/json" + "fmt" + "strconv" + "time" + + "github.com/dgraph-io/dgraph/graphql/resolve" + "github.com/dgraph-io/dgraph/graphql/schema" + "github.com/dgraph-io/dgraph/protos/pb" + "github.com/dgraph-io/dgraph/worker" + "github.com/pkg/errors" +) + +type taskInput struct { + Id string +} + +func resolveTask(ctx context.Context, q schema.Query) *resolve.Resolved { + // Get Task ID. + input, err := getTaskInput(q) + if err != nil { + return resolve.EmptyResult(q, err) + } + if input.Id == "" { + return resolve.EmptyResult(q, fmt.Errorf("task ID is missing")) + } + taskId, err := strconv.ParseUint(input.Id, 0, 64) + if err != nil { + err = errors.Wrapf(err, "invalid task ID: %s", input.Id) + return resolve.EmptyResult(q, err) + } + + // Get TaskMeta from network. + req := &pb.TaskStatusRequest{TaskId: taskId} + resp, err := worker.TaskStatusOverNetwork(context.Background(), req) + if err != nil { + return resolve.EmptyResult(q, err) + } + meta := worker.TaskMeta(resp.GetTaskMeta()) + return resolve.DataResult( + q, + map[string]interface{}{q.Name(): map[string]interface{}{ + "kind": meta.Kind().String(), + "status": meta.Status().String(), + "lastUpdated": meta.Timestamp().Format(time.RFC3339), + }}, + nil, + ) +} + +func getTaskInput(q schema.Query) (*taskInput, error) { + inputArg := q.ArgValue(schema.InputArgName) + inputBytes, err := json.Marshal(inputArg) + if err != nil { + return nil, schema.GQLWrapf(err, "couldn't get input argument") + } + + var input taskInput + if err := json.Unmarshal(inputBytes, &input); err != nil { + return nil, schema.GQLWrapf(err, "couldn't get input argument") + } + return &input, nil +} diff --git a/graphql/e2e/custom_logic/cmd/main.go b/graphql/e2e/custom_logic/cmd/main.go index 75a81df7c98..a639235a661 100644 --- a/graphql/e2e/custom_logic/cmd/main.go +++ b/graphql/e2e/custom_logic/cmd/main.go @@ -824,7 +824,7 @@ func deleteCommonHeaders(headers http.Header) { func carsHandlerWithHeaders(w http.ResponseWriter, r *http.Request) { deleteCommonHeaders(r.Header) if err := compareHeaders(map[string][]string{ - "Stripe-Api-Key": {"some-api-key"}, + "Stripe-Api-Key": []string{"some-api-key"}, }, r.Header); err != nil { check2(w.Write([]byte(err.Error()))) return @@ -835,7 +835,7 @@ func carsHandlerWithHeaders(w http.ResponseWriter, r *http.Request) { func userNameHandlerWithHeaders(w http.ResponseWriter, r *http.Request) { deleteCommonHeaders(r.Header) if err := compareHeaders(map[string][]string{ - "Github-Api-Token": {"some-api-token"}, + "Github-Api-Token": []string{"some-api-token"}, }, r.Header); err != nil { check2(w.Write([]byte(err.Error()))) return @@ -1025,45 +1025,45 @@ func (r countryResolver) Name() *string { return &(r.c.Name) } -func (*query) Country(ctx context.Context, args struct { +func (_ *query) Country(ctx context.Context, args struct { Code string }) countryResolver { return countryResolver{&country{Code: graphql.ID(args.Code), Name: "Burundi"}} } -func (*query) Countries(ctx context.Context, args struct { +func (_ *query) Countries(ctx context.Context, args struct { Filter struct { Code string Name string } }) []countryResolver { - return []countryResolver{{&country{ + return []countryResolver{countryResolver{&country{ Code: graphql.ID(args.Filter.Code), Name: args.Filter.Name, }}} } -func (*query) ValidCountries(ctx context.Context, args struct { +func (_ *query) ValidCountries(ctx context.Context, args struct { Code string }) *[]*countryResolver { return &[]*countryResolver{{&country{Code: graphql.ID(args.Code), Name: "Burundi"}}} } -func (*query) UserName(ctx context.Context, args struct { +func (_ *query) UserName(ctx context.Context, args struct { Id string }) *string { s := fmt.Sprintf(`uname-%s`, args.Id) return &s } -func (*query) TeacherName(ctx context.Context, args struct { +func (_ *query) TeacherName(ctx context.Context, args struct { Id string }) *string { s := fmt.Sprintf(`tname-%s`, args.Id) return &s } -func (*query) SchoolName(ctx context.Context, args struct { +func (_ *query) SchoolName(ctx context.Context, args struct { Id string }) *string { s := fmt.Sprintf(`sname-%s`, args.Id) @@ -1117,7 +1117,7 @@ func (r *carResolver) Name() string { return "car-" + string(r.c.ID) } -func (*query) Car(ctx context.Context, args struct { +func (_ *query) Car(ctx context.Context, args struct { Id string }) *carResolver { return &carResolver{&car{ID: graphql.ID(args.Id)}} @@ -1139,13 +1139,13 @@ func (r *classResolver) Name() string { return "class-" + string(r.c.ID) } -func (*query) Class(ctx context.Context, args struct { +func (_ *query) Class(ctx context.Context, args struct { Id string }) *[]*classResolver { - return &[]*classResolver{{&class{ID: graphql.ID(args.Id)}}} + return &[]*classResolver{&classResolver{&class{ID: graphql.ID(args.Id)}}} } -func (*query) UserNames(ctx context.Context, args struct { +func (_ *query) UserNames(ctx context.Context, args struct { Users *[]*struct { Id string Age float64 @@ -1162,7 +1162,7 @@ func (*query) UserNames(ctx context.Context, args struct { return &res } -func (*query) Cars(ctx context.Context, args struct { +func (_ *query) Cars(ctx context.Context, args struct { Users *[]*struct { Id string Age float64 @@ -1178,7 +1178,7 @@ func (*query) Cars(ctx context.Context, args struct { return &resolvers } -func (*query) Classes(ctx context.Context, args struct { +func (_ *query) Classes(ctx context.Context, args struct { Schools *[]*struct { Id string Established float64 @@ -1190,12 +1190,12 @@ func (*query) Classes(ctx context.Context, args struct { resolvers := make([]*[]*classResolver, 0, len(*args.Schools)) for _, user := range *args.Schools { resolvers = append(resolvers, &[]*classResolver{ - {&class{ID: graphql.ID(user.Id)}}}) + &classResolver{&class{ID: graphql.ID(user.Id)}}}) } return &resolvers } -func (*query) TeacherNames(ctx context.Context, args struct { +func (_ *query) TeacherNames(ctx context.Context, args struct { Teachers *[]*struct { Tid string Age float64 @@ -1212,7 +1212,7 @@ func (*query) TeacherNames(ctx context.Context, args struct { return &res } -func (*query) SchoolNames(ctx context.Context, args struct { +func (_ *query) SchoolNames(ctx context.Context, args struct { Schools *[]*struct { Id string Established float64 @@ -1264,8 +1264,12 @@ func gqlCarsWithErrorHandler(w http.ResponseWriter, r *http.Request) { "cars": output, }, "errors": []map[string]interface{}{ - {"message": "error-1 from cars"}, - {"message": "error-2 from cars"}, + map[string]interface{}{ + "message": "error-1 from cars", + }, + map[string]interface{}{ + "message": "error-2 from cars", + }, }, } diff --git a/graphql/e2e/custom_logic/custom_logic_test.go b/graphql/e2e/custom_logic/custom_logic_test.go index 67bd722bfe6..b1b28d83190 100644 --- a/graphql/e2e/custom_logic/custom_logic_test.go +++ b/graphql/e2e/custom_logic/custom_logic_test.go @@ -200,9 +200,9 @@ func TestCustomQueryShouldForwardHeaders(t *testing.T) { params := &common.GraphQLParams{ Query: query, Headers: map[string][]string{ - "X-App-Token": {"app-token"}, - "X-User-Id": {"123"}, - "Random-header": {"random"}, + "X-App-Token": []string{"app-token"}, + "X-User-Id": []string{"123"}, + "Random-header": []string{"random"}, }, } @@ -238,9 +238,9 @@ func TestCustomNameForwardHeaders(t *testing.T) { params := &common.GraphQLParams{ Query: query, Headers: map[string][]string{ - "App": {"app-token"}, - "X-User-Id": {"123"}, - "Random-header": {"random"}, + "App": []string{"app-token"}, + "X-User-Id": []string{"123"}, + "Random-header": []string{"random"}, }, } @@ -2618,7 +2618,7 @@ func TestCustomDQL(t *testing.T) { } } """) - + dqlTweetsByAuthorFollowers: [Tweets] @custom(dql: """ query { var(func: type(Tweets)) @filter(anyoftext(Tweets.text, "DQL")) { @@ -2634,7 +2634,7 @@ func TestCustomDQL(t *testing.T) { } } """) - + filteredTweetsByAuthorFollowers(search: String!): [Tweets] @custom(dql: """ query t($search: string) { var(func: type(Tweets)) @filter(anyoftext(Tweets.text, $search)) { @@ -2859,7 +2859,7 @@ func TestCustomGetQuerywithRESTError(t *testing.T) { func TestCustomFieldsWithRestError(t *testing.T) { schema := ` type Car @remote { - id: ID! + id: ID! name: String! } @@ -2883,7 +2883,7 @@ func TestCustomFieldsWithRestError(t *testing.T) { body: "{uid: $id}" mode: BATCH, } - ) + ) } ` @@ -2931,7 +2931,7 @@ func TestCustomFieldsWithRestError(t *testing.T) { "age": 10, "cars": { "name": "car-0x1" - } + } } ] }` @@ -3005,7 +3005,7 @@ func TestCustomResolverInInterfaceImplFrag(t *testing.T) { id: ID! name: String! @id } - + type Human implements Character { totalCredits: Int bio: String @custom(http: { @@ -3079,23 +3079,23 @@ func TestCustomFieldIsResolvedWhenNoModeGiven(t *testing.T) { skipIntrospection: true, }) } - + type Blueprint { blueprintId: String! @id shallowProducts: [ItemType] deepProducts: [BlueprintProduct] } - + type BlueprintProduct { itemType: ItemType amount: Int } - + type MarketStats { typeId: String! @id - price: Float + price: Float } - + type MarketStatsR @remote { typeId: String price: Float diff --git a/protos/pb.proto b/protos/pb.proto index fdc00a213bf..0b53154b944 100644 --- a/protos/pb.proto +++ b/protos/pb.proto @@ -14,7 +14,6 @@ * limitations under the License. */ - // Style guide for Protocol Buffer 3. // Use CamelCase (with an initial capital) for message names – for example, // SongServerRequest. Use underscore_separated_names for field names – for @@ -36,658 +35,683 @@ import "github.com/gogo/protobuf/gogoproto/gogo.proto"; /* option (gogoproto.goproto_getters_all) = true; */ message List { - repeated fixed64 uids = 1; + repeated fixed64 uids = 1; } message TaskValue { - bytes val = 1; - Posting.ValType val_type = 2; + bytes val = 1; + Posting.ValType val_type = 2; } message SrcFunction { - string name = 1; - repeated string args = 3; - bool isCount = 4; + string name = 1; + repeated string args = 3; + bool isCount = 4; } message Query { - string attr = 1; - repeated string langs = 2; // language list for attribute - fixed64 after_uid = 3; // Only return UIDs greater than this. - bool do_count = 4; // Are we just getting lengths? + string attr = 1; + repeated string langs = 2; // language list for attribute + fixed64 after_uid = 3; // Only return UIDs greater than this. + bool do_count = 4; // Are we just getting lengths? - // Exactly one of uids and terms is populated. - List uid_list = 5; + // Exactly one of uids and terms is populated. + List uid_list = 5; - // Function to generate or filter UIDs. - SrcFunction src_func = 6; + // Function to generate or filter UIDs. + SrcFunction src_func = 6; - bool reverse = 7; // Whether this is a reverse edge. + bool reverse = 7; // Whether this is a reverse edge. - FacetParams facet_param = 8; // which facets to fetch - FilterTree facets_filter = 9; // filtering on facets : has Op (and/or/not) tree + FacetParams facet_param = 8; // which facets to fetch + FilterTree facets_filter = + 9; // filtering on facets : has Op (and/or/not) tree - bool expand_all = 10; // expand all language variants. + bool expand_all = 10; // expand all language variants. - uint64 read_ts = 13; - int32 cache = 14; - int32 first = 15; // used to limit the number of result. Typically, the count is value of first - // field. Now, It's been used only for has query. + uint64 read_ts = 13; + int32 cache = 14; + int32 first = 15; // used to limit the number of result. Typically, the count + // is value of first + // field. Now, It's been used only for has query. } message ValueList { - repeated TaskValue values = 1; + repeated TaskValue values = 1; } message LangList { - repeated string lang = 1; + repeated string lang = 1; } message Result { - repeated List uid_matrix = 1; - repeated ValueList value_matrix = 2; - repeated uint32 counts = 3; - bool intersect_dest = 4; - repeated FacetsList facet_matrix = 5; - repeated LangList lang_matrix = 6; - bool list = 7; + repeated List uid_matrix = 1; + repeated ValueList value_matrix = 2; + repeated uint32 counts = 3; + bool intersect_dest = 4; + repeated FacetsList facet_matrix = 5; + repeated LangList lang_matrix = 6; + bool list = 7; } message Order { - string attr = 1; - bool desc = 2; - repeated string langs = 3; + string attr = 1; + bool desc = 2; + repeated string langs = 3; } message SortMessage { - repeated Order order = 1; - repeated List uid_matrix = 2; - int32 count = 3; // Return this many elements. - int32 offset = 4; // Skip this many elements. + repeated Order order = 1; + repeated List uid_matrix = 2; + int32 count = 3; // Return this many elements. + int32 offset = 4; // Skip this many elements. - uint64 read_ts = 13; + uint64 read_ts = 13; } message SortResult { - repeated List uid_matrix = 1; + repeated List uid_matrix = 1; } message RaftContext { - fixed64 id = 1; - uint32 group = 2; - string addr = 3; - uint64 snapshot_ts = 4; - bool is_learner = 5; + fixed64 id = 1; + uint32 group = 2; + string addr = 3; + uint64 snapshot_ts = 4; + bool is_learner = 5; } // Member stores information about RAFT group member for a single RAFT node. -// Note that each server can be serving multiple RAFT groups. Each group would have -// one RAFT node per server serving that group. +// Note that each server can be serving multiple RAFT groups. Each group would +// have one RAFT node per server serving that group. message Member { - fixed64 id = 1; - uint32 group_id = 2 [(gogoproto.jsontag) = "groupId,omitempty"]; - string addr = 3; - bool leader = 4; - bool am_dead = 5 [(gogoproto.jsontag) = "amDead,omitempty"]; - uint64 last_update = 6 [(gogoproto.jsontag) = "lastUpdate,omitempty"]; - bool learner = 7; + fixed64 id = 1; + uint32 group_id = 2 [(gogoproto.jsontag) = "groupId,omitempty"]; + string addr = 3; + bool leader = 4; + bool am_dead = 5 [(gogoproto.jsontag) = "amDead,omitempty"]; + uint64 last_update = 6 [(gogoproto.jsontag) = "lastUpdate,omitempty"]; + bool learner = 7; - bool cluster_info_only = 13 [(gogoproto.jsontag) = "clusterInfoOnly,omitempty"]; - bool force_group_id = 14 [(gogoproto.jsontag) = "forceGroupId,omitempty"]; + bool cluster_info_only = 13 + [(gogoproto.jsontag) = "clusterInfoOnly,omitempty"]; + bool force_group_id = 14 [(gogoproto.jsontag) = "forceGroupId,omitempty"]; } message Group { - map members = 1; // Raft ID is the key. - map tablets = 2; // Predicate + others are key. - uint64 snapshot_ts = 3; // Stores Snapshot transaction ts. - uint64 checksum = 4; // Stores a checksum. - uint64 checkpoint_ts = 5; // Stores checkpoint ts as seen by leader. + map members = 1; // Raft ID is the key. + map tablets = 2; // Predicate + others are key. + uint64 snapshot_ts = 3; // Stores Snapshot transaction ts. + uint64 checksum = 4; // Stores a checksum. + uint64 checkpoint_ts = 5; // Stores checkpoint ts as seen by leader. } message License { - string user = 1; - uint64 maxNodes = 2; - int64 expiryTs = 3; - bool enabled = 4; + string user = 1; + uint64 maxNodes = 2; + int64 expiryTs = 3; + bool enabled = 4; } message ZeroProposal { - reserved 8; // Was used for string key. - map snapshot_ts = 1; // Group ID -> Snapshot Ts. - Member member = 2; - Tablet tablet = 3; - uint64 maxUID = 4; - uint64 maxTxnTs = 5; - uint64 maxNsID = 12; - uint64 maxRaftId = 6; - api.TxnContext txn = 7; - string cid = 9; // Used as unique identifier for the cluster. - License license = 10; - ZeroSnapshot snapshot = 11; // Used to make Zeros take a snapshot. - // 12 has already been used. - DeleteNsRequest delete_ns = 13; // Used to delete namespace. -} - -// MembershipState is used to pack together the current membership state of all the nodes -// in the caller server; and the membership updates recorded by the callee server since -// the provided lastUpdate. + reserved 8; // Was used for string key. + map snapshot_ts = 1; // Group ID -> Snapshot Ts. + Member member = 2; + Tablet tablet = 3; + uint64 maxUID = 4; + uint64 maxTxnTs = 5; + uint64 maxNsID = 12; + uint64 maxRaftId = 6; + api.TxnContext txn = 7; + string cid = 9; // Used as unique identifier for the cluster. + License license = 10; + ZeroSnapshot snapshot = 11; // Used to make Zeros take a snapshot. + // 12 has already been used. + DeleteNsRequest delete_ns = 13; // Used to delete namespace. +} + +// MembershipState is used to pack together the current membership state of all +// the nodes in the caller server; and the membership updates recorded by the +// callee server since the provided lastUpdate. message MembershipState { - uint64 counter = 1; // used to find latest membershipState in case of race. - map groups = 2; - map zeros = 3; - uint64 maxUID = 4; - uint64 maxTxnTs = 5; - uint64 maxNsID = 10; - uint64 maxRaftId = 6; - repeated Member removed = 7; - string cid = 8; // Used to uniquely identify the Dgraph cluster. - License license = 9; - // 10 has already been used. + uint64 counter = 1; // used to find latest membershipState in case of race. + map groups = 2; + map zeros = 3; + uint64 maxUID = 4; + uint64 maxTxnTs = 5; + uint64 maxNsID = 10; + uint64 maxRaftId = 6; + repeated Member removed = 7; + string cid = 8; // Used to uniquely identify the Dgraph cluster. + License license = 9; + // 10 has already been used. } message ConnectionState { - Member member = 1; - MembershipState state = 2; - uint64 max_pending = 3; // Used to determine the timstamp for reading after bulk load + Member member = 1; + MembershipState state = 2; + uint64 max_pending = + 3; // Used to determine the timstamp for reading after bulk load } message HealthInfo { - string instance = 1; - string address = 2; - string status = 3; - string group = 4; // string so group = 0 can be printed in JSON. - string version = 5; - int64 uptime = 6; - int64 lastEcho = 7; - repeated string ongoing = 8; - repeated string indexing = 9; - repeated string ee_features = 10; - uint64 max_assigned = 11; + string instance = 1; + string address = 2; + string status = 3; + string group = 4; // string so group = 0 can be printed in JSON. + string version = 5; + int64 uptime = 6; + int64 lastEcho = 7; + repeated string ongoing = 8; + repeated string indexing = 9; + repeated string ee_features = 10; + uint64 max_assigned = 11; } message Tablet { - uint32 group_id = 1 [(gogoproto.jsontag) = "groupId,omitempty"]; // Served by which group. - string predicate = 2; - bool force = 3; // Used while moving predicate. - int64 on_disk_bytes = 7; - bool remove = 8; - bool read_only = 9 [(gogoproto.jsontag) = "readOnly,omitempty"]; // If true, do not ask zero to serve any tablets. - uint64 move_ts = 10 [(gogoproto.jsontag) = "moveTs,omitempty"]; - int64 uncompressed_bytes = 11; // Estimated uncompressed size of tablet in bytes + uint32 group_id = 1 + [(gogoproto.jsontag) = "groupId,omitempty"]; // Served by which group. + string predicate = 2; + bool force = 3; // Used while moving predicate. + int64 on_disk_bytes = 7; + bool remove = 8; + bool read_only = 9 [ + (gogoproto.jsontag) = "readOnly,omitempty" + ]; // If true, do not ask zero to serve any tablets. + uint64 move_ts = 10 [(gogoproto.jsontag) = "moveTs,omitempty"]; + int64 uncompressed_bytes = + 11; // Estimated uncompressed size of tablet in bytes } message DirectedEdge { - reserved 6; // This was used for label. - fixed64 entity = 1; // Subject or source node / UID. - string attr = 2; // Attribute or predicate. Labels the edge. - bytes value = 3; // Edge points to a value. - Posting.ValType value_type = 4; // The type of the value - fixed64 value_id = 5; // Object or destination node / UID. - string lang = 7; - enum Op { - SET = 0; - DEL = 1; - } - Op op = 8; - repeated api.Facet facets = 9; - repeated string allowedPreds = 10; - uint64 namespace = 11; + reserved 6; // This was used for label. + fixed64 entity = 1; // Subject or source node / UID. + string attr = 2; // Attribute or predicate. Labels the edge. + bytes value = 3; // Edge points to a value. + Posting.ValType value_type = 4; // The type of the value + fixed64 value_id = 5; // Object or destination node / UID. + string lang = 7; + enum Op { + SET = 0; + DEL = 1; + } + Op op = 8; + repeated api.Facet facets = 9; + repeated string allowedPreds = 10; + uint64 namespace = 11; } message Mutations { - uint32 group_id = 1; - uint64 start_ts = 2; - repeated DirectedEdge edges = 3; - repeated SchemaUpdate schema = 4; - repeated TypeUpdate types = 6; - enum DropOp { - NONE = 0; - ALL = 1; - DATA = 2; - TYPE = 3; - } - DropOp drop_op = 7; - string drop_value = 8; - - Metadata metadata = 9; + uint32 group_id = 1; + uint64 start_ts = 2; + repeated DirectedEdge edges = 3; + repeated SchemaUpdate schema = 4; + repeated TypeUpdate types = 6; + enum DropOp { + NONE = 0; + ALL = 1; + DATA = 2; + TYPE = 3; + } + DropOp drop_op = 7; + string drop_value = 8; + + Metadata metadata = 9; } message Metadata { // HintType represents a hint that will be passed along the mutation and used // to add the predicate to the schema if it's not already there. enum HintType { - // DEFAULT means no hint is provided and Dgraph will follow the default behavior. + // DEFAULT means no hint is provided and Dgraph will follow the default + // behavior. DEFAULT = 0; - // SINGLE signals that the predicate should be created as a single type (e.g string, uid). + // SINGLE signals that the predicate should be created as a single type (e.g + // string, uid). SINGLE = 1; - // LIST signals that the predicate should be created as a list (e.g [string], [uid]). + // LIST signals that the predicate should be created as a list (e.g + // [string], [uid]). LIST = 2; } // Map of predicates to their hints. - map pred_hints = 1; + map pred_hints = 1; } message Snapshot { - RaftContext context = 1; - uint64 index = 2; - uint64 read_ts = 3; - // done is used to indicate that snapshot stream was a success. - bool done = 4; - // since_ts stores the ts of the last snapshot to support diff snap updates. - uint64 since_ts = 5; + RaftContext context = 1; + uint64 index = 2; + uint64 read_ts = 3; + // done is used to indicate that snapshot stream was a success. + bool done = 4; + // since_ts stores the ts of the last snapshot to support diff snap updates. + uint64 since_ts = 5; } message ZeroSnapshot { - uint64 index = 1; - uint64 checkpoint_ts = 2; - MembershipState state = 5; + uint64 index = 1; + uint64 checkpoint_ts = 2; + MembershipState state = 5; } message RestoreRequest { - uint32 group_id = 1; - uint64 restore_ts = 2; - string location = 3; - string backup_id = 4; - - // Credentials when using a minio or S3 bucket as the backup location. - string access_key = 5; - string secret_key = 6; - string session_token = 7; - bool anonymous = 8; - - // Info needed to process encrypted backups. - string encryption_key_file = 9; - // Vault options - string vault_addr = 10; - string vault_roleid_file = 11; - string vault_secretid_file = 12; - string vault_path = 13; - string vault_field = 14; - string vault_format = 15; - - uint64 backup_num = 16; + uint32 group_id = 1; + uint64 restore_ts = 2; + string location = 3; + string backup_id = 4; + + // Credentials when using a minio or S3 bucket as the backup location. + string access_key = 5; + string secret_key = 6; + string session_token = 7; + bool anonymous = 8; + + // Info needed to process encrypted backups. + string encryption_key_file = 9; + // Vault options + string vault_addr = 10; + string vault_roleid_file = 11; + string vault_secretid_file = 12; + string vault_path = 13; + string vault_field = 14; + string vault_format = 15; + + uint64 backup_num = 16; } message Proposal { - reserved 7; // Was used for string key. - Mutations mutations = 2; - repeated badgerpb3.KV kv = 4; - MembershipState state = 5; - string clean_predicate = 6; // Delete the predicate which was moved to other group. - OracleDelta delta = 8; - Snapshot snapshot = 9; // Used to tell the group when to take snapshot. - uint64 index = 10; // Used to store Raft index, in raft.Ready. - uint64 expected_checksum = 11; // Block an operation until membership reaches this checksum. - RestoreRequest restore = 12; - CDCState cdc_state = 13; - DeleteNsRequest delete_ns = 14; // Used to delete namespace. + reserved 7; // Was used for string key. + Mutations mutations = 2; + repeated badgerpb3.KV kv = 4; + MembershipState state = 5; + string clean_predicate = + 6; // Delete the predicate which was moved to other group. + OracleDelta delta = 8; + Snapshot snapshot = 9; // Used to tell the group when to take snapshot. + uint64 index = 10; // Used to store Raft index, in raft.Ready. + uint64 expected_checksum = + 11; // Block an operation until membership reaches this checksum. + RestoreRequest restore = 12; + CDCState cdc_state = 13; + DeleteNsRequest delete_ns = 14; // Used to delete namespace. } message CDCState { - uint64 sent_ts = 1; + uint64 sent_ts = 1; } message KVS { - bytes data = 5; - - // done used to indicate if the stream of KVS is over. - bool done = 2; - // predicates is the list of predicates known by the leader at the time of the snapshot. - repeated string predicates = 3; - // types is the list of types known by the leader at the time of the snapshot. - repeated string types = 4; + bytes data = 5; + + // done used to indicate if the stream of KVS is over. + bool done = 2; + // predicates is the list of predicates known by the leader at the time of the + // snapshot. + repeated string predicates = 3; + // types is the list of types known by the leader at the time of the snapshot. + repeated string types = 4; } // Posting messages. message Posting { - reserved 6; // This was used for label. - fixed64 uid = 1; - bytes value = 2; - enum ValType { - DEFAULT = 0; - BINARY = 1; - INT = 2; // We treat it as int64. - FLOAT = 3; - BOOL = 4; - DATETIME = 5; - GEO = 6; - UID = 7; - PASSWORD = 8; - STRING = 9; + reserved 6; // This was used for label. + fixed64 uid = 1; + bytes value = 2; + enum ValType { + DEFAULT = 0; + BINARY = 1; + INT = 2; // We treat it as int64. + FLOAT = 3; + BOOL = 4; + DATETIME = 5; + GEO = 6; + UID = 7; + PASSWORD = 8; + STRING = 9; OBJECT = 10; - } - ValType val_type = 3; - enum PostingType { - REF=0; // UID - VALUE=1; // simple, plain value - VALUE_LANG=2; // value with specified language - } - PostingType posting_type = 4; - bytes lang_tag = 5; // Only set for VALUE_LANG - repeated api.Facet facets = 9; - - // TODO: op is only used temporarily. See if we can remove it from here. - uint32 op = 12; - uint64 start_ts = 13; // Meant to use only inmemory - uint64 commit_ts = 14; // Meant to use only inmemory + } + ValType val_type = 3; + enum PostingType { + REF = 0; // UID + VALUE = 1; // simple, plain value + VALUE_LANG = 2; // value with specified language + } + PostingType posting_type = 4; + bytes lang_tag = 5; // Only set for VALUE_LANG + repeated api.Facet facets = 9; + + // TODO: op is only used temporarily. See if we can remove it from here. + uint32 op = 12; + uint64 start_ts = 13; // Meant to use only inmemory + uint64 commit_ts = 14; // Meant to use only inmemory } message UidBlock { - uint64 base = 1; - // deltas contains the deltas encoded with Varints. We don't store deltas as a list of integers, - // because when the PB is brought to memory, Go would always use 8-bytes per integer. Instead, - // storing it as a byte slice is a lot cheaper in memory. - bytes deltas = 2; - // num_uids is the number of UIDs in the block. We are including this because we want to - // switch encoding to groupvarint encoding. Current avaialble open source version implements - // encoding and decoding for uint32. To use that, we create different blocks for different 32-bit - // MSB base uids. That is, if the 32 MSBs are different, we will create a new block irrespective - // of whether the block is filled with the block_size or not. - // Default Blocksize is 256 so uint32 would be sufficient. - uint32 num_uids = 3; + uint64 base = 1; + // deltas contains the deltas encoded with Varints. We don't store deltas as a + // list of integers, because when the PB is brought to memory, Go would always + // use 8-bytes per integer. Instead, storing it as a byte slice is a lot + // cheaper in memory. + bytes deltas = 2; + // num_uids is the number of UIDs in the block. We are including this because + // we want to switch encoding to groupvarint encoding. Current avaialble open + // source version implements encoding and decoding for uint32. To use that, we + // create different blocks for different 32-bit MSB base uids. That is, if the + // 32 MSBs are different, we will create a new block irrespective of whether + // the block is filled with the block_size or not. Default Blocksize is 256 so + // uint32 would be sufficient. + uint32 num_uids = 3; } message UidPack { - uint32 block_size = 1; - repeated UidBlock blocks = 2; - uint64 alloc_ref = 23; // This field should be set to 0 during marshal. + uint32 block_size = 1; + repeated UidBlock blocks = 2; + uint64 alloc_ref = 23; // This field should be set to 0 during marshal. } message PostingList { - UidPack pack = 1; // Encoded list of uids in this posting list. - repeated Posting postings = 2; - uint64 commit_ts = 3; // More inclination towards smaller values. + UidPack pack = 1; // Encoded list of uids in this posting list. + repeated Posting postings = 2; + uint64 commit_ts = 3; // More inclination towards smaller values. repeated uint64 splits = 4; } message FacetParam { - string key = 1; - string alias = 2; + string key = 1; + string alias = 2; } message FacetParams { - bool all_keys = 1; // keys should be in sorted order. - repeated FacetParam param = 2; + bool all_keys = 1; // keys should be in sorted order. + repeated FacetParam param = 2; } message Facets { - repeated api.Facet facets = 1; + repeated api.Facet facets = 1; } message FacetsList { - repeated Facets facets_list = 1; + repeated Facets facets_list = 1; } message Function { - string name = 1; // Name of the function : eq, le - string key = 2; // Facet key over which to run the function. - repeated string args = 3; // Arguments of the function. + string name = 1; // Name of the function : eq, le + string key = 2; // Facet key over which to run the function. + repeated string args = 3; // Arguments of the function. } // Op and Children are internal nodes and Func on leaves. message FilterTree { - string op = 1; - repeated FilterTree children = 2; - Function func = 3; + string op = 1; + repeated FilterTree children = 2; + Function func = 3; } // Schema messages. message SchemaRequest { - uint32 group_id = 1; - repeated string predicates = 2; - // fields can be on of type, index, reverse or tokenizer - repeated string fields = 3; + uint32 group_id = 1; + repeated string predicates = 2; + // fields can be on of type, index, reverse or tokenizer + repeated string fields = 3; repeated string types = 4; } message SchemaNode { - string predicate = 1; - string type = 2; - bool index = 3; - repeated string tokenizer = 4; - bool reverse = 5; - bool count = 6; - bool list = 7; - bool upsert = 8; - bool lang = 9; - bool no_conflict = 10; + string predicate = 1; + string type = 2; + bool index = 3; + repeated string tokenizer = 4; + bool reverse = 5; + bool count = 6; + bool list = 7; + bool upsert = 8; + bool lang = 9; + bool no_conflict = 10; } message SchemaResult { - repeated SchemaNode schema = 1 [deprecated=true]; + repeated SchemaNode schema = 1 [deprecated = true]; } message SchemaUpdate { - string predicate = 1; - Posting.ValType value_type = 2; - enum Directive { - NONE = 0; - INDEX = 1; - REVERSE = 2; - DELETE = 3; - } - Directive directive = 3; - repeated string tokenizer = 4; - bool count = 5; - bool list = 6; - bool upsert = 8; - bool lang = 9; - - // Fields required for type system. - bool non_nullable = 10; - bool non_nullable_list = 11; - - // If value_type is OBJECT, then this represents an object type with a - // custom name. This field stores said name. - string object_type_name = 12; - - bool no_conflict = 13; - - // Deleted field: - reserved 7; - reserved "explicit"; + string predicate = 1; + Posting.ValType value_type = 2; + enum Directive { + NONE = 0; + INDEX = 1; + REVERSE = 2; + DELETE = 3; + } + Directive directive = 3; + repeated string tokenizer = 4; + bool count = 5; + bool list = 6; + bool upsert = 8; + bool lang = 9; + + // Fields required for type system. + bool non_nullable = 10; + bool non_nullable_list = 11; + + // If value_type is OBJECT, then this represents an object type with a + // custom name. This field stores said name. + string object_type_name = 12; + + bool no_conflict = 13; + + // Deleted field: + reserved 7; + reserved "explicit"; } message TypeUpdate { - string type_name = 1; - repeated SchemaUpdate fields = 2; + string type_name = 1; + repeated SchemaUpdate fields = 2; } message MapHeader { - repeated bytes partition_keys = 1; + repeated bytes partition_keys = 1; } message MovePredicatePayload { - string predicate = 1; - uint32 source_gid = 2; - uint32 dest_gid = 3; - uint64 txn_ts = 4; - uint64 expected_checksum = 5; + string predicate = 1; + uint32 source_gid = 2; + uint32 dest_gid = 3; + uint64 txn_ts = 4; + uint64 expected_checksum = 5; } message TxnStatus { - uint64 start_ts = 1; - uint64 commit_ts = 2; + uint64 start_ts = 1; + uint64 commit_ts = 2; } message OracleDelta { - repeated TxnStatus txns = 1; - uint64 max_assigned = 2; - map group_checksums = 3; - // implement tmax. + repeated TxnStatus txns = 1; + uint64 max_assigned = 2; + map group_checksums = 3; + // implement tmax. } message TxnTimestamps { - repeated uint64 ts = 1; + repeated uint64 ts = 1; } message PeerResponse { - bool status = 1; + bool status = 1; } message RaftBatch { - RaftContext context = 1; - api.Payload payload = 2; + RaftContext context = 1; + api.Payload payload = 2; } service Raft { - rpc Heartbeat (api.Payload) returns (stream HealthInfo) {} - rpc RaftMessage (stream RaftBatch) returns (api.Payload) {} - rpc JoinCluster (RaftContext) returns (api.Payload) {} - rpc IsPeer (RaftContext) returns (PeerResponse) {} + rpc Heartbeat(api.Payload) returns (stream HealthInfo) {} + rpc RaftMessage(stream RaftBatch) returns (api.Payload) {} + rpc JoinCluster(RaftContext) returns (api.Payload) {} + rpc IsPeer(RaftContext) returns (PeerResponse) {} } service Zero { - // These 3 endpoints are for handling membership. - rpc Connect (Member) returns (ConnectionState) {} - rpc UpdateMembership (Group) returns (api.Payload) {} - rpc StreamMembership (api.Payload) returns (stream MembershipState) {} - - rpc Oracle (api.Payload) returns (stream OracleDelta) {} - rpc ShouldServe (Tablet) returns (Tablet) {} - rpc AssignIds (Num) returns (AssignedIds) {} - rpc Timestamps (Num) returns (AssignedIds) {} - rpc CommitOrAbort (api.TxnContext) returns (api.TxnContext) {} - rpc TryAbort (TxnTimestamps) returns (OracleDelta) {} - rpc DeleteNamespace(DeleteNsRequest) returns (Status) {} - rpc RemoveNode (RemoveNodeRequest) returns (Status) {} - rpc MoveTablet (MoveTabletRequest) returns (Status) {} - rpc ApplyLicense (ApplyLicenseRequest) returns (Status) {} + // These 3 endpoints are for handling membership. + rpc Connect(Member) returns (ConnectionState) {} + rpc UpdateMembership(Group) returns (api.Payload) {} + rpc StreamMembership(api.Payload) returns (stream MembershipState) {} + + rpc Oracle(api.Payload) returns (stream OracleDelta) {} + rpc ShouldServe(Tablet) returns (Tablet) {} + rpc AssignIds(Num) returns (AssignedIds) {} + rpc Timestamps(Num) returns (AssignedIds) {} + rpc CommitOrAbort(api.TxnContext) returns (api.TxnContext) {} + rpc TryAbort(TxnTimestamps) returns (OracleDelta) {} + rpc DeleteNamespace(DeleteNsRequest) returns (Status) {} + rpc RemoveNode(RemoveNodeRequest) returns (Status) {} + rpc MoveTablet(MoveTabletRequest) returns (Status) {} + rpc ApplyLicense(ApplyLicenseRequest) returns (Status) {} } service Worker { - // Data serving RPCs. - rpc Mutate (Mutations) returns (api.TxnContext) {} - rpc ServeTask (Query) returns (Result) {} - rpc StreamSnapshot (stream Snapshot) returns (stream KVS) {} - rpc Sort (SortMessage) returns (SortResult) {} - rpc Schema (SchemaRequest) returns (SchemaResult) {} - rpc Backup (BackupRequest) returns (BackupResponse) {} - rpc Restore (RestoreRequest) returns (Status) {} - rpc Export (ExportRequest) returns (ExportResponse) {} - rpc ReceivePredicate(stream KVS) returns (api.Payload) {} - rpc MovePredicate(MovePredicatePayload) returns (api.Payload) {} - rpc Subscribe(SubscriptionRequest) returns (stream badgerpb3.KVList) {} - rpc UpdateGraphQLSchema(UpdateGraphQLSchemaRequest) returns (UpdateGraphQLSchemaResponse) {} - rpc DeleteNamespace (DeleteNsRequest) returns (Status) {} + // Data serving RPCs. + rpc Mutate(Mutations) returns (api.TxnContext) {} + rpc ServeTask(Query) returns (Result) {} + rpc StreamSnapshot(stream Snapshot) returns (stream KVS) {} + rpc Sort(SortMessage) returns (SortResult) {} + rpc Schema(SchemaRequest) returns (SchemaResult) {} + rpc Backup(BackupRequest) returns (BackupResponse) {} + rpc Restore(RestoreRequest) returns (Status) {} + rpc Export(ExportRequest) returns (ExportResponse) {} + rpc ReceivePredicate(stream KVS) returns (api.Payload) {} + rpc MovePredicate(MovePredicatePayload) returns (api.Payload) {} + rpc Subscribe(SubscriptionRequest) returns (stream badgerpb3.KVList) {} + rpc UpdateGraphQLSchema(UpdateGraphQLSchemaRequest) + returns (UpdateGraphQLSchemaResponse) {} + rpc DeleteNamespace(DeleteNsRequest) returns (Status) {} + rpc TaskStatus(TaskStatusRequest) returns (TaskStatusResponse) {} } message SubscriptionRequest { - repeated bytes prefixes = 1; - repeated badgerpb3.Match matches = 2; + repeated bytes prefixes = 1; + repeated badgerpb3.Match matches = 2; } message SubscriptionResponse { - badgerpb3.KVList kvs = 1; + badgerpb3.KVList kvs = 1; } message Num { - uint64 val = 1; - bool read_only = 2; - bool forwarded = 3; // True if this request was forwarded by a peer. - enum leaseType { - NS_ID = 0; - UID = 1; - TXN_TS = 2; - } - leaseType type = 4; + uint64 val = 1; + bool read_only = 2; + bool forwarded = 3; // True if this request was forwarded by a peer. + enum leaseType { + NS_ID = 0; + UID = 1; + TXN_TS = 2; + } + leaseType type = 4; } message AssignedIds { - uint64 startId = 1; - uint64 endId = 2; + uint64 startId = 1; + uint64 endId = 2; - // The following is used for read only transactions. - uint64 read_only = 5; + // The following is used for read only transactions. + uint64 read_only = 5; } message RemoveNodeRequest { - uint64 nodeId = 1; - uint32 groupId = 2; + uint64 nodeId = 1; + uint32 groupId = 2; } message MoveTabletRequest { - uint64 namespace = 1; - string tablet = 2; - uint32 dstGroup = 3; + uint64 namespace = 1; + string tablet = 2; + uint32 dstGroup = 3; } message ApplyLicenseRequest { - bytes license = 1; + bytes license = 1; } message SnapshotMeta { - uint64 client_ts = 1; - uint32 group_id = 2; + uint64 client_ts = 1; + uint32 group_id = 2; } // Status describes a general status response. // code: 0 = success, 0 != failure. message Status { - int32 code = 1; - string msg = 2; + int32 code = 1; + string msg = 2; } +// Backups record all data from since_ts to read_ts. +// With incremental backups, the read_ts of the first backup becomes +// the since_ts of the second backup. +// Incremental backups can be disabled using the force_full field. message BackupRequest { - uint64 read_ts = 1; + uint64 read_ts = 1; uint64 since_ts = 2; - uint32 group_id = 3; - string unix_ts = 4; - string destination = 5; - string access_key = 6; - string secret_key = 7; - string session_token = 8; + uint32 group_id = 3; + string unix_ts = 4; + string destination = 5; + string access_key = 6; + string secret_key = 7; + string session_token = 8; + + // True if no credentials should be used to access the S3 or minio bucket. + // For example, when using a bucket with a public policy. + bool anonymous = 9; - // True if no credentials should be used to access the S3 or minio bucket. - // For example, when using a bucket with a public policy. - bool anonymous = 9; + // The predicates to backup. All other predicates present in the group (e.g + // stale data from a predicate move) will be ignored. + repeated string predicates = 10; - // The predicates to backup. All other predicates present in the group (e.g - // stale data from a predicate move) will be ignored. - repeated string predicates = 10; + bool force_full = 11; } message BackupResponse { - repeated DropOperation drop_operations = 1; + repeated DropOperation drop_operations = 1; } message DropOperation { - enum DropOp { - ALL = 0; - DATA = 1; - ATTR = 2; - NS = 3; - } - DropOp drop_op = 1; - // When drop_op is ATTR, drop_value will be the name of the ATTR; empty otherwise. - string drop_value = 2; + enum DropOp { + ALL = 0; + DATA = 1; + ATTR = 2; + NS = 3; + } + DropOp drop_op = 1; + // When drop_op is ATTR, drop_value will be the name of the ATTR; empty + // otherwise. + string drop_value = 2; } message ExportRequest { - uint32 group_id = 1; // Group id to back up. - uint64 read_ts = 2; - int64 unix_ts = 3; - string format = 4; + uint32 group_id = 1; // Group id to back up. + uint64 read_ts = 2; + int64 unix_ts = 3; + string format = 4; - string destination = 5; + string destination = 5; - // These credentials are used to access the S3 or minio bucket. - string access_key = 6; - string secret_key = 7; - string session_token = 8; - bool anonymous = 9; + // These credentials are used to access the S3 or minio bucket. + string access_key = 6; + string secret_key = 7; + string session_token = 8; + bool anonymous = 9; - uint64 namespace = 10; + uint64 namespace = 10; } message ExportResponse { - // 0 indicates a success, and a non-zero code indicates failure - int32 code = 1; - string msg = 2; - repeated string files = 3; + // 0 indicates a success, and a non-zero code indicates failure + int32 code = 1; + string msg = 2; + repeated string files = 3; } // A key stored in the format used for writing backups. @@ -709,39 +733,47 @@ message BackupKey { uint64 start_uid = 4; string term = 5; uint32 count = 6; - uint64 namespace = 7; + uint64 namespace = 7; } // A posting list stored in the format used for writing backups. message BackupPostingList { - repeated uint64 uids = 1; - repeated Posting postings = 2; - uint64 commit_ts = 3; + repeated uint64 uids = 1; + repeated Posting postings = 2; + uint64 commit_ts = 3; repeated uint64 splits = 4; - bytes uid_bytes = 5; + bytes uid_bytes = 5; } message UpdateGraphQLSchemaRequest { - uint64 start_ts = 1; - string graphql_schema = 2; - repeated SchemaUpdate dgraph_preds = 3; - repeated TypeUpdate dgraph_types = 4; + uint64 start_ts = 1; + string graphql_schema = 2; + repeated SchemaUpdate dgraph_preds = 3; + repeated TypeUpdate dgraph_types = 4; } message UpdateGraphQLSchemaResponse { - uint64 uid = 1; + uint64 uid = 1; } // BulkMeta stores metadata from the map phase of the bulk loader. message BulkMeta { - int64 edge_count = 1; - map schema_map = 2; - repeated TypeUpdate types = 3; + int64 edge_count = 1; + map schema_map = 2; + repeated TypeUpdate types = 3; } message DeleteNsRequest { - uint32 group_id = 1; - uint64 namespace = 2; + uint32 group_id = 1; + uint64 namespace = 2; +} + +message TaskStatusRequest { + uint64 task_id = 1; +} + +message TaskStatusResponse { + uint64 task_meta = 1; } -// vim: noexpandtab sw=2 ts=2 +// vim: expandtab sw=2 ts=2 diff --git a/protos/pb/pb.pb.go b/protos/pb/pb.pb.go index f1652350f08..c05b92bc897 100644 --- a/protos/pb/pb.pb.go +++ b/protos/pb/pb.pb.go @@ -91,11 +91,14 @@ func (Mutations_DropOp) EnumDescriptor() ([]byte, []int) { type Metadata_HintType int32 const ( - // DEFAULT means no hint is provided and Dgraph will follow the default behavior. + // DEFAULT means no hint is provided and Dgraph will follow the default + // behavior. Metadata_DEFAULT Metadata_HintType = 0 - // SINGLE signals that the predicate should be created as a single type (e.g string, uid). + // SINGLE signals that the predicate should be created as a single type (e.g + // string, uid). Metadata_SINGLE Metadata_HintType = 1 - // LIST signals that the predicate should be created as a list (e.g [string], [uid]). + // LIST signals that the predicate should be created as a list (e.g + // [string], [uid]). Metadata_LIST Metadata_HintType = 2 ) @@ -1067,8 +1070,8 @@ func (m *RaftContext) GetIsLearner() bool { } // Member stores information about RAFT group member for a single RAFT node. -// Note that each server can be serving multiple RAFT groups. Each group would have -// one RAFT node per server serving that group. +// Note that each server can be serving multiple RAFT groups. Each group would +// have one RAFT node per server serving that group. type Member struct { Id uint64 `protobuf:"fixed64,1,opt,name=id,proto3" json:"id,omitempty"` GroupId uint32 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"groupId,omitempty"` @@ -1454,9 +1457,9 @@ func (m *ZeroProposal) GetDeleteNs() *DeleteNsRequest { return nil } -// MembershipState is used to pack together the current membership state of all the nodes -// in the caller server; and the membership updates recorded by the callee server since -// the provided lastUpdate. +// MembershipState is used to pack together the current membership state of all +// the nodes in the caller server; and the membership updates recorded by the +// callee server since the provided lastUpdate. type MembershipState struct { Counter uint64 `protobuf:"varint,1,opt,name=counter,proto3" json:"counter,omitempty"` Groups map[uint32]*Group `protobuf:"bytes,2,rep,name=groups,proto3" json:"groups,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` @@ -2595,7 +2598,8 @@ type KVS struct { Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` // done used to indicate if the stream of KVS is over. Done bool `protobuf:"varint,2,opt,name=done,proto3" json:"done,omitempty"` - // predicates is the list of predicates known by the leader at the time of the snapshot. + // predicates is the list of predicates known by the leader at the time of the + // snapshot. Predicates []string `protobuf:"bytes,3,rep,name=predicates,proto3" json:"predicates,omitempty"` // types is the list of types known by the leader at the time of the snapshot. Types []string `protobuf:"bytes,4,rep,name=types,proto3" json:"types,omitempty"` @@ -2774,16 +2778,18 @@ func (m *Posting) GetCommitTs() uint64 { type UidBlock struct { Base uint64 `protobuf:"varint,1,opt,name=base,proto3" json:"base,omitempty"` - // deltas contains the deltas encoded with Varints. We don't store deltas as a list of integers, - // because when the PB is brought to memory, Go would always use 8-bytes per integer. Instead, - // storing it as a byte slice is a lot cheaper in memory. + // deltas contains the deltas encoded with Varints. We don't store deltas as a + // list of integers, because when the PB is brought to memory, Go would always + // use 8-bytes per integer. Instead, storing it as a byte slice is a lot + // cheaper in memory. Deltas []byte `protobuf:"bytes,2,opt,name=deltas,proto3" json:"deltas,omitempty"` - // num_uids is the number of UIDs in the block. We are including this because we want to - // switch encoding to groupvarint encoding. Current avaialble open source version implements - // encoding and decoding for uint32. To use that, we create different blocks for different 32-bit - // MSB base uids. That is, if the 32 MSBs are different, we will create a new block irrespective - // of whether the block is filled with the block_size or not. - // Default Blocksize is 256 so uint32 would be sufficient. + // num_uids is the number of UIDs in the block. We are including this because + // we want to switch encoding to groupvarint encoding. Current avaialble open + // source version implements encoding and decoding for uint32. To use that, we + // create different blocks for different 32-bit MSB base uids. That is, if the + // 32 MSBs are different, we will create a new block irrespective of whether + // the block is filled with the block_size or not. Default Blocksize is 256 so + // uint32 would be sufficient. NumUids uint32 `protobuf:"varint,3,opt,name=num_uids,json=numUids,proto3" json:"num_uids,omitempty"` } @@ -4559,6 +4565,10 @@ func (m *Status) GetMsg() string { return "" } +// Backups record all data from since_ts to read_ts. +// With incremental backups, the read_ts of the first backup becomes +// the since_ts of the second backup. +// Incremental backups can be disabled using the force_full field. type BackupRequest struct { ReadTs uint64 `protobuf:"varint,1,opt,name=read_ts,json=readTs,proto3" json:"read_ts,omitempty"` SinceTs uint64 `protobuf:"varint,2,opt,name=since_ts,json=sinceTs,proto3" json:"since_ts,omitempty"` @@ -4574,6 +4584,7 @@ type BackupRequest struct { // The predicates to backup. All other predicates present in the group (e.g // stale data from a predicate move) will be ignored. Predicates []string `protobuf:"bytes,10,rep,name=predicates,proto3" json:"predicates,omitempty"` + ForceFull bool `protobuf:"varint,11,opt,name=force_full,json=forceFull,proto3" json:"force_full,omitempty"` } func (m *BackupRequest) Reset() { *m = BackupRequest{} } @@ -4679,6 +4690,13 @@ func (m *BackupRequest) GetPredicates() []string { return nil } +func (m *BackupRequest) GetForceFull() bool { + if m != nil { + return m.ForceFull + } + return false +} + type BackupResponse struct { DropOperations []*DropOperation `protobuf:"bytes,1,rep,name=drop_operations,json=dropOperations,proto3" json:"drop_operations,omitempty"` } @@ -4725,7 +4743,8 @@ func (m *BackupResponse) GetDropOperations() []*DropOperation { type DropOperation struct { DropOp DropOperation_DropOp `protobuf:"varint,1,opt,name=drop_op,json=dropOp,proto3,enum=pb.DropOperation_DropOp" json:"drop_op,omitempty"` - // When drop_op is ATTR, drop_value will be the name of the ATTR; empty otherwise. + // When drop_op is ATTR, drop_value will be the name of the ATTR; empty + // otherwise. DropValue string `protobuf:"bytes,2,opt,name=drop_value,json=dropValue,proto3" json:"drop_value,omitempty"` } @@ -5349,6 +5368,94 @@ func (m *DeleteNsRequest) GetNamespace() uint64 { return 0 } +type TaskStatusRequest struct { + TaskId uint64 `protobuf:"varint,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` +} + +func (m *TaskStatusRequest) Reset() { *m = TaskStatusRequest{} } +func (m *TaskStatusRequest) String() string { return proto.CompactTextString(m) } +func (*TaskStatusRequest) ProtoMessage() {} +func (*TaskStatusRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_f80abaa17e25ccc8, []int{70} +} +func (m *TaskStatusRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TaskStatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TaskStatusRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TaskStatusRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_TaskStatusRequest.Merge(m, src) +} +func (m *TaskStatusRequest) XXX_Size() int { + return m.Size() +} +func (m *TaskStatusRequest) XXX_DiscardUnknown() { + xxx_messageInfo_TaskStatusRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_TaskStatusRequest proto.InternalMessageInfo + +func (m *TaskStatusRequest) GetTaskId() uint64 { + if m != nil { + return m.TaskId + } + return 0 +} + +type TaskStatusResponse struct { + TaskMeta uint64 `protobuf:"varint,1,opt,name=task_meta,json=taskMeta,proto3" json:"task_meta,omitempty"` +} + +func (m *TaskStatusResponse) Reset() { *m = TaskStatusResponse{} } +func (m *TaskStatusResponse) String() string { return proto.CompactTextString(m) } +func (*TaskStatusResponse) ProtoMessage() {} +func (*TaskStatusResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f80abaa17e25ccc8, []int{71} +} +func (m *TaskStatusResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TaskStatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TaskStatusResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TaskStatusResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_TaskStatusResponse.Merge(m, src) +} +func (m *TaskStatusResponse) XXX_Size() int { + return m.Size() +} +func (m *TaskStatusResponse) XXX_DiscardUnknown() { + xxx_messageInfo_TaskStatusResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_TaskStatusResponse proto.InternalMessageInfo + +func (m *TaskStatusResponse) GetTaskMeta() uint64 { + if m != nil { + return m.TaskMeta + } + return 0 +} + func init() { proto.RegisterEnum("pb.DirectedEdge_Op", DirectedEdge_Op_name, DirectedEdge_Op_value) proto.RegisterEnum("pb.Mutations_DropOp", Mutations_DropOp_name, Mutations_DropOp_value) @@ -5437,343 +5544,349 @@ func init() { proto.RegisterType((*BulkMeta)(nil), "pb.BulkMeta") proto.RegisterMapType((map[string]*SchemaUpdate)(nil), "pb.BulkMeta.SchemaMapEntry") proto.RegisterType((*DeleteNsRequest)(nil), "pb.DeleteNsRequest") + proto.RegisterType((*TaskStatusRequest)(nil), "pb.TaskStatusRequest") + proto.RegisterType((*TaskStatusResponse)(nil), "pb.TaskStatusResponse") } func init() { proto.RegisterFile("pb.proto", fileDescriptor_f80abaa17e25ccc8) } var fileDescriptor_f80abaa17e25ccc8 = []byte{ - // 5283 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x7b, 0x4b, 0x6f, 0x1c, 0x67, - 0x76, 0x28, 0xfb, 0x5d, 0x75, 0xfa, 0xa1, 0xe6, 0x27, 0x59, 0xee, 0xa1, 0x6c, 0x91, 0x2e, 0x59, - 0x36, 0x2d, 0x59, 0x94, 0x4c, 0xcd, 0xe0, 0x8e, 0x3d, 0xb8, 0xc0, 0xe5, 0xa3, 0x25, 0xd3, 0xa2, - 0x48, 0x4d, 0xb1, 0xa5, 0x79, 0x00, 0xf7, 0x36, 0x8a, 0x55, 0x1f, 0xc9, 0x1a, 0x56, 0x57, 0xd5, - 0x54, 0x55, 0x73, 0x48, 0xef, 0x06, 0x17, 0x98, 0xd9, 0x64, 0x31, 0x40, 0x36, 0x59, 0x25, 0x40, - 0x16, 0xd9, 0x64, 0x11, 0x24, 0x40, 0x80, 0x20, 0x40, 0x76, 0x41, 0x10, 0x64, 0x93, 0x59, 0x06, - 0x48, 0x62, 0x04, 0x9e, 0x20, 0x0b, 0xef, 0x82, 0xfc, 0x81, 0xe0, 0x9c, 0xf3, 0xd5, 0xab, 0xd9, - 0x92, 0xec, 0x09, 0xb2, 0xc8, 0xaa, 0xbf, 0x73, 0xbe, 0xf7, 0xf9, 0xce, 0xfb, 0x54, 0x83, 0x16, - 0x1e, 0xae, 0x85, 0x51, 0x90, 0x04, 0xa2, 0x1a, 0x1e, 0x2e, 0xe9, 0x56, 0xe8, 0x32, 0xb8, 0x74, - 0xe7, 0xd8, 0x4d, 0x4e, 0xa6, 0x87, 0x6b, 0x76, 0x30, 0xb9, 0xef, 0x1c, 0x47, 0x56, 0x78, 0x72, - 0xcf, 0x0d, 0xee, 0x1f, 0x5a, 0xce, 0xb1, 0x8c, 0xee, 0x9f, 0x3d, 0xbc, 0x1f, 0x1e, 0xde, 0x4f, - 0xa7, 0x2e, 0xdd, 0x2b, 0x8c, 0x3d, 0x0e, 0x8e, 0x83, 0xfb, 0x84, 0x3e, 0x9c, 0x1e, 0x11, 0x44, - 0x00, 0xb5, 0x78, 0xb8, 0xb1, 0x04, 0xf5, 0x5d, 0x37, 0x4e, 0x84, 0x80, 0xfa, 0xd4, 0x75, 0xe2, - 0x41, 0x65, 0xa5, 0xb6, 0xda, 0x34, 0xa9, 0x6d, 0x3c, 0x05, 0x7d, 0x64, 0xc5, 0xa7, 0x2f, 0x2c, - 0x6f, 0x2a, 0x45, 0x1f, 0x6a, 0x67, 0x96, 0x37, 0xa8, 0xac, 0x54, 0x56, 0x3b, 0x26, 0x36, 0xc5, - 0x1a, 0x68, 0x67, 0x96, 0x37, 0x4e, 0x2e, 0x42, 0x39, 0xa8, 0xae, 0x54, 0x56, 0x7b, 0xeb, 0x57, - 0xd7, 0xc2, 0xc3, 0xb5, 0x67, 0x41, 0x9c, 0xb8, 0xfe, 0xf1, 0xda, 0x0b, 0xcb, 0x1b, 0x5d, 0x84, - 0xd2, 0x6c, 0x9d, 0x71, 0xc3, 0xd8, 0x87, 0xf6, 0x41, 0x64, 0x3f, 0x9a, 0xfa, 0x76, 0xe2, 0x06, - 0x3e, 0xee, 0xe8, 0x5b, 0x13, 0x49, 0x2b, 0xea, 0x26, 0xb5, 0x11, 0x67, 0x45, 0xc7, 0xf1, 0xa0, - 0xb6, 0x52, 0x43, 0x1c, 0xb6, 0xc5, 0x00, 0x5a, 0x6e, 0xbc, 0x15, 0x4c, 0xfd, 0x64, 0x50, 0x5f, - 0xa9, 0xac, 0x6a, 0x66, 0x0a, 0x1a, 0x7f, 0x50, 0x83, 0xc6, 0xf7, 0xa7, 0x32, 0xba, 0xa0, 0x79, - 0x49, 0x12, 0xa5, 0x6b, 0x61, 0x5b, 0x5c, 0x83, 0x86, 0x67, 0xf9, 0xc7, 0xf1, 0xa0, 0x4a, 0x8b, - 0x31, 0x20, 0x6e, 0x80, 0x6e, 0x1d, 0x25, 0x32, 0x1a, 0x4f, 0x5d, 0x67, 0x50, 0x5b, 0xa9, 0xac, - 0x36, 0x4d, 0x8d, 0x10, 0xcf, 0x5d, 0x47, 0x7c, 0x0b, 0x34, 0x27, 0x18, 0xdb, 0xc5, 0xbd, 0x9c, - 0x80, 0xf6, 0x12, 0xb7, 0x40, 0x9b, 0xba, 0xce, 0xd8, 0x73, 0xe3, 0x64, 0xd0, 0x58, 0xa9, 0xac, - 0xb6, 0xd7, 0x35, 0xbc, 0x2c, 0xd2, 0xce, 0x6c, 0x4d, 0x5d, 0x87, 0x88, 0x78, 0x07, 0xb4, 0x38, - 0xb2, 0xc7, 0x47, 0x53, 0xdf, 0x1e, 0x34, 0x69, 0xd0, 0x15, 0x1c, 0x54, 0xb8, 0xb5, 0xd9, 0x8a, - 0x19, 0xc0, 0x6b, 0x45, 0xf2, 0x4c, 0x46, 0xb1, 0x1c, 0xb4, 0x78, 0x2b, 0x05, 0x8a, 0x07, 0xd0, - 0x3e, 0xb2, 0x6c, 0x99, 0x8c, 0x43, 0x2b, 0xb2, 0x26, 0x03, 0x2d, 0x5f, 0xe8, 0x11, 0xa2, 0x9f, - 0x21, 0x36, 0x36, 0xe1, 0x28, 0x03, 0xc4, 0x43, 0xe8, 0x12, 0x14, 0x8f, 0x8f, 0x5c, 0x2f, 0x91, - 0xd1, 0x40, 0xa7, 0x39, 0x3d, 0x9a, 0x43, 0x98, 0x51, 0x24, 0xa5, 0xd9, 0xe1, 0x41, 0x8c, 0x11, - 0x6f, 0x03, 0xc8, 0xf3, 0xd0, 0xf2, 0x9d, 0xb1, 0xe5, 0x79, 0x03, 0xa0, 0x33, 0xe8, 0x8c, 0xd9, - 0xf0, 0x3c, 0xf1, 0x26, 0x9e, 0xcf, 0x72, 0xc6, 0x49, 0x3c, 0xe8, 0xae, 0x54, 0x56, 0xeb, 0x66, - 0x13, 0xc1, 0x51, 0x8c, 0x74, 0xb5, 0x2d, 0xfb, 0x44, 0x0e, 0x7a, 0x2b, 0x95, 0xd5, 0x86, 0xc9, - 0x00, 0x62, 0x8f, 0xdc, 0x28, 0x4e, 0x06, 0x57, 0x18, 0x4b, 0x80, 0xb1, 0x0e, 0x3a, 0x71, 0x0f, - 0x51, 0xe7, 0x36, 0x34, 0xcf, 0x10, 0x60, 0x26, 0x6b, 0xaf, 0x77, 0xf1, 0x78, 0x19, 0x83, 0x99, - 0xaa, 0xd3, 0xb8, 0x09, 0xda, 0xae, 0xe5, 0x1f, 0xa7, 0x5c, 0x89, 0xcf, 0x46, 0x13, 0x74, 0x93, - 0xda, 0xc6, 0xef, 0x55, 0xa1, 0x69, 0xca, 0x78, 0xea, 0x25, 0xe2, 0x7d, 0x00, 0x7c, 0x94, 0x89, - 0x95, 0x44, 0xee, 0xb9, 0x5a, 0x35, 0x7f, 0x16, 0x7d, 0xea, 0x3a, 0x4f, 0xa9, 0x4b, 0x3c, 0x80, - 0x0e, 0xad, 0x9e, 0x0e, 0xad, 0xe6, 0x07, 0xc8, 0xce, 0x67, 0xb6, 0x69, 0x88, 0x9a, 0x71, 0x1d, - 0x9a, 0xc4, 0x07, 0xcc, 0x8b, 0x5d, 0x53, 0x41, 0xe2, 0x36, 0xf4, 0x5c, 0x3f, 0xc1, 0x77, 0xb2, - 0x93, 0xb1, 0x23, 0xe3, 0x94, 0x51, 0xba, 0x19, 0x76, 0x5b, 0xc6, 0x89, 0xf8, 0x08, 0x98, 0xd8, - 0xe9, 0x86, 0x0d, 0xda, 0xb0, 0x97, 0x3d, 0x62, 0xcc, 0x3b, 0xd2, 0x18, 0xb5, 0xe3, 0x3d, 0x68, - 0xe3, 0xfd, 0xd2, 0x19, 0x4d, 0x9a, 0xd1, 0xa1, 0xdb, 0x28, 0x72, 0x98, 0x80, 0x03, 0xd4, 0x70, - 0x24, 0x0d, 0x32, 0x23, 0x33, 0x0f, 0xb5, 0x8d, 0x21, 0x34, 0xf6, 0x23, 0x47, 0x46, 0x73, 0xe5, - 0x41, 0x40, 0xdd, 0x91, 0xb1, 0x4d, 0xa2, 0xaa, 0x99, 0xd4, 0xce, 0x65, 0xa4, 0x56, 0x90, 0x11, - 0xe3, 0xf7, 0x2b, 0xd0, 0x3e, 0x08, 0xa2, 0xe4, 0xa9, 0x8c, 0x63, 0xeb, 0x58, 0x8a, 0x65, 0x68, - 0x04, 0xb8, 0xac, 0xa2, 0xb0, 0x8e, 0x67, 0xa2, 0x7d, 0x4c, 0xc6, 0xcf, 0xbc, 0x43, 0xf5, 0xe5, - 0xef, 0x80, 0xbc, 0x43, 0xd2, 0x55, 0x53, 0xbc, 0x43, 0xb2, 0x75, 0x1d, 0x9a, 0xc1, 0xd1, 0x51, - 0x2c, 0x99, 0x96, 0x0d, 0x53, 0x41, 0x2f, 0x65, 0x41, 0xe3, 0x3b, 0x00, 0x78, 0xbe, 0x6f, 0xc8, - 0x05, 0xc6, 0x2f, 0x2b, 0xd0, 0x36, 0xad, 0xa3, 0x64, 0x2b, 0xf0, 0x13, 0x79, 0x9e, 0x88, 0x1e, - 0x54, 0x5d, 0x87, 0x68, 0xd4, 0x34, 0xab, 0xae, 0x83, 0xa7, 0x3b, 0x8e, 0x82, 0x69, 0x48, 0x24, - 0xea, 0x9a, 0x0c, 0x10, 0x2d, 0x1d, 0x27, 0xa2, 0x23, 0x23, 0x2d, 0x1d, 0x27, 0x12, 0xcb, 0xd0, - 0x8e, 0x7d, 0x2b, 0x8c, 0x4f, 0x82, 0x04, 0x4f, 0x57, 0xa7, 0xd3, 0x41, 0x8a, 0x1a, 0xc5, 0x28, - 0x5c, 0x6e, 0x3c, 0xf6, 0xa4, 0x15, 0xf9, 0x32, 0x22, 0x85, 0xa1, 0x99, 0xba, 0x1b, 0xef, 0x32, - 0xc2, 0xf8, 0x65, 0x0d, 0x9a, 0x4f, 0xe5, 0xe4, 0x50, 0x46, 0x97, 0x0e, 0xf1, 0x00, 0x34, 0xda, - 0x77, 0xec, 0x3a, 0x7c, 0x8e, 0xcd, 0x37, 0xbe, 0xfa, 0x62, 0x79, 0x91, 0x70, 0x3b, 0xce, 0x87, - 0xc1, 0xc4, 0x4d, 0xe4, 0x24, 0x4c, 0x2e, 0xcc, 0x96, 0x42, 0xcd, 0x3d, 0xe0, 0x75, 0x68, 0x7a, - 0xd2, 0xc2, 0x37, 0x63, 0xf6, 0x54, 0x90, 0xb8, 0x07, 0x2d, 0x6b, 0x32, 0x76, 0xa4, 0xe5, 0xf0, - 0xa1, 0x36, 0xaf, 0x7d, 0xf5, 0xc5, 0x72, 0xdf, 0x9a, 0x6c, 0x4b, 0xab, 0xb8, 0x76, 0x93, 0x31, - 0xe2, 0x63, 0xe4, 0xc9, 0x38, 0x19, 0x4f, 0x43, 0xc7, 0x4a, 0x24, 0xe9, 0xb4, 0xfa, 0xe6, 0xe0, - 0xab, 0x2f, 0x96, 0xaf, 0x21, 0xfa, 0x39, 0x61, 0x0b, 0xd3, 0x20, 0xc7, 0xa2, 0x7e, 0x4b, 0xaf, - 0xaf, 0xf4, 0x9b, 0x02, 0xc5, 0x0e, 0x2c, 0xda, 0xde, 0x34, 0x46, 0x25, 0xec, 0xfa, 0x47, 0xc1, - 0x38, 0xf0, 0xbd, 0x0b, 0x7a, 0x60, 0x6d, 0xf3, 0xed, 0xaf, 0xbe, 0x58, 0xfe, 0x96, 0xea, 0xdc, - 0xf1, 0x8f, 0x82, 0x7d, 0xdf, 0xbb, 0x28, 0xac, 0x7f, 0x65, 0xa6, 0x4b, 0xfc, 0x1f, 0xe8, 0x1d, - 0x05, 0x91, 0x2d, 0xc7, 0x19, 0xc9, 0x7a, 0xb4, 0xce, 0xd2, 0x57, 0x5f, 0x2c, 0x5f, 0xa7, 0x9e, - 0xc7, 0x97, 0xe8, 0xd6, 0x29, 0xe2, 0x8d, 0x7f, 0xae, 0x42, 0x83, 0xda, 0xe2, 0x01, 0xb4, 0x26, - 0xf4, 0x24, 0xa9, 0x7e, 0xba, 0x8e, 0x3c, 0x44, 0x7d, 0x6b, 0xfc, 0x56, 0xf1, 0xd0, 0x4f, 0xa2, - 0x0b, 0x33, 0x1d, 0x86, 0x33, 0x12, 0xeb, 0xd0, 0x93, 0x49, 0xac, 0x78, 0xbe, 0x30, 0x63, 0xc4, - 0x1d, 0x6a, 0x86, 0x1a, 0x36, 0xcb, 0x37, 0xb5, 0x4b, 0x7c, 0xb3, 0x04, 0x9a, 0x7d, 0x22, 0xed, - 0xd3, 0x78, 0x3a, 0x51, 0x5c, 0x95, 0xc1, 0xe2, 0x16, 0x74, 0xa9, 0x1d, 0x06, 0xae, 0x4f, 0xd3, - 0x1b, 0x34, 0xa0, 0x93, 0x23, 0x47, 0xf1, 0xd2, 0x23, 0xe8, 0x14, 0x0f, 0x8b, 0x66, 0xfb, 0x54, - 0x5e, 0x10, 0x7f, 0xd5, 0x4d, 0x6c, 0x8a, 0x15, 0x68, 0x90, 0xa2, 0x23, 0xee, 0x6a, 0xaf, 0x03, - 0x9e, 0x99, 0xa7, 0x98, 0xdc, 0xf1, 0x49, 0xf5, 0xbb, 0x15, 0x5c, 0xa7, 0x78, 0x85, 0xe2, 0x3a, - 0xfa, 0xcb, 0xd7, 0xe1, 0x29, 0x85, 0x75, 0x8c, 0x00, 0x5a, 0xbb, 0xae, 0x2d, 0xfd, 0x98, 0x8c, - 0xfb, 0x34, 0x96, 0x99, 0x52, 0xc2, 0x36, 0xde, 0x77, 0x62, 0x9d, 0xef, 0x05, 0x8e, 0x8c, 0x69, - 0x9d, 0xba, 0x99, 0xc1, 0xd8, 0x27, 0xcf, 0x43, 0x37, 0xba, 0x18, 0x31, 0xa5, 0x6a, 0x66, 0x06, - 0x23, 0x77, 0x49, 0x1f, 0x37, 0x73, 0x52, 0x43, 0xad, 0x40, 0xe3, 0x17, 0x75, 0xe8, 0xfc, 0x58, - 0x46, 0xc1, 0xb3, 0x28, 0x08, 0x83, 0xd8, 0xf2, 0xc4, 0x46, 0x99, 0xe6, 0xfc, 0xb6, 0x2b, 0x78, - 0xda, 0xe2, 0xb0, 0xb5, 0x83, 0xec, 0x11, 0xf8, 0xcd, 0x8a, 0xaf, 0x62, 0x40, 0x93, 0xdf, 0x7c, - 0x0e, 0xcd, 0x54, 0x0f, 0x8e, 0xe1, 0x57, 0xa6, 0xb3, 0x96, 0xe9, 0xa1, 0x7a, 0x50, 0x2a, 0x27, - 0xd6, 0xf9, 0xf3, 0x9d, 0x6d, 0xf5, 0xb6, 0x0a, 0x52, 0x54, 0x18, 0x9d, 0xfb, 0xa3, 0xf4, 0x51, - 0x33, 0x18, 0x6f, 0x8a, 0x14, 0x89, 0x77, 0xb6, 0x07, 0x1d, 0xea, 0x4a, 0x41, 0xf1, 0x16, 0xe8, - 0x13, 0xeb, 0x1c, 0x15, 0xda, 0x8e, 0xc3, 0xa2, 0x69, 0xe6, 0x08, 0xf1, 0x0e, 0xd4, 0x92, 0x73, - 0x9f, 0x64, 0x0f, 0xbd, 0x07, 0x74, 0x26, 0x47, 0xe7, 0xbe, 0x52, 0x7d, 0x26, 0xf6, 0xe1, 0x9b, - 0xda, 0xae, 0x43, 0xce, 0x82, 0x6e, 0x62, 0x53, 0xdc, 0x86, 0x96, 0xc7, 0xaf, 0x45, 0x0e, 0x41, - 0x7b, 0xbd, 0xcd, 0x7a, 0x94, 0x50, 0x66, 0xda, 0x27, 0x3e, 0x04, 0x2d, 0xa5, 0xce, 0xa0, 0x4d, - 0xe3, 0xfa, 0x29, 0x3d, 0x53, 0x32, 0x9a, 0xd9, 0x08, 0xf1, 0x00, 0x74, 0x47, 0x7a, 0x32, 0x91, - 0x63, 0x9f, 0x15, 0x79, 0x9b, 0x1d, 0xc5, 0x6d, 0x42, 0xee, 0xc5, 0xa6, 0xfc, 0xe9, 0x54, 0xc6, - 0x89, 0xa9, 0x39, 0x0a, 0xb1, 0xf4, 0xbf, 0xe1, 0xca, 0xcc, 0x73, 0x14, 0xf9, 0xaf, 0xcb, 0xfc, - 0x77, 0xad, 0xc8, 0x7f, 0xf5, 0x02, 0xcf, 0x7d, 0x56, 0xd7, 0xb4, 0xbe, 0x6e, 0xfc, 0x7b, 0x0d, - 0xae, 0x28, 0x51, 0x38, 0x71, 0xc3, 0x83, 0x44, 0x29, 0x25, 0x32, 0x39, 0x8a, 0x0b, 0xeb, 0x66, - 0x0a, 0x8a, 0xff, 0x05, 0x4d, 0xd2, 0x21, 0xa9, 0x28, 0x2f, 0xe7, 0x4f, 0x9c, 0x4d, 0x67, 0xd1, - 0x56, 0xfc, 0xa1, 0x86, 0x8b, 0x6f, 0x43, 0xe3, 0x73, 0x19, 0x05, 0x6c, 0x42, 0xdb, 0xeb, 0x37, - 0xe7, 0xcd, 0x43, 0xc2, 0xa8, 0x69, 0x3c, 0xf8, 0xbf, 0xca, 0x09, 0xf0, 0x4d, 0x38, 0xe1, 0x5d, - 0x34, 0xa3, 0x93, 0xe0, 0x4c, 0x3a, 0x83, 0x16, 0x9d, 0xb1, 0xc8, 0xbe, 0x69, 0x57, 0xca, 0x0c, - 0xda, 0x5c, 0x66, 0xd0, 0x5f, 0xce, 0x0c, 0x4b, 0xdb, 0xd0, 0x2e, 0xd0, 0x65, 0xce, 0x43, 0x2d, - 0x97, 0x15, 0x85, 0x9e, 0x29, 0xc9, 0xa2, 0xbe, 0xd9, 0x06, 0xc8, 0xa9, 0xf4, 0xdb, 0x6a, 0x2d, - 0xe3, 0xe7, 0x15, 0xb8, 0xb2, 0x15, 0xf8, 0xbe, 0x24, 0x67, 0x9b, 0xdf, 0x3c, 0x17, 0xde, 0xca, - 0x4b, 0x85, 0xf7, 0x03, 0x68, 0xc4, 0x38, 0x58, 0xad, 0x7e, 0x75, 0xce, 0x23, 0x9a, 0x3c, 0x02, - 0x55, 0xf8, 0xc4, 0x3a, 0x1f, 0x87, 0xd2, 0x77, 0x5c, 0xff, 0x38, 0x55, 0xe1, 0x13, 0xeb, 0xfc, - 0x19, 0x63, 0x8c, 0xbf, 0xa8, 0x02, 0x7c, 0x2a, 0x2d, 0x2f, 0x39, 0x41, 0x33, 0x85, 0x2f, 0xea, - 0xfa, 0x71, 0x62, 0xf9, 0x76, 0x1a, 0xea, 0x64, 0x30, 0xbe, 0x28, 0x5a, 0x6b, 0x19, 0xb3, 0xf2, - 0xd3, 0xcd, 0x14, 0x44, 0xfe, 0xc0, 0xed, 0xa6, 0xb1, 0xb2, 0xea, 0x0a, 0xca, 0x5d, 0x94, 0x3a, - 0xa1, 0x95, 0x8b, 0x32, 0x80, 0x16, 0x86, 0x0e, 0x6e, 0xe0, 0x13, 0xd3, 0xe8, 0x66, 0x0a, 0xe2, - 0x3a, 0xd3, 0x30, 0x71, 0x27, 0x6c, 0xbb, 0x6b, 0xa6, 0x82, 0xf0, 0x54, 0x68, 0xab, 0x87, 0xf6, - 0x49, 0x40, 0x2a, 0xa2, 0x66, 0x66, 0x30, 0xae, 0x16, 0xf8, 0xc7, 0x01, 0xde, 0x4e, 0x23, 0xb7, - 0x30, 0x05, 0xf9, 0x2e, 0x8e, 0x3c, 0xc7, 0x2e, 0x9d, 0xba, 0x32, 0x18, 0xe9, 0x22, 0xe5, 0xf8, - 0x48, 0x5a, 0xc9, 0x34, 0x92, 0xf1, 0x00, 0xa8, 0x1b, 0xa4, 0x7c, 0xa4, 0x30, 0xe2, 0x1d, 0xe8, - 0x20, 0xe1, 0xac, 0x38, 0x76, 0x8f, 0x7d, 0xe9, 0x90, 0xe2, 0xa8, 0x9b, 0x48, 0xcc, 0x0d, 0x85, - 0x32, 0xfe, 0xaa, 0x0a, 0x4d, 0x56, 0x99, 0x25, 0x37, 0xa8, 0xf2, 0xb5, 0xdc, 0xa0, 0xb7, 0x40, - 0x0f, 0x23, 0xe9, 0xb8, 0x76, 0xfa, 0x8e, 0xba, 0x99, 0x23, 0x28, 0x3e, 0x41, 0xbb, 0x4f, 0xf4, - 0xd4, 0x4c, 0x06, 0x84, 0x01, 0xdd, 0xc0, 0x1f, 0x3b, 0x6e, 0x7c, 0x3a, 0x3e, 0xbc, 0x48, 0x64, - 0xac, 0x68, 0xd1, 0x0e, 0xfc, 0x6d, 0x37, 0x3e, 0xdd, 0x44, 0x14, 0x92, 0x90, 0x65, 0x84, 0x64, - 0x43, 0x33, 0x15, 0x24, 0x1e, 0x82, 0x4e, 0xde, 0x29, 0xb9, 0x2f, 0x3a, 0xb9, 0x1d, 0xd7, 0xbf, - 0xfa, 0x62, 0x59, 0x20, 0x72, 0xc6, 0x6f, 0xd1, 0x52, 0x1c, 0xfa, 0x5f, 0x38, 0x19, 0x0d, 0x11, - 0xc9, 0x30, 0xfb, 0x5f, 0x88, 0x1a, 0xc5, 0x45, 0xff, 0x8b, 0x31, 0xe2, 0x1e, 0x88, 0xa9, 0x6f, - 0x07, 0x93, 0x10, 0x99, 0x42, 0x3a, 0xea, 0x90, 0x6d, 0x3a, 0xe4, 0x62, 0xb1, 0x87, 0x8e, 0x6a, - 0xfc, 0x53, 0x15, 0x3a, 0xdb, 0x6e, 0x24, 0xed, 0x44, 0x3a, 0x43, 0xe7, 0x58, 0xe2, 0xd9, 0xa5, - 0x9f, 0xb8, 0xc9, 0x85, 0x72, 0x30, 0x15, 0x94, 0xc5, 0x07, 0xd5, 0x72, 0xbc, 0xcc, 0x12, 0x56, - 0xa3, 0x10, 0x9f, 0x01, 0xb1, 0x0e, 0xc0, 0x91, 0x13, 0x85, 0xf9, 0xf5, 0x97, 0x87, 0xf9, 0x3a, - 0x0d, 0xc3, 0x26, 0x86, 0xd1, 0x3c, 0xc7, 0x65, 0x2f, 0xb3, 0x49, 0x39, 0x80, 0xa9, 0x64, 0x5f, - 0x95, 0x02, 0xba, 0x16, 0x6f, 0x8c, 0x6d, 0x71, 0x0b, 0xaa, 0x41, 0x48, 0xc4, 0x55, 0x4b, 0x17, - 0xaf, 0xb0, 0xb6, 0x1f, 0x9a, 0xd5, 0x20, 0x44, 0x29, 0xe6, 0xe8, 0x95, 0x18, 0x0f, 0xa5, 0x18, - 0x2d, 0x1a, 0xc5, 0x52, 0xa6, 0xea, 0x11, 0x06, 0x74, 0x2c, 0xcf, 0x0b, 0x7e, 0x26, 0x9d, 0x67, - 0x91, 0x74, 0x52, 0x1e, 0x2c, 0xe1, 0x90, 0x4b, 0x7c, 0x6b, 0x22, 0xe3, 0xd0, 0xb2, 0xa5, 0x62, - 0xc1, 0x1c, 0x61, 0x5c, 0x87, 0xea, 0x7e, 0x28, 0x5a, 0x50, 0x3b, 0x18, 0x8e, 0xfa, 0x0b, 0xd8, - 0xd8, 0x1e, 0xee, 0xf6, 0xd1, 0xa2, 0x34, 0xfb, 0x2d, 0xe3, 0xcb, 0x2a, 0xe8, 0x4f, 0xa7, 0x89, - 0x85, 0xba, 0x25, 0xc6, 0x5b, 0x96, 0x39, 0x34, 0x67, 0xc5, 0x6f, 0x81, 0x16, 0x27, 0x56, 0x44, - 0xfe, 0x06, 0x5b, 0xa7, 0x16, 0xc1, 0xa3, 0x58, 0xbc, 0x07, 0x0d, 0xe9, 0x1c, 0xcb, 0xd4, 0x5c, - 0xf4, 0x67, 0xef, 0x6b, 0x72, 0xb7, 0x58, 0x85, 0x66, 0x6c, 0x9f, 0xc8, 0x89, 0x35, 0xa8, 0xe7, - 0x03, 0x0f, 0x08, 0xc3, 0x0e, 0xb6, 0xa9, 0xfa, 0xc5, 0xbb, 0xd0, 0xc0, 0xb7, 0x89, 0x55, 0xc4, - 0x48, 0x31, 0x26, 0x3e, 0x83, 0x1a, 0xc6, 0x9d, 0xc8, 0x78, 0x4e, 0x14, 0x84, 0xe3, 0x20, 0x24, - 0xda, 0xf7, 0xd6, 0xaf, 0x91, 0x8e, 0x4b, 0x6f, 0xb3, 0xb6, 0x1d, 0x05, 0xe1, 0x7e, 0x68, 0x36, - 0x1d, 0xfa, 0xc5, 0xf8, 0x85, 0x86, 0x33, 0x47, 0xb0, 0x51, 0xd0, 0x11, 0xc3, 0xc9, 0xa0, 0x55, - 0xd0, 0x26, 0x32, 0xb1, 0x1c, 0x2b, 0xb1, 0x94, 0x6d, 0xe8, 0xb0, 0xca, 0x64, 0x9c, 0x99, 0xf5, - 0x1a, 0xf7, 0xa1, 0xc9, 0x4b, 0x0b, 0x0d, 0xea, 0x7b, 0xfb, 0x7b, 0x43, 0x26, 0xeb, 0xc6, 0xee, - 0x6e, 0xbf, 0x82, 0xa8, 0xed, 0x8d, 0xd1, 0x46, 0xbf, 0x8a, 0xad, 0xd1, 0x8f, 0x9e, 0x0d, 0xfb, - 0x35, 0xe3, 0xef, 0x2a, 0xa0, 0xa5, 0xeb, 0x88, 0x4f, 0x00, 0x50, 0x84, 0xc7, 0x27, 0xae, 0x9f, - 0xb9, 0x6e, 0x37, 0x8a, 0x3b, 0xad, 0xe1, 0xab, 0x7e, 0x8a, 0xbd, 0x6c, 0x5e, 0x49, 0xe2, 0x09, - 0x5e, 0x3a, 0x80, 0x5e, 0xb9, 0x73, 0x8e, 0x0f, 0x7b, 0xb7, 0x68, 0x55, 0x7a, 0xeb, 0x6f, 0x94, - 0x96, 0xc6, 0x99, 0xc4, 0xda, 0x05, 0x03, 0x73, 0x0f, 0xb4, 0x14, 0x2d, 0xda, 0xd0, 0xda, 0x1e, - 0x3e, 0xda, 0x78, 0xbe, 0x8b, 0xac, 0x02, 0xd0, 0x3c, 0xd8, 0xd9, 0x7b, 0xbc, 0x3b, 0xe4, 0x6b, - 0xed, 0xee, 0x1c, 0x8c, 0xfa, 0x55, 0xe3, 0x77, 0x2b, 0xa0, 0xa5, 0x9e, 0x8c, 0xf8, 0x00, 0x9d, - 0x0f, 0x72, 0xbf, 0x94, 0x25, 0xa2, 0x9c, 0x4e, 0x21, 0x20, 0x35, 0xd3, 0x7e, 0x94, 0x45, 0x52, - 0xac, 0xa9, 0x6f, 0x43, 0x40, 0x31, 0x1e, 0xae, 0x95, 0x52, 0x32, 0x18, 0xda, 0x07, 0xbe, 0x54, - 0xae, 0x30, 0xb5, 0x89, 0x07, 0x5d, 0xdf, 0x96, 0x79, 0xa0, 0xd0, 0x22, 0x78, 0x14, 0x1b, 0x09, - 0x7b, 0xc8, 0xd9, 0xc1, 0xb2, 0xdd, 0x2a, 0xc5, 0xdd, 0x2e, 0x85, 0x1b, 0xd5, 0xcb, 0xe1, 0x46, - 0x6e, 0x38, 0x1b, 0xaf, 0x33, 0x9c, 0xc6, 0x9f, 0xd6, 0xa1, 0x67, 0xca, 0x38, 0x09, 0x22, 0xa9, - 0x3c, 0xbe, 0x57, 0x89, 0xd0, 0xdb, 0x00, 0x11, 0x0f, 0xce, 0xb7, 0xd6, 0x15, 0x86, 0xe3, 0x24, - 0x2f, 0xb0, 0x89, 0x77, 0x95, 0x85, 0xcc, 0x60, 0x71, 0x03, 0xf4, 0x43, 0xcb, 0x3e, 0xe5, 0x65, - 0xd9, 0x4e, 0x6a, 0x8c, 0xe0, 0x75, 0x2d, 0xdb, 0x96, 0x71, 0x3c, 0x46, 0x56, 0x60, 0x6b, 0xa9, - 0x33, 0xe6, 0x89, 0xbc, 0xc0, 0xee, 0x58, 0xda, 0x91, 0x4c, 0xa8, 0xbb, 0xc9, 0xdd, 0x8c, 0xc1, - 0xee, 0x5b, 0xd0, 0x8d, 0x65, 0x8c, 0x96, 0x75, 0x9c, 0x04, 0xa7, 0xd2, 0x57, 0x7a, 0xac, 0xa3, - 0x90, 0x23, 0xc4, 0xa1, 0x8a, 0xb1, 0xfc, 0xc0, 0xbf, 0x98, 0x04, 0xd3, 0x58, 0xd9, 0x8c, 0x1c, - 0x21, 0xd6, 0xe0, 0xaa, 0xf4, 0xed, 0xe8, 0x22, 0xc4, 0xb3, 0xe2, 0x2e, 0xe3, 0x23, 0xd7, 0x93, - 0xca, 0x09, 0x5f, 0xcc, 0xbb, 0x9e, 0xc8, 0x8b, 0x47, 0xae, 0x27, 0xf1, 0x44, 0x67, 0xd6, 0xd4, - 0x4b, 0xc6, 0x14, 0xe3, 0x03, 0x9f, 0x88, 0x30, 0x1b, 0x18, 0xe8, 0xdf, 0x81, 0x45, 0xee, 0x8e, - 0x02, 0x4f, 0xba, 0x0e, 0x2f, 0xd6, 0xa6, 0x51, 0x57, 0xa8, 0xc3, 0x24, 0x3c, 0x2d, 0xb5, 0x06, - 0x57, 0x79, 0x2c, 0x5f, 0x28, 0x1d, 0xdd, 0xe1, 0xad, 0xa9, 0xeb, 0x40, 0xf5, 0x94, 0xb7, 0x0e, - 0xad, 0xe4, 0x84, 0x3c, 0xf7, 0x74, 0xeb, 0x67, 0x56, 0x72, 0x82, 0x16, 0x9f, 0xbb, 0x8f, 0x5c, - 0xe9, 0x71, 0xe4, 0xad, 0x9b, 0x3c, 0xe3, 0x11, 0x62, 0xd0, 0xe2, 0xab, 0x01, 0x41, 0x34, 0xb1, - 0x38, 0x35, 0xa8, 0x9b, 0x3c, 0xe9, 0x11, 0xa1, 0x70, 0x0b, 0xf5, 0x56, 0xfe, 0x74, 0x32, 0xe8, - 0xf3, 0x33, 0x33, 0x66, 0x6f, 0x3a, 0x31, 0xfe, 0xbe, 0x06, 0x5a, 0x16, 0xc8, 0xdd, 0x05, 0x7d, - 0x92, 0xea, 0x2b, 0xe5, 0xa8, 0x75, 0x4b, 0x4a, 0xcc, 0xcc, 0xfb, 0xc5, 0xdb, 0x50, 0x3d, 0x3d, - 0x53, 0xba, 0xb3, 0xbb, 0xc6, 0xa9, 0xf2, 0xf0, 0xf0, 0xe1, 0xda, 0x93, 0x17, 0x66, 0xf5, 0xf4, - 0xec, 0x1b, 0xf0, 0xad, 0x78, 0x1f, 0xae, 0xd8, 0x9e, 0xb4, 0xfc, 0x71, 0xee, 0x5d, 0x30, 0x5f, - 0xf4, 0x08, 0xfd, 0x2c, 0x73, 0x31, 0x6e, 0x43, 0xc3, 0x91, 0x5e, 0x62, 0x15, 0x33, 0xb6, 0xfb, - 0x91, 0x65, 0x7b, 0x72, 0x1b, 0xd1, 0x26, 0xf7, 0xa2, 0xee, 0xcc, 0x82, 0xa7, 0x82, 0xee, 0x9c, - 0x13, 0x38, 0x65, 0x72, 0x09, 0x45, 0xb9, 0xbc, 0x0b, 0x8b, 0xf2, 0x3c, 0x24, 0x83, 0x31, 0xce, - 0x72, 0x05, 0x6c, 0xc9, 0xfa, 0x69, 0xc7, 0x56, 0x9a, 0x33, 0xf8, 0x10, 0x55, 0x06, 0x09, 0x0d, - 0x3d, 0x73, 0x7b, 0x5d, 0x90, 0xce, 0x29, 0x89, 0xa1, 0x99, 0x0e, 0x11, 0x1f, 0x80, 0x6e, 0x3b, - 0xf6, 0x98, 0x29, 0xd3, 0xcd, 0xcf, 0xb6, 0xb5, 0xbd, 0xc5, 0x24, 0xd1, 0x6c, 0xc7, 0x66, 0xaf, - 0xba, 0x14, 0xd4, 0xf5, 0xbe, 0x46, 0x50, 0xf7, 0x59, 0x5d, 0x6b, 0xf5, 0x35, 0xe3, 0x16, 0x68, - 0xe9, 0x6a, 0xa8, 0xcf, 0x62, 0xe9, 0xab, 0xa8, 0x9c, 0xf4, 0x19, 0x82, 0xa3, 0xd8, 0xb0, 0xa1, - 0xf6, 0xe4, 0xc5, 0x01, 0xa9, 0x35, 0xb4, 0x30, 0x0d, 0x72, 0x48, 0xa8, 0x9d, 0xa9, 0xba, 0x6a, - 0x41, 0xd5, 0xdd, 0x64, 0x2b, 0x41, 0xaf, 0x90, 0xa6, 0x32, 0x0b, 0x18, 0xa4, 0x23, 0x5b, 0xc8, - 0x3a, 0x67, 0x39, 0x09, 0x30, 0xfe, 0xad, 0x06, 0x2d, 0xe5, 0xc4, 0xa0, 0x65, 0x98, 0x66, 0x59, - 0x38, 0x6c, 0x96, 0xa3, 0xcb, 0xcc, 0x1b, 0x2a, 0x96, 0x3c, 0x6a, 0xaf, 0x2f, 0x79, 0x88, 0x4f, - 0xa0, 0x13, 0x72, 0x5f, 0xd1, 0x7f, 0x7a, 0xb3, 0x38, 0x47, 0xfd, 0xd2, 0xbc, 0x76, 0x98, 0x03, - 0xa8, 0x1c, 0x29, 0x1f, 0x9c, 0x58, 0xc7, 0x8a, 0x02, 0x2d, 0x84, 0x47, 0xd6, 0xf1, 0xd7, 0x72, - 0x86, 0x7a, 0xe4, 0x55, 0x75, 0x48, 0xab, 0xa2, 0x03, 0x55, 0xf4, 0x49, 0xba, 0x65, 0x9f, 0xe4, - 0x06, 0xe8, 0x76, 0x30, 0x99, 0xb8, 0xd4, 0xd7, 0x53, 0x59, 0x27, 0x42, 0x8c, 0x62, 0xe3, 0x17, - 0x15, 0x68, 0xa9, 0x7b, 0x5d, 0xb2, 0x78, 0x9b, 0x3b, 0x7b, 0x1b, 0xe6, 0x8f, 0xfa, 0x15, 0xb4, - 0xe8, 0x3b, 0x7b, 0xa3, 0x7e, 0x55, 0xe8, 0xd0, 0x78, 0xb4, 0xbb, 0xbf, 0x31, 0xea, 0xd7, 0xd0, - 0x0a, 0x6e, 0xee, 0xef, 0xef, 0xf6, 0xeb, 0xa2, 0x03, 0xda, 0xf6, 0xc6, 0x68, 0x38, 0xda, 0x79, - 0x3a, 0xec, 0x37, 0x70, 0xec, 0xe3, 0xe1, 0x7e, 0xbf, 0x89, 0x8d, 0xe7, 0x3b, 0xdb, 0xfd, 0x16, - 0xf6, 0x3f, 0xdb, 0x38, 0x38, 0xf8, 0xc1, 0xbe, 0xb9, 0xdd, 0xd7, 0xc8, 0x92, 0x8e, 0xcc, 0x9d, - 0xbd, 0xc7, 0x7d, 0x1d, 0xdb, 0xfb, 0x9b, 0x9f, 0x0d, 0xb7, 0x46, 0x7d, 0x30, 0x3e, 0x82, 0x76, - 0x81, 0x56, 0x38, 0xdb, 0x1c, 0x3e, 0xea, 0x2f, 0xe0, 0x96, 0x2f, 0x36, 0x76, 0x9f, 0xa3, 0xe1, - 0xed, 0x01, 0x50, 0x73, 0xbc, 0xbb, 0xb1, 0xf7, 0xb8, 0x5f, 0x55, 0x6e, 0xdb, 0xf7, 0x41, 0x7b, - 0xee, 0x3a, 0x9b, 0x5e, 0x60, 0x9f, 0x22, 0xfb, 0x1c, 0x5a, 0xb1, 0x54, 0xfc, 0x46, 0x6d, 0x74, - 0x92, 0x49, 0x32, 0x63, 0xf5, 0xd6, 0x0a, 0x42, 0x8a, 0xf9, 0xd3, 0xc9, 0x98, 0xca, 0x62, 0x35, - 0xb6, 0x4e, 0xfe, 0x74, 0xf2, 0xdc, 0x75, 0x62, 0xe3, 0x14, 0x5a, 0xcf, 0x5d, 0xe7, 0x99, 0x65, - 0x9f, 0x92, 0x06, 0xc3, 0xa5, 0xc7, 0xb1, 0xfb, 0xb9, 0x54, 0x56, 0x4c, 0x27, 0xcc, 0x81, 0xfb, - 0xb9, 0x14, 0xef, 0x42, 0x93, 0x80, 0x34, 0xaf, 0x40, 0xf2, 0x94, 0x1e, 0xc7, 0x54, 0x7d, 0x54, - 0x95, 0xf2, 0xbc, 0xc0, 0x1e, 0x47, 0xf2, 0x68, 0xf0, 0x26, 0xbf, 0x00, 0x21, 0x4c, 0x79, 0x64, - 0xfc, 0x4e, 0x25, 0xbb, 0x39, 0x15, 0x45, 0x96, 0xa1, 0x1e, 0x5a, 0xf6, 0xa9, 0x72, 0x22, 0xda, - 0x6a, 0x41, 0x3c, 0x8c, 0x49, 0x1d, 0xe2, 0x7d, 0xd0, 0x14, 0x23, 0xa5, 0xbb, 0xb6, 0x0b, 0x1c, - 0x67, 0x66, 0x9d, 0xe5, 0x87, 0xaf, 0x95, 0x1f, 0x9e, 0x42, 0xd0, 0xd0, 0x73, 0x13, 0x16, 0x1b, - 0x14, 0x4e, 0x82, 0x8c, 0x6f, 0x03, 0xe4, 0x75, 0xa8, 0x39, 0x3e, 0xd5, 0x35, 0x68, 0x58, 0x9e, - 0x6b, 0xa5, 0x21, 0x2d, 0x03, 0xc6, 0x1e, 0xb4, 0x0b, 0xd5, 0x2b, 0xa4, 0xad, 0xe5, 0x79, 0x68, - 0xfe, 0x58, 0xf6, 0x35, 0xb3, 0x65, 0x79, 0xde, 0x13, 0x79, 0x11, 0xa3, 0x3f, 0xcb, 0x85, 0xaf, - 0xea, 0x4c, 0xcd, 0x84, 0xa6, 0x9a, 0xdc, 0x69, 0x7c, 0x08, 0xcd, 0x47, 0xa9, 0xd7, 0x9f, 0x0a, - 0x43, 0xe5, 0x65, 0xc2, 0x60, 0x7c, 0xac, 0xce, 0x4c, 0x65, 0x17, 0x71, 0x57, 0x15, 0xd8, 0x62, - 0x2e, 0xe7, 0x55, 0xf2, 0xa4, 0x08, 0x0f, 0x52, 0xb5, 0x35, 0x1a, 0x6c, 0x6c, 0x83, 0xf6, 0xca, - 0x92, 0xa5, 0x22, 0x40, 0x35, 0x27, 0xc0, 0x9c, 0x22, 0xa6, 0xf1, 0x13, 0x80, 0xbc, 0x10, 0xa7, - 0x64, 0x93, 0x57, 0x41, 0xd9, 0xbc, 0x03, 0x9a, 0x7d, 0xe2, 0x7a, 0x4e, 0x24, 0xfd, 0xd2, 0xad, - 0xf3, 0xd2, 0x5d, 0xd6, 0x2f, 0x56, 0xa0, 0x4e, 0xf5, 0xc5, 0x5a, 0xae, 0x9e, 0xb3, 0xe2, 0x22, - 0xf5, 0x18, 0xe7, 0xd0, 0xe5, 0x40, 0xe1, 0x6b, 0xb8, 0x59, 0x65, 0xd5, 0x59, 0xbd, 0xa4, 0x3a, - 0xaf, 0x43, 0x93, 0xac, 0x7b, 0x7a, 0x1b, 0x05, 0xbd, 0x44, 0xa5, 0xfe, 0xff, 0x2a, 0x00, 0x6f, - 0xbd, 0x17, 0x38, 0xb2, 0x1c, 0x91, 0x57, 0x66, 0x23, 0x72, 0x01, 0xf5, 0xac, 0x74, 0xac, 0x9b, - 0xd4, 0xce, 0x2d, 0x9e, 0x8a, 0xd2, 0xd9, 0xe2, 0xbd, 0x05, 0x3a, 0x79, 0x5b, 0xee, 0xe7, 0x54, - 0xcf, 0xc0, 0x0d, 0x73, 0x44, 0xb1, 0x90, 0xda, 0x28, 0x17, 0x52, 0xb3, 0x6a, 0x53, 0x93, 0x57, - 0xe3, 0x6a, 0xd3, 0x9c, 0xc2, 0x19, 0xa7, 0x49, 0x62, 0x19, 0x25, 0x69, 0x8c, 0xcf, 0x50, 0x16, - 0xae, 0xea, 0x6a, 0xac, 0xc5, 0x89, 0x0e, 0x3f, 0x18, 0xdb, 0x81, 0x7f, 0xe4, 0xb9, 0x76, 0xa2, - 0x0a, 0xa7, 0xe0, 0x07, 0x5b, 0x0a, 0x63, 0x7c, 0x02, 0x9d, 0x94, 0xfe, 0x54, 0x9f, 0xba, 0x93, - 0x85, 0x72, 0x95, 0xfc, 0x6d, 0x73, 0x32, 0x6d, 0x56, 0x07, 0x95, 0x34, 0x98, 0x33, 0xfe, 0xa3, - 0x96, 0x4e, 0x56, 0x65, 0x94, 0x57, 0xd3, 0xb0, 0x1c, 0x9d, 0x57, 0xbf, 0x56, 0x74, 0xfe, 0x5d, - 0xd0, 0x1d, 0x0a, 0x38, 0xdd, 0xb3, 0xd4, 0x88, 0x2d, 0xcd, 0x06, 0x97, 0x2a, 0x24, 0x75, 0xcf, - 0xa4, 0x99, 0x0f, 0x7e, 0xcd, 0x3b, 0x64, 0xd4, 0x6e, 0xcc, 0xa3, 0x76, 0xf3, 0xb7, 0xa4, 0xf6, - 0x3b, 0xd0, 0xf1, 0x03, 0x7f, 0xec, 0x4f, 0x3d, 0xcf, 0x3a, 0xf4, 0xa4, 0x22, 0x77, 0xdb, 0x0f, - 0xfc, 0x3d, 0x85, 0x42, 0x17, 0xb8, 0x38, 0x84, 0x85, 0xba, 0x4d, 0xe3, 0xae, 0x14, 0xc6, 0x91, - 0xe8, 0xaf, 0x42, 0x3f, 0x38, 0xfc, 0x89, 0xb4, 0x13, 0xa2, 0xd8, 0x98, 0xa4, 0x99, 0xfd, 0xdf, - 0x1e, 0xe3, 0x91, 0x44, 0x7b, 0x28, 0xd7, 0x33, 0xcf, 0xdc, 0xbd, 0xf4, 0xcc, 0x1f, 0x83, 0x9e, - 0x51, 0xa9, 0x10, 0xdc, 0xea, 0xd0, 0xd8, 0xd9, 0xdb, 0x1e, 0xfe, 0xb0, 0x5f, 0x41, 0x73, 0x69, - 0x0e, 0x5f, 0x0c, 0xcd, 0x83, 0x61, 0xbf, 0x8a, 0xa6, 0x6c, 0x7b, 0xb8, 0x3b, 0x1c, 0x0d, 0xfb, - 0x35, 0x76, 0x85, 0xa8, 0x9a, 0xe1, 0xb9, 0xb6, 0x9b, 0x18, 0x07, 0x00, 0x79, 0xc4, 0x8e, 0x5a, - 0x39, 0x3f, 0x9c, 0x4a, 0x19, 0x26, 0xe9, 0xb1, 0x56, 0x33, 0x81, 0xac, 0xbe, 0x2c, 0x2f, 0xc0, - 0xfd, 0xc6, 0x3a, 0xe8, 0x4f, 0xad, 0xf0, 0x53, 0xae, 0xfb, 0xdd, 0x86, 0x5e, 0x68, 0x45, 0x89, - 0x9b, 0x06, 0x1d, 0xac, 0x2c, 0x3b, 0x66, 0x37, 0xc3, 0xa2, 0xee, 0x35, 0xfe, 0xac, 0x02, 0xd7, - 0x9e, 0x06, 0x67, 0x32, 0x73, 0x6a, 0x9f, 0x59, 0x17, 0x5e, 0x60, 0x39, 0xaf, 0x61, 0x43, 0x8c, - 0x9a, 0x82, 0x29, 0xd5, 0xe1, 0xd2, 0xaa, 0xa5, 0xa9, 0x33, 0xe6, 0xb1, 0xfa, 0xac, 0x42, 0xc6, - 0x09, 0x75, 0x2a, 0x43, 0x8a, 0x30, 0x76, 0xbd, 0x01, 0xcd, 0xe4, 0xdc, 0xcf, 0x6b, 0xa8, 0x8d, - 0x84, 0x52, 0xdd, 0x73, 0x7d, 0xdc, 0xc6, 0x7c, 0x1f, 0xd7, 0xd8, 0x02, 0x7d, 0x74, 0x4e, 0xc9, - 0xde, 0x69, 0x5c, 0x72, 0x73, 0x2a, 0xaf, 0x70, 0x73, 0xaa, 0x33, 0x6e, 0xce, 0xbf, 0x56, 0xa0, - 0x5d, 0x70, 0xd6, 0xc5, 0x3b, 0x50, 0x4f, 0xce, 0xfd, 0xf2, 0xa7, 0x0a, 0xe9, 0x26, 0x26, 0x75, - 0x5d, 0x4a, 0x68, 0x56, 0x2f, 0x25, 0x34, 0xc5, 0x2e, 0x5c, 0x61, 0xcd, 0x9b, 0x5e, 0x22, 0xcd, - 0xfb, 0xdc, 0x9a, 0x09, 0x0e, 0x38, 0x21, 0x9e, 0x5e, 0x49, 0x25, 0x33, 0x7a, 0xc7, 0x25, 0xe4, - 0xd2, 0x06, 0x5c, 0x9d, 0x33, 0xec, 0x9b, 0x94, 0x46, 0x8c, 0x65, 0xe8, 0x8e, 0xce, 0xfd, 0x91, - 0x3b, 0x91, 0x71, 0x62, 0x4d, 0x42, 0x72, 0x13, 0x95, 0xe5, 0xac, 0x9b, 0xd5, 0x24, 0x36, 0xde, - 0x83, 0xce, 0x33, 0x29, 0x23, 0x53, 0xc6, 0x61, 0xe0, 0xb3, 0x73, 0xa4, 0x12, 0xd1, 0x6c, 0xa6, - 0x15, 0x64, 0xfc, 0x3f, 0xd0, 0x4d, 0xeb, 0x28, 0xd9, 0xb4, 0x12, 0xfb, 0xe4, 0x9b, 0x64, 0x36, - 0xde, 0x83, 0x56, 0xc8, 0x3c, 0xa5, 0x42, 0xb8, 0x0e, 0x99, 0x6b, 0xc5, 0x67, 0x66, 0xda, 0x69, - 0xfc, 0x5f, 0xb8, 0x7a, 0x30, 0x3d, 0x8c, 0xed, 0xc8, 0xa5, 0x68, 0x38, 0x35, 0x65, 0x4b, 0xa0, - 0x85, 0x91, 0x3c, 0x72, 0xcf, 0x65, 0xca, 0xc1, 0x19, 0x2c, 0xee, 0x40, 0x6b, 0x82, 0xc7, 0x91, - 0xb9, 0x6c, 0xe4, 0x71, 0xdf, 0x53, 0xec, 0x31, 0xd3, 0x01, 0xc6, 0xf7, 0xe0, 0x5a, 0x79, 0x79, - 0x75, 0xdd, 0x5b, 0x50, 0x3b, 0x3d, 0x8b, 0xd5, 0x2d, 0x16, 0x4b, 0x71, 0x23, 0x7d, 0x4d, 0x80, - 0xbd, 0xc6, 0x1f, 0x55, 0xa0, 0xb6, 0x37, 0x9d, 0x14, 0x3f, 0x89, 0xaa, 0xf3, 0x27, 0x51, 0x37, - 0x8a, 0x39, 0x61, 0x0e, 0x51, 0xf2, 0xdc, 0xef, 0x5b, 0xa0, 0x1f, 0x05, 0xd1, 0xcf, 0xac, 0xc8, - 0x91, 0x8e, 0x32, 0x70, 0x39, 0x42, 0xdc, 0x56, 0xe6, 0x90, 0x43, 0x84, 0x45, 0x24, 0xe0, 0xde, - 0x74, 0xb2, 0xe6, 0x49, 0x2b, 0x26, 0xbd, 0xcd, 0x16, 0xd2, 0xb8, 0x0b, 0x7a, 0x86, 0x42, 0x5d, - 0xb3, 0x77, 0x30, 0xde, 0xd9, 0xe6, 0x9c, 0x1a, 0x3a, 0xd3, 0x15, 0xd4, 0x33, 0xa3, 0x1f, 0xee, - 0x8d, 0x47, 0x07, 0xfd, 0xaa, 0xf1, 0x63, 0x68, 0xa7, 0xac, 0xb8, 0xe3, 0x50, 0x01, 0x89, 0x64, - 0x61, 0xc7, 0x29, 0x89, 0xc6, 0x0e, 0x45, 0x3b, 0xd2, 0x77, 0x76, 0x52, 0x1e, 0x66, 0xa0, 0x7c, - 0x1b, 0x55, 0x8d, 0x4a, 0x6f, 0x63, 0x0c, 0x61, 0xd1, 0xa4, 0x44, 0x38, 0xda, 0xb0, 0xf4, 0x79, - 0xae, 0x43, 0xd3, 0x0f, 0x1c, 0x99, 0x6d, 0xa0, 0x20, 0xdc, 0x59, 0x79, 0x1c, 0x4a, 0x3b, 0xa4, - 0xa0, 0x21, 0x61, 0x11, 0x15, 0x8e, 0x2a, 0x94, 0xaa, 0x65, 0x4a, 0x49, 0xda, 0xca, 0x4c, 0x92, - 0x16, 0x37, 0x51, 0x95, 0x56, 0x76, 0x1d, 0xd2, 0xea, 0xea, 0x12, 0x68, 0x4e, 0x9c, 0x90, 0x84, - 0x28, 0x35, 0x93, 0xc1, 0xc6, 0x7d, 0xb8, 0xba, 0x11, 0x86, 0xde, 0x45, 0x5a, 0xbd, 0x52, 0x1b, - 0x0d, 0xf2, 0x12, 0x57, 0x45, 0x85, 0x58, 0x0c, 0x1a, 0x8f, 0xa0, 0x93, 0x46, 0xe4, 0x4f, 0x65, - 0x62, 0x91, 0xf2, 0xf0, 0xdc, 0x52, 0xb4, 0xaa, 0x31, 0x62, 0x54, 0x4e, 0x05, 0xcf, 0xdc, 0x6f, - 0x0d, 0x9a, 0x4a, 0x33, 0x09, 0xa8, 0xdb, 0x81, 0xc3, 0x1b, 0x35, 0x4c, 0x6a, 0x23, 0x07, 0x4d, - 0xe2, 0xe3, 0xd4, 0x79, 0x9c, 0xc4, 0xc7, 0xc6, 0x5f, 0x56, 0xa1, 0xbb, 0x49, 0xf9, 0x8f, 0xf4, - 0x8c, 0x85, 0xac, 0x5f, 0xa5, 0x94, 0xf5, 0x2b, 0x66, 0xf8, 0xaa, 0xa5, 0x0c, 0x5f, 0xe9, 0x40, - 0xb5, 0xb2, 0xc7, 0xf7, 0x26, 0xb4, 0xa6, 0xbe, 0x7b, 0x9e, 0xaa, 0x5c, 0xdd, 0x6c, 0x22, 0x38, - 0x8a, 0xc5, 0x0a, 0xb4, 0x51, 0x2b, 0xbb, 0x3e, 0x67, 0xd5, 0x38, 0x35, 0x56, 0x44, 0xcd, 0xe4, - 0xce, 0x9a, 0xaf, 0xce, 0x9d, 0xb5, 0x5e, 0x9b, 0x3b, 0xd3, 0x5e, 0x97, 0x3b, 0xd3, 0x67, 0x73, - 0x67, 0x65, 0x6f, 0x15, 0x66, 0xbd, 0x55, 0x63, 0x17, 0x7a, 0x29, 0xed, 0x94, 0x3c, 0x7f, 0x02, - 0x57, 0x54, 0xda, 0x5b, 0x46, 0x2a, 0x73, 0xc4, 0x1a, 0x9d, 0x04, 0x8c, 0x33, 0xd3, 0xaa, 0xc7, - 0xec, 0x39, 0x45, 0x30, 0x36, 0x7e, 0x55, 0x81, 0x6e, 0x69, 0x84, 0xf8, 0x28, 0x4f, 0xa2, 0x57, - 0x48, 0x4c, 0x07, 0x97, 0x56, 0x79, 0x75, 0x22, 0xbd, 0x3a, 0x93, 0x48, 0x37, 0xee, 0x65, 0xe9, - 0x71, 0x95, 0x14, 0x5f, 0xc8, 0x92, 0xe2, 0x94, 0x47, 0xde, 0x18, 0x8d, 0xcc, 0x7e, 0x55, 0x34, - 0xa1, 0xba, 0x77, 0xd0, 0xaf, 0x19, 0x7f, 0x5e, 0x85, 0xee, 0xf0, 0x3c, 0xa4, 0x6f, 0x9f, 0x5e, - 0xeb, 0xdb, 0x17, 0x18, 0xa7, 0x5a, 0x62, 0x9c, 0x02, 0x0b, 0xd4, 0x54, 0x55, 0x90, 0x59, 0x00, - 0xbd, 0x7d, 0x4e, 0xd5, 0x29, 0xd6, 0x60, 0xe8, 0x7f, 0x02, 0x6b, 0x94, 0x54, 0x06, 0xcc, 0xd6, - 0x75, 0x76, 0xa1, 0x97, 0x92, 0x4d, 0x31, 0xc6, 0xd7, 0x92, 0x46, 0xfe, 0xaa, 0xd1, 0xcb, 0x92, - 0x4a, 0x0c, 0x18, 0x7f, 0x5c, 0x05, 0x9d, 0xf9, 0x0c, 0x0f, 0xff, 0x81, 0x52, 0xdc, 0x95, 0xbc, - 0x84, 0x90, 0x75, 0xae, 0x3d, 0x91, 0x17, 0xb9, 0xf2, 0x9e, 0x5b, 0x76, 0x53, 0xa9, 0x27, 0x8e, - 0xbe, 0x29, 0xf5, 0x74, 0x03, 0x74, 0x76, 0x61, 0xa6, 0x2a, 0x7f, 0x5d, 0x37, 0xd9, 0xa7, 0x79, - 0xee, 0x52, 0x01, 0x2d, 0x91, 0xd1, 0x44, 0xbd, 0x01, 0xb5, 0xcb, 0x71, 0x4e, 0x37, 0xf5, 0xbc, - 0x4b, 0x14, 0x69, 0xcd, 0x52, 0xe4, 0x04, 0x5a, 0xea, 0x6c, 0xe8, 0xa6, 0x3e, 0xdf, 0x7b, 0xb2, - 0xb7, 0xff, 0x83, 0xbd, 0x12, 0xf7, 0x65, 0x8e, 0x6c, 0xb5, 0xe8, 0xc8, 0xd6, 0x10, 0xbf, 0xb5, - 0xff, 0x7c, 0x6f, 0xd4, 0xaf, 0x8b, 0x2e, 0xe8, 0xd4, 0x1c, 0x9b, 0xc3, 0x17, 0xfd, 0x06, 0x65, - 0x6e, 0xb6, 0x3e, 0x1d, 0x3e, 0xdd, 0xe8, 0x37, 0xb3, 0x82, 0x4e, 0xcb, 0xf8, 0xc3, 0x0a, 0x2c, - 0x32, 0x41, 0x8a, 0x49, 0x8c, 0xe2, 0xf7, 0xc6, 0x75, 0xfe, 0xde, 0xf8, 0xbf, 0x37, 0x6f, 0x81, - 0x93, 0xa6, 0x6e, 0x5a, 0x42, 0xe5, 0x84, 0x9a, 0x36, 0x75, 0x55, 0xe5, 0xf4, 0x6f, 0x2a, 0xb0, - 0xc4, 0xfe, 0xf3, 0xe3, 0xc8, 0x0a, 0x4f, 0xbe, 0xbf, 0x7b, 0x29, 0x82, 0x7e, 0x99, 0x57, 0x79, - 0x1b, 0x7a, 0xf4, 0x45, 0xf6, 0x4f, 0xbd, 0xb1, 0x8a, 0xf2, 0xf8, 0x75, 0xbb, 0x0a, 0xcb, 0x0b, - 0x89, 0x87, 0xd0, 0xe1, 0x2f, 0xb7, 0x29, 0x8d, 0x5c, 0x2a, 0xff, 0x95, 0xbc, 0xf7, 0x36, 0x8f, - 0xe2, 0x62, 0xe5, 0x47, 0xd9, 0xa4, 0x3c, 0xd8, 0xbe, 0x5c, 0xe1, 0x53, 0x53, 0x46, 0x14, 0x82, - 0xdf, 0x87, 0x1b, 0x73, 0xef, 0xa1, 0xd8, 0xbe, 0x90, 0xe8, 0x64, 0x6e, 0x33, 0xfe, 0xb1, 0x02, - 0xda, 0xe6, 0xd4, 0x3b, 0x25, 0x2b, 0xf7, 0x36, 0x80, 0x74, 0x8e, 0xa5, 0xfa, 0x04, 0xba, 0x42, - 0xca, 0x41, 0x47, 0x0c, 0x7f, 0x04, 0xfd, 0x09, 0x00, 0xdf, 0x71, 0x3c, 0xb1, 0x42, 0xf5, 0x44, - 0x54, 0x8e, 0x4b, 0x17, 0x50, 0x77, 0x79, 0x6a, 0x85, 0xaa, 0x1c, 0x17, 0xa7, 0x70, 0x5e, 0xa6, - 0xac, 0xbd, 0xa2, 0x4c, 0xb9, 0xb4, 0x07, 0xbd, 0xf2, 0x12, 0x73, 0x12, 0x4c, 0xef, 0x95, 0x3f, - 0x05, 0xb9, 0x4c, 0xc3, 0x82, 0xbf, 0xfb, 0x19, 0x5c, 0x99, 0xc9, 0x48, 0xbf, 0x4a, 0x63, 0x96, - 0x44, 0xa6, 0x3a, 0x23, 0x32, 0xeb, 0x7f, 0x5d, 0x81, 0x3a, 0xfa, 0xb4, 0xe2, 0x1e, 0xe8, 0x9f, - 0x4a, 0x2b, 0x4a, 0x0e, 0xa5, 0x95, 0x88, 0x92, 0xff, 0xba, 0x44, 0xd7, 0xca, 0xbf, 0xfe, 0x30, - 0x16, 0x1e, 0x54, 0xc4, 0x1a, 0x7f, 0x75, 0x9a, 0x7e, 0x4d, 0xdb, 0x4d, 0x7d, 0x63, 0xf2, 0x9d, - 0x97, 0x4a, 0xf3, 0x8d, 0x85, 0x55, 0x1a, 0xff, 0x59, 0xe0, 0xfa, 0x5b, 0xfc, 0xad, 0xa3, 0x98, - 0xf5, 0xa5, 0x67, 0x67, 0x88, 0x7b, 0xd0, 0xdc, 0x89, 0xd1, 0x69, 0xbf, 0x3c, 0x94, 0x68, 0x53, - 0xf4, 0xe7, 0x8d, 0x85, 0xf5, 0x9f, 0x37, 0xa0, 0xfe, 0x63, 0x19, 0x05, 0xe2, 0x43, 0x68, 0xa9, - 0x6f, 0x65, 0x44, 0xe1, 0x9b, 0x98, 0x25, 0xca, 0x1f, 0xcc, 0x7c, 0x44, 0x43, 0xbb, 0xf4, 0x99, - 0xbc, 0x79, 0x99, 0x44, 0xe4, 0x9f, 0xf2, 0x5c, 0x3a, 0xd4, 0xc7, 0xd0, 0x3f, 0x48, 0x22, 0x69, - 0x4d, 0x0a, 0xc3, 0xcb, 0xa4, 0x9a, 0x57, 0x73, 0x21, 0x7a, 0xdd, 0x85, 0x26, 0x47, 0x46, 0x33, - 0x13, 0x66, 0x0b, 0x2a, 0x34, 0xf8, 0x7d, 0x68, 0x1f, 0x9c, 0x04, 0x53, 0xcf, 0x39, 0x90, 0xd1, - 0x99, 0x14, 0x85, 0xaf, 0xee, 0x96, 0x0a, 0x6d, 0x63, 0x41, 0xbc, 0x0f, 0x3a, 0xfb, 0xc2, 0xe8, - 0x09, 0xb7, 0x94, 0x7b, 0xcd, 0x6b, 0x16, 0x7c, 0x64, 0x63, 0x41, 0xac, 0x02, 0x14, 0xe2, 0xa3, - 0x57, 0x8d, 0x7c, 0x08, 0xdd, 0x2d, 0xd2, 0x3a, 0xfb, 0xd1, 0xc6, 0x61, 0x10, 0x25, 0x62, 0xf6, - 0x33, 0xbb, 0xa5, 0x59, 0x84, 0xb1, 0x20, 0x1e, 0x80, 0x36, 0x8a, 0x2e, 0x78, 0xfc, 0xa2, 0x0a, - 0x2b, 0xf3, 0xfd, 0xe6, 0x5c, 0x52, 0x7c, 0x3b, 0xe3, 0xe1, 0xcc, 0x05, 0x9e, 0x57, 0x6a, 0xe1, - 0xfb, 0xb2, 0xb3, 0x69, 0x2c, 0x88, 0x8f, 0x00, 0x72, 0xff, 0x5c, 0xbc, 0xc1, 0x65, 0x9f, 0x19, - 0x7f, 0xfd, 0xf2, 0x94, 0xdc, 0x17, 0xe7, 0x29, 0x97, 0x7c, 0xf3, 0x99, 0x29, 0xdf, 0x81, 0x4e, - 0xd1, 0xaf, 0x16, 0x54, 0xda, 0x98, 0xe3, 0x69, 0x97, 0xa7, 0xad, 0xff, 0x49, 0x03, 0x9a, 0x3f, - 0x08, 0xa2, 0x53, 0x19, 0x89, 0x3b, 0xd0, 0xa4, 0x02, 0x9e, 0x12, 0x8c, 0xac, 0x98, 0x37, 0x8f, - 0x76, 0xef, 0x82, 0x4e, 0xcf, 0x3c, 0xb2, 0xe2, 0x53, 0x66, 0x3e, 0xfa, 0xfb, 0x07, 0x2f, 0xce, - 0xd9, 0x36, 0xe2, 0xd4, 0x1e, 0xb3, 0x5e, 0x56, 0xe0, 0x2e, 0x15, 0xd8, 0x96, 0xe8, 0x49, 0x9f, - 0xbc, 0x38, 0x40, 0x61, 0x7b, 0x50, 0x41, 0xfb, 0x7d, 0xc0, 0x8f, 0x87, 0x83, 0xf2, 0xcf, 0xde, - 0x59, 0x96, 0xf3, 0xef, 0xcc, 0x8d, 0x05, 0x71, 0x1f, 0x9a, 0x4a, 0x9d, 0x2f, 0xe6, 0x4a, 0x27, - 0xbd, 0x61, 0xbf, 0x88, 0x52, 0x13, 0x3e, 0x82, 0x26, 0x9b, 0x3e, 0x9e, 0x50, 0x72, 0xec, 0x97, - 0x44, 0x11, 0x95, 0x8a, 0xa7, 0xb8, 0x0b, 0x2d, 0x55, 0x9e, 0x13, 0x73, 0x6a, 0x75, 0x97, 0x5e, - 0xac, 0xc9, 0x7e, 0x0d, 0xaf, 0x5f, 0x72, 0x0d, 0x79, 0xfd, 0xb2, 0xdb, 0xc3, 0x72, 0x6c, 0x4a, - 0x5b, 0xba, 0x85, 0x24, 0x8f, 0x48, 0x29, 0x32, 0x47, 0x19, 0x7d, 0x0c, 0xdd, 0x52, 0x42, 0x48, - 0x0c, 0x52, 0xb6, 0x98, 0xcd, 0x11, 0x5d, 0x52, 0x01, 0xdf, 0x03, 0x5d, 0xc5, 0xd8, 0x87, 0x8a, - 0x31, 0xe6, 0x44, 0xf4, 0x4b, 0x97, 0x83, 0x6c, 0x92, 0xeb, 0x1f, 0xc2, 0xd5, 0x39, 0x76, 0x4c, - 0xd0, 0xe7, 0x95, 0x2f, 0x37, 0xd4, 0x4b, 0xcb, 0x2f, 0xed, 0xcf, 0x08, 0xf0, 0x5b, 0x89, 0xd3, - 0xe6, 0xe0, 0x6f, 0xbf, 0xbc, 0x59, 0xf9, 0xf5, 0x97, 0x37, 0x2b, 0xff, 0xf2, 0xe5, 0xcd, 0xca, - 0xaf, 0x7e, 0x73, 0x73, 0xe1, 0xd7, 0xbf, 0xb9, 0xb9, 0xf0, 0x0f, 0xbf, 0xb9, 0xb9, 0x70, 0xd8, - 0xa4, 0x3f, 0x52, 0x3d, 0xfc, 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x65, 0x15, 0xf2, 0xe2, 0xbe, - 0x35, 0x00, 0x00, + // 5351 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x3b, 0x4b, 0x6f, 0x1c, 0x67, + 0x72, 0x9c, 0xf7, 0x74, 0xcd, 0x43, 0xc3, 0x4f, 0xb2, 0x3c, 0x3b, 0xb2, 0x45, 0xba, 0x65, 0xd9, + 0xb4, 0x64, 0x51, 0x12, 0xb5, 0x8b, 0xac, 0xbd, 0x58, 0x20, 0x7c, 0x0c, 0x65, 0x5a, 0x14, 0xa9, + 0x6d, 0x8e, 0xb4, 0x0f, 0x20, 0x19, 0x34, 0xbb, 0x3f, 0x92, 0xbd, 0xec, 0xe9, 0xee, 0xed, 0xee, + 0xe1, 0x92, 0xbe, 0x2d, 0x02, 0xec, 0x5e, 0x72, 0x58, 0x20, 0x97, 0x9c, 0x12, 0x20, 0x87, 0x5c, + 0x72, 0x4a, 0x80, 0x00, 0xb9, 0xe4, 0x16, 0x04, 0x41, 0x2e, 0xd9, 0x63, 0x82, 0x24, 0x46, 0xe0, + 0x0d, 0x72, 0xf0, 0x21, 0x40, 0x90, 0x3f, 0x10, 0x54, 0xd5, 0xd7, 0xaf, 0xe1, 0x48, 0xb2, 0x37, + 0xc8, 0x21, 0xa7, 0xf9, 0xaa, 0xbe, 0x77, 0x7d, 0xf5, 0xae, 0x1e, 0x68, 0x06, 0x87, 0xab, 0x41, + 0xe8, 0xc7, 0xbe, 0x28, 0x07, 0x87, 0x03, 0xcd, 0x0c, 0x1c, 0x06, 0x07, 0x77, 0x8e, 0x9d, 0xf8, + 0x64, 0x7a, 0xb8, 0x6a, 0xf9, 0x93, 0xfb, 0xf6, 0x71, 0x68, 0x06, 0x27, 0xf7, 0x1c, 0xff, 0xfe, + 0xa1, 0x69, 0x1f, 0xcb, 0xf0, 0xfe, 0xd9, 0xa3, 0xfb, 0xc1, 0xe1, 0xfd, 0x64, 0xea, 0xe0, 0x5e, + 0x6e, 0xec, 0xb1, 0x7f, 0xec, 0xdf, 0x27, 0xf4, 0xe1, 0xf4, 0x88, 0x20, 0x02, 0xa8, 0xc5, 0xc3, + 0xf5, 0x01, 0x54, 0x77, 0x9d, 0x28, 0x16, 0x02, 0xaa, 0x53, 0xc7, 0x8e, 0xfa, 0xa5, 0xe5, 0xca, + 0x4a, 0xdd, 0xa0, 0xb6, 0xfe, 0x14, 0xb4, 0x91, 0x19, 0x9d, 0xbe, 0x30, 0xdd, 0xa9, 0x14, 0x3d, + 0xa8, 0x9c, 0x99, 0x6e, 0xbf, 0xb4, 0x5c, 0x5a, 0x69, 0x1b, 0xd8, 0x14, 0xab, 0xd0, 0x3c, 0x33, + 0xdd, 0x71, 0x7c, 0x11, 0xc8, 0x7e, 0x79, 0xb9, 0xb4, 0xd2, 0x5d, 0xbb, 0xba, 0x1a, 0x1c, 0xae, + 0x3e, 0xf3, 0xa3, 0xd8, 0xf1, 0x8e, 0x57, 0x5f, 0x98, 0xee, 0xe8, 0x22, 0x90, 0x46, 0xe3, 0x8c, + 0x1b, 0xfa, 0x3e, 0xb4, 0x0e, 0x42, 0x6b, 0x7b, 0xea, 0x59, 0xb1, 0xe3, 0x7b, 0xb8, 0xa3, 0x67, + 0x4e, 0x24, 0xad, 0xa8, 0x19, 0xd4, 0x46, 0x9c, 0x19, 0x1e, 0x47, 0xfd, 0xca, 0x72, 0x05, 0x71, + 0xd8, 0x16, 0x7d, 0x68, 0x38, 0xd1, 0xa6, 0x3f, 0xf5, 0xe2, 0x7e, 0x75, 0xb9, 0xb4, 0xd2, 0x34, + 0x12, 0x50, 0xff, 0xe3, 0x0a, 0xd4, 0xbe, 0x37, 0x95, 0xe1, 0x05, 0xcd, 0x8b, 0xe3, 0x30, 0x59, + 0x0b, 0xdb, 0xe2, 0x1a, 0xd4, 0x5c, 0xd3, 0x3b, 0x8e, 0xfa, 0x65, 0x5a, 0x8c, 0x01, 0x71, 0x03, + 0x34, 0xf3, 0x28, 0x96, 0xe1, 0x78, 0xea, 0xd8, 0xfd, 0xca, 0x72, 0x69, 0xa5, 0x6e, 0x34, 0x09, + 0xf1, 0xdc, 0xb1, 0xc5, 0x37, 0xa0, 0x69, 0xfb, 0x63, 0x2b, 0xbf, 0x97, 0xed, 0xd3, 0x5e, 0xe2, + 0x16, 0x34, 0xa7, 0x8e, 0x3d, 0x76, 0x9d, 0x28, 0xee, 0xd7, 0x96, 0x4b, 0x2b, 0xad, 0xb5, 0x26, + 0x5e, 0x16, 0x69, 0x67, 0x34, 0xa6, 0x8e, 0x4d, 0x44, 0xbc, 0x03, 0xcd, 0x28, 0xb4, 0xc6, 0x47, + 0x53, 0xcf, 0xea, 0xd7, 0x69, 0xd0, 0x15, 0x1c, 0x94, 0xbb, 0xb5, 0xd1, 0x88, 0x18, 0xc0, 0x6b, + 0x85, 0xf2, 0x4c, 0x86, 0x91, 0xec, 0x37, 0x78, 0x2b, 0x05, 0x8a, 0x07, 0xd0, 0x3a, 0x32, 0x2d, + 0x19, 0x8f, 0x03, 0x33, 0x34, 0x27, 0xfd, 0x66, 0xb6, 0xd0, 0x36, 0xa2, 0x9f, 0x21, 0x36, 0x32, + 0xe0, 0x28, 0x05, 0xc4, 0x23, 0xe8, 0x10, 0x14, 0x8d, 0x8f, 0x1c, 0x37, 0x96, 0x61, 0x5f, 0xa3, + 0x39, 0x5d, 0x9a, 0x43, 0x98, 0x51, 0x28, 0xa5, 0xd1, 0xe6, 0x41, 0x8c, 0x11, 0x6f, 0x03, 0xc8, + 0xf3, 0xc0, 0xf4, 0xec, 0xb1, 0xe9, 0xba, 0x7d, 0xa0, 0x33, 0x68, 0x8c, 0x59, 0x77, 0x5d, 0xf1, + 0x26, 0x9e, 0xcf, 0xb4, 0xc7, 0x71, 0xd4, 0xef, 0x2c, 0x97, 0x56, 0xaa, 0x46, 0x1d, 0xc1, 0x51, + 0x84, 0x74, 0xb5, 0x4c, 0xeb, 0x44, 0xf6, 0xbb, 0xcb, 0xa5, 0x95, 0x9a, 0xc1, 0x00, 0x62, 0x8f, + 0x9c, 0x30, 0x8a, 0xfb, 0x57, 0x18, 0x4b, 0x80, 0xbe, 0x06, 0x1a, 0x71, 0x0f, 0x51, 0xe7, 0x36, + 0xd4, 0xcf, 0x10, 0x60, 0x26, 0x6b, 0xad, 0x75, 0xf0, 0x78, 0x29, 0x83, 0x19, 0xaa, 0x53, 0xbf, + 0x09, 0xcd, 0x5d, 0xd3, 0x3b, 0x4e, 0xb8, 0x12, 0x9f, 0x8d, 0x26, 0x68, 0x06, 0xb5, 0xf5, 0x3f, + 0x2c, 0x43, 0xdd, 0x90, 0xd1, 0xd4, 0x8d, 0xc5, 0xfb, 0x00, 0xf8, 0x28, 0x13, 0x33, 0x0e, 0x9d, + 0x73, 0xb5, 0x6a, 0xf6, 0x2c, 0xda, 0xd4, 0xb1, 0x9f, 0x52, 0x97, 0x78, 0x00, 0x6d, 0x5a, 0x3d, + 0x19, 0x5a, 0xce, 0x0e, 0x90, 0x9e, 0xcf, 0x68, 0xd1, 0x10, 0x35, 0xe3, 0x3a, 0xd4, 0x89, 0x0f, + 0x98, 0x17, 0x3b, 0x86, 0x82, 0xc4, 0x6d, 0xe8, 0x3a, 0x5e, 0x8c, 0xef, 0x64, 0xc5, 0x63, 0x5b, + 0x46, 0x09, 0xa3, 0x74, 0x52, 0xec, 0x96, 0x8c, 0x62, 0xf1, 0x10, 0x98, 0xd8, 0xc9, 0x86, 0x35, + 0xda, 0xb0, 0x9b, 0x3e, 0x62, 0xc4, 0x3b, 0xd2, 0x18, 0xb5, 0xe3, 0x3d, 0x68, 0xe1, 0xfd, 0x92, + 0x19, 0x75, 0x9a, 0xd1, 0xa6, 0xdb, 0x28, 0x72, 0x18, 0x80, 0x03, 0xd4, 0x70, 0x24, 0x0d, 0x32, + 0x23, 0x33, 0x0f, 0xb5, 0xf5, 0x21, 0xd4, 0xf6, 0x43, 0x5b, 0x86, 0x73, 0xe5, 0x41, 0x40, 0xd5, + 0x96, 0x91, 0x45, 0xa2, 0xda, 0x34, 0xa8, 0x9d, 0xc9, 0x48, 0x25, 0x27, 0x23, 0xfa, 0x1f, 0x95, + 0xa0, 0x75, 0xe0, 0x87, 0xf1, 0x53, 0x19, 0x45, 0xe6, 0xb1, 0x14, 0x4b, 0x50, 0xf3, 0x71, 0x59, + 0x45, 0x61, 0x0d, 0xcf, 0x44, 0xfb, 0x18, 0x8c, 0x9f, 0x79, 0x87, 0xf2, 0xcb, 0xdf, 0x01, 0x79, + 0x87, 0xa4, 0xab, 0xa2, 0x78, 0x87, 0x64, 0xeb, 0x3a, 0xd4, 0xfd, 0xa3, 0xa3, 0x48, 0x32, 0x2d, + 0x6b, 0x86, 0x82, 0x5e, 0xca, 0x82, 0xfa, 0xb7, 0x00, 0xf0, 0x7c, 0x5f, 0x93, 0x0b, 0xf4, 0x5f, + 0x94, 0xa0, 0x65, 0x98, 0x47, 0xf1, 0xa6, 0xef, 0xc5, 0xf2, 0x3c, 0x16, 0x5d, 0x28, 0x3b, 0x36, + 0xd1, 0xa8, 0x6e, 0x94, 0x1d, 0x1b, 0x4f, 0x77, 0x1c, 0xfa, 0xd3, 0x80, 0x48, 0xd4, 0x31, 0x18, + 0x20, 0x5a, 0xda, 0x76, 0x48, 0x47, 0x46, 0x5a, 0xda, 0x76, 0x28, 0x96, 0xa0, 0x15, 0x79, 0x66, + 0x10, 0x9d, 0xf8, 0x31, 0x9e, 0xae, 0x4a, 0xa7, 0x83, 0x04, 0x35, 0x8a, 0x50, 0xb8, 0x9c, 0x68, + 0xec, 0x4a, 0x33, 0xf4, 0x64, 0x48, 0x0a, 0xa3, 0x69, 0x68, 0x4e, 0xb4, 0xcb, 0x08, 0xfd, 0x17, + 0x15, 0xa8, 0x3f, 0x95, 0x93, 0x43, 0x19, 0x5e, 0x3a, 0xc4, 0x03, 0x68, 0xd2, 0xbe, 0x63, 0xc7, + 0xe6, 0x73, 0x6c, 0xbc, 0xf1, 0xe5, 0xe7, 0x4b, 0x8b, 0x84, 0xdb, 0xb1, 0x3f, 0xf4, 0x27, 0x4e, + 0x2c, 0x27, 0x41, 0x7c, 0x61, 0x34, 0x14, 0x6a, 0xee, 0x01, 0xaf, 0x43, 0xdd, 0x95, 0x26, 0xbe, + 0x19, 0xb3, 0xa7, 0x82, 0xc4, 0x3d, 0x68, 0x98, 0x93, 0xb1, 0x2d, 0x4d, 0x9b, 0x0f, 0xb5, 0x71, + 0xed, 0xcb, 0xcf, 0x97, 0x7a, 0xe6, 0x64, 0x4b, 0x9a, 0xf9, 0xb5, 0xeb, 0x8c, 0x11, 0x1f, 0x21, + 0x4f, 0x46, 0xf1, 0x78, 0x1a, 0xd8, 0x66, 0x2c, 0x49, 0xa7, 0x55, 0x37, 0xfa, 0x5f, 0x7e, 0xbe, + 0x74, 0x0d, 0xd1, 0xcf, 0x09, 0x9b, 0x9b, 0x06, 0x19, 0x16, 0xf5, 0x5b, 0x72, 0x7d, 0xa5, 0xdf, + 0x14, 0x28, 0x76, 0x60, 0xd1, 0x72, 0xa7, 0x11, 0x2a, 0x61, 0xc7, 0x3b, 0xf2, 0xc7, 0xbe, 0xe7, + 0x5e, 0xd0, 0x03, 0x37, 0x37, 0xde, 0xfe, 0xf2, 0xf3, 0xa5, 0x6f, 0xa8, 0xce, 0x1d, 0xef, 0xc8, + 0xdf, 0xf7, 0xdc, 0x8b, 0xdc, 0xfa, 0x57, 0x66, 0xba, 0xc4, 0x6f, 0x43, 0xf7, 0xc8, 0x0f, 0x2d, + 0x39, 0x4e, 0x49, 0xd6, 0xa5, 0x75, 0x06, 0x5f, 0x7e, 0xbe, 0x74, 0x9d, 0x7a, 0x1e, 0x5f, 0xa2, + 0x5b, 0x3b, 0x8f, 0xd7, 0xff, 0xb5, 0x0c, 0x35, 0x6a, 0x8b, 0x07, 0xd0, 0x98, 0xd0, 0x93, 0x24, + 0xfa, 0xe9, 0x3a, 0xf2, 0x10, 0xf5, 0xad, 0xf2, 0x5b, 0x45, 0x43, 0x2f, 0x0e, 0x2f, 0x8c, 0x64, + 0x18, 0xce, 0x88, 0xcd, 0x43, 0x57, 0xc6, 0x91, 0xe2, 0xf9, 0xdc, 0x8c, 0x11, 0x77, 0xa8, 0x19, + 0x6a, 0xd8, 0x2c, 0xdf, 0x54, 0x2e, 0xf1, 0xcd, 0x00, 0x9a, 0xd6, 0x89, 0xb4, 0x4e, 0xa3, 0xe9, + 0x44, 0x71, 0x55, 0x0a, 0x8b, 0x5b, 0xd0, 0xa1, 0x76, 0xe0, 0x3b, 0x1e, 0x4d, 0xaf, 0xd1, 0x80, + 0x76, 0x86, 0x1c, 0x45, 0x83, 0x6d, 0x68, 0xe7, 0x0f, 0x8b, 0x66, 0xfb, 0x54, 0x5e, 0x10, 0x7f, + 0x55, 0x0d, 0x6c, 0x8a, 0x65, 0xa8, 0x91, 0xa2, 0x23, 0xee, 0x6a, 0xad, 0x01, 0x9e, 0x99, 0xa7, + 0x18, 0xdc, 0xf1, 0x71, 0xf9, 0xdb, 0x25, 0x5c, 0x27, 0x7f, 0x85, 0xfc, 0x3a, 0xda, 0xcb, 0xd7, + 0xe1, 0x29, 0xb9, 0x75, 0x74, 0x1f, 0x1a, 0xbb, 0x8e, 0x25, 0xbd, 0x88, 0x8c, 0xfb, 0x34, 0x92, + 0xa9, 0x52, 0xc2, 0x36, 0xde, 0x77, 0x62, 0x9e, 0xef, 0xf9, 0xb6, 0x8c, 0x68, 0x9d, 0xaa, 0x91, + 0xc2, 0xd8, 0x27, 0xcf, 0x03, 0x27, 0xbc, 0x18, 0x31, 0xa5, 0x2a, 0x46, 0x0a, 0x23, 0x77, 0x49, + 0x0f, 0x37, 0xb3, 0x13, 0x43, 0xad, 0x40, 0xfd, 0xe7, 0x55, 0x68, 0xff, 0x48, 0x86, 0xfe, 0xb3, + 0xd0, 0x0f, 0xfc, 0xc8, 0x74, 0xc5, 0x7a, 0x91, 0xe6, 0xfc, 0xb6, 0xcb, 0x78, 0xda, 0xfc, 0xb0, + 0xd5, 0x83, 0xf4, 0x11, 0xf8, 0xcd, 0xf2, 0xaf, 0xa2, 0x43, 0x9d, 0xdf, 0x7c, 0x0e, 0xcd, 0x54, + 0x0f, 0x8e, 0xe1, 0x57, 0xa6, 0xb3, 0x16, 0xe9, 0xa1, 0x7a, 0x50, 0x2a, 0x27, 0xe6, 0xf9, 0xf3, + 0x9d, 0x2d, 0xf5, 0xb6, 0x0a, 0x52, 0x54, 0x18, 0x9d, 0x7b, 0xa3, 0xe4, 0x51, 0x53, 0x18, 0x6f, + 0x8a, 0x14, 0x89, 0x76, 0xb6, 0xfa, 0x6d, 0xea, 0x4a, 0x40, 0xf1, 0x16, 0x68, 0x13, 0xf3, 0x1c, + 0x15, 0xda, 0x8e, 0xcd, 0xa2, 0x69, 0x64, 0x08, 0xf1, 0x0e, 0x54, 0xe2, 0x73, 0x8f, 0x64, 0x0f, + 0xbd, 0x07, 0x74, 0x26, 0x47, 0xe7, 0x9e, 0x52, 0x7d, 0x06, 0xf6, 0xe1, 0x9b, 0x5a, 0x8e, 0x4d, + 0xce, 0x82, 0x66, 0x60, 0x53, 0xdc, 0x86, 0x86, 0xcb, 0xaf, 0x45, 0x0e, 0x41, 0x6b, 0xad, 0xc5, + 0x7a, 0x94, 0x50, 0x46, 0xd2, 0x27, 0x3e, 0x84, 0x66, 0x42, 0x9d, 0x7e, 0x8b, 0xc6, 0xf5, 0x12, + 0x7a, 0x26, 0x64, 0x34, 0xd2, 0x11, 0xe2, 0x01, 0x68, 0xb6, 0x74, 0x65, 0x2c, 0xc7, 0x1e, 0x2b, + 0xf2, 0x16, 0x3b, 0x8a, 0x5b, 0x84, 0xdc, 0x8b, 0x0c, 0xf9, 0x93, 0xa9, 0x8c, 0x62, 0xa3, 0x69, + 0x2b, 0xc4, 0xe0, 0xbb, 0x70, 0x65, 0xe6, 0x39, 0xf2, 0xfc, 0xd7, 0x61, 0xfe, 0xbb, 0x96, 0xe7, + 0xbf, 0x6a, 0x8e, 0xe7, 0x3e, 0xad, 0x36, 0x9b, 0x3d, 0x4d, 0xff, 0xaf, 0x0a, 0x5c, 0x51, 0xa2, + 0x70, 0xe2, 0x04, 0x07, 0xb1, 0x52, 0x4a, 0x64, 0x72, 0x14, 0x17, 0x56, 0x8d, 0x04, 0x14, 0xbf, + 0x05, 0x75, 0xd2, 0x21, 0x89, 0x28, 0x2f, 0x65, 0x4f, 0x9c, 0x4e, 0x67, 0xd1, 0x56, 0xfc, 0xa1, + 0x86, 0x8b, 0x6f, 0x42, 0xed, 0x33, 0x19, 0xfa, 0x6c, 0x42, 0x5b, 0x6b, 0x37, 0xe7, 0xcd, 0x43, + 0xc2, 0xa8, 0x69, 0x3c, 0xf8, 0x7f, 0xcb, 0x09, 0xf0, 0x75, 0x38, 0xe1, 0x5d, 0x34, 0xa3, 0x13, + 0xff, 0x4c, 0xda, 0xfd, 0x06, 0x9d, 0x31, 0xcf, 0xbe, 0x49, 0x57, 0xc2, 0x0c, 0xcd, 0xb9, 0xcc, + 0xa0, 0xbd, 0x9c, 0x19, 0x06, 0x5b, 0xd0, 0xca, 0xd1, 0x65, 0xce, 0x43, 0x2d, 0x15, 0x15, 0x85, + 0x96, 0x2a, 0xc9, 0xbc, 0xbe, 0xd9, 0x02, 0xc8, 0xa8, 0xf4, 0x9b, 0x6a, 0x2d, 0xfd, 0x67, 0x25, + 0xb8, 0xb2, 0xe9, 0x7b, 0x9e, 0x24, 0x67, 0x9b, 0xdf, 0x3c, 0x13, 0xde, 0xd2, 0x4b, 0x85, 0xf7, + 0x03, 0xa8, 0x45, 0x38, 0x58, 0xad, 0x7e, 0x75, 0xce, 0x23, 0x1a, 0x3c, 0x02, 0x55, 0xf8, 0xc4, + 0x3c, 0x1f, 0x07, 0xd2, 0xb3, 0x1d, 0xef, 0x38, 0x51, 0xe1, 0x13, 0xf3, 0xfc, 0x19, 0x63, 0xf4, + 0xbf, 0x2a, 0x03, 0x7c, 0x22, 0x4d, 0x37, 0x3e, 0x41, 0x33, 0x85, 0x2f, 0xea, 0x78, 0x51, 0x6c, + 0x7a, 0x56, 0x12, 0xea, 0xa4, 0x30, 0xbe, 0x28, 0x5a, 0x6b, 0x19, 0xb1, 0xf2, 0xd3, 0x8c, 0x04, + 0x44, 0xfe, 0xc0, 0xed, 0xa6, 0x91, 0xb2, 0xea, 0x0a, 0xca, 0x5c, 0x94, 0x2a, 0xa1, 0x95, 0x8b, + 0xd2, 0x87, 0x06, 0x86, 0x0e, 0x8e, 0xef, 0x11, 0xd3, 0x68, 0x46, 0x02, 0xe2, 0x3a, 0xd3, 0x20, + 0x76, 0x26, 0x6c, 0xbb, 0x2b, 0x86, 0x82, 0xf0, 0x54, 0x68, 0xab, 0x87, 0xd6, 0x89, 0x4f, 0x2a, + 0xa2, 0x62, 0xa4, 0x30, 0xae, 0xe6, 0x7b, 0xc7, 0x3e, 0xde, 0xae, 0x49, 0x6e, 0x61, 0x02, 0xf2, + 0x5d, 0x6c, 0x79, 0x8e, 0x5d, 0x1a, 0x75, 0xa5, 0x30, 0xd2, 0x45, 0xca, 0xf1, 0x91, 0x34, 0xe3, + 0x69, 0x28, 0xa3, 0x3e, 0x50, 0x37, 0x48, 0xb9, 0xad, 0x30, 0xe2, 0x1d, 0x68, 0x23, 0xe1, 0xcc, + 0x28, 0x72, 0x8e, 0x3d, 0x69, 0x93, 0xe2, 0xa8, 0x1a, 0x48, 0xcc, 0x75, 0x85, 0xd2, 0xff, 0xba, + 0x0c, 0x75, 0x56, 0x99, 0x05, 0x37, 0xa8, 0xf4, 0x95, 0xdc, 0xa0, 0xb7, 0x40, 0x0b, 0x42, 0x69, + 0x3b, 0x56, 0xf2, 0x8e, 0x9a, 0x91, 0x21, 0x28, 0x3e, 0x41, 0xbb, 0x4f, 0xf4, 0x6c, 0x1a, 0x0c, + 0x08, 0x1d, 0x3a, 0xbe, 0x37, 0xb6, 0x9d, 0xe8, 0x74, 0x7c, 0x78, 0x11, 0xcb, 0x48, 0xd1, 0xa2, + 0xe5, 0x7b, 0x5b, 0x4e, 0x74, 0xba, 0x81, 0x28, 0x24, 0x21, 0xcb, 0x08, 0xc9, 0x46, 0xd3, 0x50, + 0x90, 0x78, 0x04, 0x1a, 0x79, 0xa7, 0xe4, 0xbe, 0x68, 0xe4, 0x76, 0x5c, 0xff, 0xf2, 0xf3, 0x25, + 0x81, 0xc8, 0x19, 0xbf, 0xa5, 0x99, 0xe0, 0xd0, 0xff, 0xc2, 0xc9, 0x68, 0x88, 0x48, 0x86, 0xd9, + 0xff, 0x42, 0xd4, 0x28, 0xca, 0xfb, 0x5f, 0x8c, 0x11, 0xf7, 0x40, 0x4c, 0x3d, 0xcb, 0x9f, 0x04, + 0xc8, 0x14, 0xd2, 0x56, 0x87, 0x6c, 0xd1, 0x21, 0x17, 0xf3, 0x3d, 0x74, 0x54, 0xfd, 0x5f, 0xca, + 0xd0, 0xde, 0x72, 0x42, 0x69, 0xc5, 0xd2, 0x1e, 0xda, 0xc7, 0x12, 0xcf, 0x2e, 0xbd, 0xd8, 0x89, + 0x2f, 0x94, 0x83, 0xa9, 0xa0, 0x34, 0x3e, 0x28, 0x17, 0xe3, 0x65, 0x96, 0xb0, 0x0a, 0x85, 0xf8, + 0x0c, 0x88, 0x35, 0x00, 0x8e, 0x9c, 0x28, 0xcc, 0xaf, 0xbe, 0x3c, 0xcc, 0xd7, 0x68, 0x18, 0x36, + 0x31, 0x8c, 0xe6, 0x39, 0x0e, 0x7b, 0x99, 0x75, 0xca, 0x01, 0x4c, 0x25, 0xfb, 0xaa, 0x14, 0xd0, + 0x35, 0x78, 0x63, 0x6c, 0x8b, 0x5b, 0x50, 0xf6, 0x03, 0x22, 0xae, 0x5a, 0x3a, 0x7f, 0x85, 0xd5, + 0xfd, 0xc0, 0x28, 0xfb, 0x01, 0x4a, 0x31, 0x47, 0xaf, 0xc4, 0x78, 0x28, 0xc5, 0x68, 0xd1, 0x28, + 0x96, 0x32, 0x54, 0x8f, 0xd0, 0xa1, 0x6d, 0xba, 0xae, 0xff, 0x53, 0x69, 0x3f, 0x0b, 0xa5, 0x9d, + 0xf0, 0x60, 0x01, 0x87, 0x5c, 0xe2, 0x99, 0x13, 0x19, 0x05, 0xa6, 0x25, 0x15, 0x0b, 0x66, 0x08, + 0xfd, 0x3a, 0x94, 0xf7, 0x03, 0xd1, 0x80, 0xca, 0xc1, 0x70, 0xd4, 0x5b, 0xc0, 0xc6, 0xd6, 0x70, + 0xb7, 0x87, 0x16, 0xa5, 0xde, 0x6b, 0xe8, 0x5f, 0x94, 0x41, 0x7b, 0x3a, 0x8d, 0x4d, 0xd4, 0x2d, + 0x11, 0xde, 0xb2, 0xc8, 0xa1, 0x19, 0x2b, 0x7e, 0x03, 0x9a, 0x51, 0x6c, 0x86, 0xe4, 0x6f, 0xb0, + 0x75, 0x6a, 0x10, 0x3c, 0x8a, 0xc4, 0x7b, 0x50, 0x93, 0xf6, 0xb1, 0x4c, 0xcc, 0x45, 0x6f, 0xf6, + 0xbe, 0x06, 0x77, 0x8b, 0x15, 0xa8, 0x47, 0xd6, 0x89, 0x9c, 0x98, 0xfd, 0x6a, 0x36, 0xf0, 0x80, + 0x30, 0xec, 0x60, 0x1b, 0xaa, 0x5f, 0xbc, 0x0b, 0x35, 0x7c, 0x9b, 0x48, 0x45, 0x8c, 0x14, 0x63, + 0xe2, 0x33, 0xa8, 0x61, 0xdc, 0x89, 0x8c, 0x67, 0x87, 0x7e, 0x30, 0xf6, 0x03, 0xa2, 0x7d, 0x77, + 0xed, 0x1a, 0xe9, 0xb8, 0xe4, 0x36, 0xab, 0x5b, 0xa1, 0x1f, 0xec, 0x07, 0x46, 0xdd, 0xa6, 0x5f, + 0x8c, 0x5f, 0x68, 0x38, 0x73, 0x04, 0x1b, 0x05, 0x0d, 0x31, 0x9c, 0x0c, 0x5a, 0x81, 0xe6, 0x44, + 0xc6, 0xa6, 0x6d, 0xc6, 0xa6, 0xb2, 0x0d, 0x6d, 0x56, 0x99, 0x8c, 0x33, 0xd2, 0x5e, 0xfd, 0x3e, + 0xd4, 0x79, 0x69, 0xd1, 0x84, 0xea, 0xde, 0xfe, 0xde, 0x90, 0xc9, 0xba, 0xbe, 0xbb, 0xdb, 0x2b, + 0x21, 0x6a, 0x6b, 0x7d, 0xb4, 0xde, 0x2b, 0x63, 0x6b, 0xf4, 0xc3, 0x67, 0xc3, 0x5e, 0x45, 0xff, + 0xfb, 0x12, 0x34, 0x93, 0x75, 0xc4, 0xc7, 0x00, 0x28, 0xc2, 0xe3, 0x13, 0xc7, 0x4b, 0x5d, 0xb7, + 0x1b, 0xf9, 0x9d, 0x56, 0xf1, 0x55, 0x3f, 0xc1, 0x5e, 0x36, 0xaf, 0x24, 0xf1, 0x04, 0x0f, 0x0e, + 0xa0, 0x5b, 0xec, 0x9c, 0xe3, 0xc3, 0xde, 0xcd, 0x5b, 0x95, 0xee, 0xda, 0x1b, 0x85, 0xa5, 0x71, + 0x26, 0xb1, 0x76, 0xce, 0xc0, 0xdc, 0x83, 0x66, 0x82, 0x16, 0x2d, 0x68, 0x6c, 0x0d, 0xb7, 0xd7, + 0x9f, 0xef, 0x22, 0xab, 0x00, 0xd4, 0x0f, 0x76, 0xf6, 0x1e, 0xef, 0x0e, 0xf9, 0x5a, 0xbb, 0x3b, + 0x07, 0xa3, 0x5e, 0x59, 0xff, 0x83, 0x12, 0x34, 0x13, 0x4f, 0x46, 0x7c, 0x80, 0xce, 0x07, 0xb9, + 0x5f, 0xca, 0x12, 0x51, 0x4e, 0x27, 0x17, 0x90, 0x1a, 0x49, 0x3f, 0xca, 0x22, 0x29, 0xd6, 0xc4, + 0xb7, 0x21, 0x20, 0x1f, 0x0f, 0x57, 0x0a, 0x29, 0x19, 0x0c, 0xed, 0x7d, 0x4f, 0x2a, 0x57, 0x98, + 0xda, 0xc4, 0x83, 0x8e, 0x67, 0xc9, 0x2c, 0x50, 0x68, 0x10, 0x3c, 0x8a, 0xf4, 0x98, 0x3d, 0xe4, + 0xf4, 0x60, 0xe9, 0x6e, 0xa5, 0xfc, 0x6e, 0x97, 0xc2, 0x8d, 0xf2, 0xe5, 0x70, 0x23, 0x33, 0x9c, + 0xb5, 0xd7, 0x19, 0x4e, 0xfd, 0xcf, 0xab, 0xd0, 0x35, 0x64, 0x14, 0xfb, 0xa1, 0x54, 0x1e, 0xdf, + 0xab, 0x44, 0xe8, 0x6d, 0x80, 0x90, 0x07, 0x67, 0x5b, 0x6b, 0x0a, 0xc3, 0x71, 0x92, 0xeb, 0x5b, + 0xc4, 0xbb, 0xca, 0x42, 0xa6, 0xb0, 0xb8, 0x01, 0xda, 0xa1, 0x69, 0x9d, 0xf2, 0xb2, 0x6c, 0x27, + 0x9b, 0x8c, 0xe0, 0x75, 0x4d, 0xcb, 0x92, 0x51, 0x34, 0x46, 0x56, 0x60, 0x6b, 0xa9, 0x31, 0xe6, + 0x89, 0xbc, 0xc0, 0xee, 0x48, 0x5a, 0xa1, 0x8c, 0xa9, 0xbb, 0xce, 0xdd, 0x8c, 0xc1, 0xee, 0x5b, + 0xd0, 0x89, 0x64, 0x84, 0x96, 0x75, 0x1c, 0xfb, 0xa7, 0xd2, 0x53, 0x7a, 0xac, 0xad, 0x90, 0x23, + 0xc4, 0xa1, 0x8a, 0x31, 0x3d, 0xdf, 0xbb, 0x98, 0xf8, 0xd3, 0x48, 0xd9, 0x8c, 0x0c, 0x21, 0x56, + 0xe1, 0xaa, 0xf4, 0xac, 0xf0, 0x22, 0xc0, 0xb3, 0xe2, 0x2e, 0xe3, 0x23, 0xc7, 0x95, 0xca, 0x09, + 0x5f, 0xcc, 0xba, 0x9e, 0xc8, 0x8b, 0x6d, 0xc7, 0x95, 0x78, 0xa2, 0x33, 0x73, 0xea, 0xc6, 0x63, + 0x8a, 0xf1, 0x81, 0x4f, 0x44, 0x98, 0x75, 0x0c, 0xf4, 0xef, 0xc0, 0x22, 0x77, 0x87, 0xbe, 0x2b, + 0x1d, 0x9b, 0x17, 0x6b, 0xd1, 0xa8, 0x2b, 0xd4, 0x61, 0x10, 0x9e, 0x96, 0x5a, 0x85, 0xab, 0x3c, + 0x96, 0x2f, 0x94, 0x8c, 0x6e, 0xf3, 0xd6, 0xd4, 0x75, 0xa0, 0x7a, 0x8a, 0x5b, 0x07, 0x66, 0x7c, + 0x42, 0x9e, 0x7b, 0xb2, 0xf5, 0x33, 0x33, 0x3e, 0x41, 0x8b, 0xcf, 0xdd, 0x47, 0x8e, 0x74, 0x39, + 0xf2, 0xd6, 0x0c, 0x9e, 0xb1, 0x8d, 0x18, 0xb4, 0xf8, 0x6a, 0x80, 0x1f, 0x4e, 0x4c, 0x4e, 0x0d, + 0x6a, 0x06, 0x4f, 0xda, 0x26, 0x14, 0x6e, 0xa1, 0xde, 0xca, 0x9b, 0x4e, 0xfa, 0x3d, 0x7e, 0x66, + 0xc6, 0xec, 0x4d, 0x27, 0xfa, 0x3f, 0x54, 0xa0, 0x99, 0x06, 0x72, 0x77, 0x41, 0x9b, 0x24, 0xfa, + 0x4a, 0x39, 0x6a, 0x9d, 0x82, 0x12, 0x33, 0xb2, 0x7e, 0xf1, 0x36, 0x94, 0x4f, 0xcf, 0x94, 0xee, + 0xec, 0xac, 0x72, 0xaa, 0x3c, 0x38, 0x7c, 0xb4, 0xfa, 0xe4, 0x85, 0x51, 0x3e, 0x3d, 0xfb, 0x1a, + 0x7c, 0x2b, 0xde, 0x87, 0x2b, 0x96, 0x2b, 0x4d, 0x6f, 0x9c, 0x79, 0x17, 0xcc, 0x17, 0x5d, 0x42, + 0x3f, 0x4b, 0x5d, 0x8c, 0xdb, 0x50, 0xb3, 0xa5, 0x1b, 0x9b, 0xf9, 0x8c, 0xed, 0x7e, 0x68, 0x5a, + 0xae, 0xdc, 0x42, 0xb4, 0xc1, 0xbd, 0xa8, 0x3b, 0xd3, 0xe0, 0x29, 0xa7, 0x3b, 0xe7, 0x04, 0x4e, + 0xa9, 0x5c, 0x42, 0x5e, 0x2e, 0xef, 0xc2, 0xa2, 0x3c, 0x0f, 0xc8, 0x60, 0x8c, 0xd3, 0x5c, 0x01, + 0x5b, 0xb2, 0x5e, 0xd2, 0xb1, 0x99, 0xe4, 0x0c, 0x3e, 0x44, 0x95, 0x41, 0x42, 0x43, 0xcf, 0xdc, + 0x5a, 0x13, 0xa4, 0x73, 0x0a, 0x62, 0x68, 0x24, 0x43, 0xc4, 0x07, 0xa0, 0x59, 0xb6, 0x35, 0x66, + 0xca, 0x74, 0xb2, 0xb3, 0x6d, 0x6e, 0x6d, 0x32, 0x49, 0x9a, 0x96, 0x6d, 0xb1, 0x57, 0x5d, 0x08, + 0xea, 0xba, 0x5f, 0x21, 0xa8, 0xfb, 0xb4, 0xda, 0x6c, 0xf4, 0x9a, 0xfa, 0x2d, 0x68, 0x26, 0xab, + 0xa1, 0x3e, 0x8b, 0xa4, 0xa7, 0xa2, 0x72, 0xd2, 0x67, 0x08, 0x8e, 0x22, 0xdd, 0x82, 0xca, 0x93, + 0x17, 0x07, 0xa4, 0xd6, 0xd0, 0xc2, 0xd4, 0xc8, 0x21, 0xa1, 0x76, 0xaa, 0xea, 0xca, 0x39, 0x55, + 0x77, 0x93, 0xad, 0x04, 0xbd, 0x42, 0x92, 0xca, 0xcc, 0x61, 0x90, 0x8e, 0x6c, 0x21, 0xab, 0x9c, + 0xe5, 0x24, 0x40, 0xff, 0x8f, 0x0a, 0x34, 0x94, 0x13, 0x83, 0x96, 0x61, 0x9a, 0x66, 0xe1, 0xb0, + 0x59, 0x8c, 0x2e, 0x53, 0x6f, 0x28, 0x5f, 0xf2, 0xa8, 0xbc, 0xbe, 0xe4, 0x21, 0x3e, 0x86, 0x76, + 0xc0, 0x7d, 0x79, 0xff, 0xe9, 0xcd, 0xfc, 0x1c, 0xf5, 0x4b, 0xf3, 0x5a, 0x41, 0x06, 0xa0, 0x72, + 0xa4, 0x7c, 0x70, 0x6c, 0x1e, 0x2b, 0x0a, 0x34, 0x10, 0x1e, 0x99, 0xc7, 0x5f, 0xc9, 0x19, 0xea, + 0x92, 0x57, 0xd5, 0x26, 0xad, 0x8a, 0x0e, 0x54, 0xde, 0x27, 0xe9, 0x14, 0x7d, 0x92, 0x1b, 0xa0, + 0x59, 0xfe, 0x64, 0xe2, 0x50, 0x5f, 0x57, 0x65, 0x9d, 0x08, 0x31, 0x8a, 0xf4, 0x9f, 0x97, 0xa0, + 0xa1, 0xee, 0x75, 0xc9, 0xe2, 0x6d, 0xec, 0xec, 0xad, 0x1b, 0x3f, 0xec, 0x95, 0xd0, 0xa2, 0xef, + 0xec, 0x8d, 0x7a, 0x65, 0xa1, 0x41, 0x6d, 0x7b, 0x77, 0x7f, 0x7d, 0xd4, 0xab, 0xa0, 0x15, 0xdc, + 0xd8, 0xdf, 0xdf, 0xed, 0x55, 0x45, 0x1b, 0x9a, 0x5b, 0xeb, 0xa3, 0xe1, 0x68, 0xe7, 0xe9, 0xb0, + 0x57, 0xc3, 0xb1, 0x8f, 0x87, 0xfb, 0xbd, 0x3a, 0x36, 0x9e, 0xef, 0x6c, 0xf5, 0x1a, 0xd8, 0xff, + 0x6c, 0xfd, 0xe0, 0xe0, 0xfb, 0xfb, 0xc6, 0x56, 0xaf, 0x49, 0x96, 0x74, 0x64, 0xec, 0xec, 0x3d, + 0xee, 0x69, 0xd8, 0xde, 0xdf, 0xf8, 0x74, 0xb8, 0x39, 0xea, 0x81, 0xfe, 0x10, 0x5a, 0x39, 0x5a, + 0xe1, 0x6c, 0x63, 0xb8, 0xdd, 0x5b, 0xc0, 0x2d, 0x5f, 0xac, 0xef, 0x3e, 0x47, 0xc3, 0xdb, 0x05, + 0xa0, 0xe6, 0x78, 0x77, 0x7d, 0xef, 0x71, 0xaf, 0xac, 0xdc, 0xb6, 0xef, 0x41, 0xf3, 0xb9, 0x63, + 0x6f, 0xb8, 0xbe, 0x75, 0x8a, 0xec, 0x73, 0x68, 0x46, 0x52, 0xf1, 0x1b, 0xb5, 0xd1, 0x49, 0x26, + 0xc9, 0x8c, 0xd4, 0x5b, 0x2b, 0x08, 0x29, 0xe6, 0x4d, 0x27, 0x63, 0x2a, 0x8b, 0x55, 0xd8, 0x3a, + 0x79, 0xd3, 0xc9, 0x73, 0xc7, 0x8e, 0xf4, 0x53, 0x68, 0x3c, 0x77, 0xec, 0x67, 0xa6, 0x75, 0x4a, + 0x1a, 0x0c, 0x97, 0x1e, 0x47, 0xce, 0x67, 0x52, 0x59, 0x31, 0x8d, 0x30, 0x07, 0xce, 0x67, 0x52, + 0xbc, 0x0b, 0x75, 0x02, 0x92, 0xbc, 0x02, 0xc9, 0x53, 0x72, 0x1c, 0x43, 0xf5, 0x51, 0x55, 0xca, + 0x75, 0x7d, 0x6b, 0x1c, 0xca, 0xa3, 0xfe, 0x9b, 0xfc, 0x02, 0x84, 0x30, 0xe4, 0x91, 0xfe, 0xfb, + 0xa5, 0xf4, 0xe6, 0x54, 0x14, 0x59, 0x82, 0x6a, 0x60, 0x5a, 0xa7, 0xca, 0x89, 0x68, 0xa9, 0x05, + 0xf1, 0x30, 0x06, 0x75, 0x88, 0xf7, 0xa1, 0xa9, 0x18, 0x29, 0xd9, 0xb5, 0x95, 0xe3, 0x38, 0x23, + 0xed, 0x2c, 0x3e, 0x7c, 0xa5, 0xf8, 0xf0, 0x14, 0x82, 0x06, 0xae, 0x13, 0xb3, 0xd8, 0xa0, 0x70, + 0x12, 0xa4, 0x7f, 0x13, 0x20, 0xab, 0x43, 0xcd, 0xf1, 0xa9, 0xae, 0x41, 0xcd, 0x74, 0x1d, 0x33, + 0x09, 0x69, 0x19, 0xd0, 0xf7, 0xa0, 0x95, 0xab, 0x5e, 0x21, 0x6d, 0x4d, 0xd7, 0x45, 0xf3, 0xc7, + 0xb2, 0xdf, 0x34, 0x1a, 0xa6, 0xeb, 0x3e, 0x91, 0x17, 0x11, 0xfa, 0xb3, 0x5c, 0xf8, 0x2a, 0xcf, + 0xd4, 0x4c, 0x68, 0xaa, 0xc1, 0x9d, 0xfa, 0x87, 0x50, 0xdf, 0x4e, 0xbc, 0xfe, 0x44, 0x18, 0x4a, + 0x2f, 0x13, 0x06, 0xfd, 0x23, 0x75, 0x66, 0x2a, 0xbb, 0x88, 0xbb, 0xaa, 0xc0, 0x16, 0x71, 0x39, + 0xaf, 0x94, 0x25, 0x45, 0x78, 0x90, 0xaa, 0xad, 0xd1, 0x60, 0x7d, 0x0b, 0x9a, 0xaf, 0x2c, 0x59, + 0x2a, 0x02, 0x94, 0x33, 0x02, 0xcc, 0x29, 0x62, 0xea, 0x3f, 0x06, 0xc8, 0x0a, 0x71, 0x4a, 0x36, + 0x79, 0x15, 0x94, 0xcd, 0x3b, 0xd0, 0xb4, 0x4e, 0x1c, 0xd7, 0x0e, 0xa5, 0x57, 0xb8, 0x75, 0x56, + 0xba, 0x4b, 0xfb, 0xc5, 0x32, 0x54, 0xa9, 0xbe, 0x58, 0xc9, 0xd4, 0x73, 0x5a, 0x5c, 0xa4, 0x1e, + 0xfd, 0x1c, 0x3a, 0x1c, 0x28, 0x7c, 0x05, 0x37, 0xab, 0xa8, 0x3a, 0xcb, 0x97, 0x54, 0xe7, 0x75, + 0xa8, 0x93, 0x75, 0x4f, 0x6e, 0xa3, 0xa0, 0x97, 0xa8, 0xd4, 0xdf, 0x2b, 0x03, 0xf0, 0xd6, 0x7b, + 0xbe, 0x2d, 0x8b, 0x11, 0x79, 0x69, 0x36, 0x22, 0x17, 0x50, 0x4d, 0x4b, 0xc7, 0x9a, 0x41, 0xed, + 0xcc, 0xe2, 0xa9, 0x28, 0x9d, 0x2d, 0xde, 0x5b, 0xa0, 0x91, 0xb7, 0xe5, 0x7c, 0x46, 0xf5, 0x0c, + 0xdc, 0x30, 0x43, 0xe4, 0x0b, 0xa9, 0xb5, 0x62, 0x21, 0x35, 0xad, 0x36, 0xd5, 0x79, 0x35, 0xae, + 0x36, 0xcd, 0x29, 0x9c, 0x71, 0x9a, 0x24, 0x92, 0x61, 0x9c, 0xc4, 0xf8, 0x0c, 0xa5, 0xe1, 0xaa, + 0xa6, 0xc6, 0x9a, 0x9c, 0xe8, 0xf0, 0xfc, 0xb1, 0xe5, 0x7b, 0x47, 0xae, 0x63, 0xc5, 0xaa, 0x70, + 0x0a, 0x9e, 0xbf, 0xa9, 0x30, 0xfa, 0xc7, 0xd0, 0x4e, 0xe8, 0x4f, 0xf5, 0xa9, 0x3b, 0x69, 0x28, + 0x57, 0xca, 0xde, 0x36, 0x23, 0xd3, 0x46, 0xb9, 0x5f, 0x4a, 0x82, 0x39, 0xfd, 0xbf, 0x2b, 0xc9, + 0x64, 0x55, 0x46, 0x79, 0x35, 0x0d, 0x8b, 0xd1, 0x79, 0xf9, 0x2b, 0x45, 0xe7, 0xdf, 0x06, 0xcd, + 0xa6, 0x80, 0xd3, 0x39, 0x4b, 0x8c, 0xd8, 0x60, 0x36, 0xb8, 0x54, 0x21, 0xa9, 0x73, 0x26, 0x8d, + 0x6c, 0xf0, 0x6b, 0xde, 0x21, 0xa5, 0x76, 0x6d, 0x1e, 0xb5, 0xeb, 0xbf, 0x21, 0xb5, 0xdf, 0x81, + 0xb6, 0xe7, 0x7b, 0x63, 0x6f, 0xea, 0xba, 0xe6, 0xa1, 0x2b, 0x15, 0xb9, 0x5b, 0x9e, 0xef, 0xed, + 0x29, 0x14, 0xba, 0xc0, 0xf9, 0x21, 0x2c, 0xd4, 0x2d, 0x1a, 0x77, 0x25, 0x37, 0x8e, 0x44, 0x7f, + 0x05, 0x7a, 0xfe, 0xe1, 0x8f, 0xa5, 0x15, 0x13, 0xc5, 0xc6, 0x24, 0xcd, 0xec, 0xff, 0x76, 0x19, + 0x8f, 0x24, 0xda, 0x43, 0xb9, 0x9e, 0x79, 0xe6, 0xce, 0xa5, 0x67, 0xfe, 0x08, 0xb4, 0x94, 0x4a, + 0xb9, 0xe0, 0x56, 0x83, 0xda, 0xce, 0xde, 0xd6, 0xf0, 0x07, 0xbd, 0x12, 0x9a, 0x4b, 0x63, 0xf8, + 0x62, 0x68, 0x1c, 0x0c, 0x7b, 0x65, 0x34, 0x65, 0x5b, 0xc3, 0xdd, 0xe1, 0x68, 0xd8, 0xab, 0xb0, + 0x2b, 0x44, 0xd5, 0x0c, 0xd7, 0xb1, 0x9c, 0x58, 0x3f, 0x00, 0xc8, 0x22, 0x76, 0xd4, 0xca, 0xd9, + 0xe1, 0x54, 0xca, 0x30, 0x4e, 0x8e, 0xb5, 0x92, 0x0a, 0x64, 0xf9, 0x65, 0x79, 0x01, 0xee, 0xd7, + 0xd7, 0x40, 0x7b, 0x6a, 0x06, 0x9f, 0x70, 0xdd, 0xef, 0x36, 0x74, 0x03, 0x33, 0x8c, 0x9d, 0x24, + 0xe8, 0x60, 0x65, 0xd9, 0x36, 0x3a, 0x29, 0x16, 0x75, 0xaf, 0xfe, 0x17, 0x25, 0xb8, 0xf6, 0xd4, + 0x3f, 0x93, 0xa9, 0x53, 0xfb, 0xcc, 0xbc, 0x70, 0x7d, 0xd3, 0x7e, 0x0d, 0x1b, 0x62, 0xd4, 0xe4, + 0x4f, 0xa9, 0x0e, 0x97, 0x54, 0x2d, 0x0d, 0x8d, 0x31, 0x8f, 0xd5, 0x67, 0x15, 0x32, 0x8a, 0xa9, + 0x53, 0x19, 0x52, 0x84, 0xb1, 0xeb, 0x0d, 0xa8, 0xc7, 0xe7, 0x5e, 0x56, 0x43, 0xad, 0xc5, 0x94, + 0xea, 0x9e, 0xeb, 0xe3, 0xd6, 0xe6, 0xfb, 0xb8, 0xfa, 0x26, 0x68, 0xa3, 0x73, 0x4a, 0xf6, 0x4e, + 0xa3, 0x82, 0x9b, 0x53, 0x7a, 0x85, 0x9b, 0x53, 0x9e, 0x71, 0x73, 0xfe, 0xbd, 0x04, 0xad, 0x9c, + 0xb3, 0x2e, 0xde, 0x81, 0x6a, 0x7c, 0xee, 0x15, 0x3f, 0x55, 0x48, 0x36, 0x31, 0xa8, 0xeb, 0x52, + 0x42, 0xb3, 0x7c, 0x29, 0xa1, 0x29, 0x76, 0xe1, 0x0a, 0x6b, 0xde, 0xe4, 0x12, 0x49, 0xde, 0xe7, + 0xd6, 0x4c, 0x70, 0xc0, 0x09, 0xf1, 0xe4, 0x4a, 0x2a, 0x99, 0xd1, 0x3d, 0x2e, 0x20, 0x07, 0xeb, + 0x70, 0x75, 0xce, 0xb0, 0xaf, 0x53, 0x1a, 0xd1, 0x97, 0xa0, 0x33, 0x3a, 0xf7, 0x46, 0xce, 0x44, + 0x46, 0xb1, 0x39, 0x09, 0xc8, 0x4d, 0x54, 0x96, 0xb3, 0x6a, 0x94, 0xe3, 0x48, 0x7f, 0x0f, 0xda, + 0xcf, 0xa4, 0x0c, 0x0d, 0x19, 0x05, 0xbe, 0xc7, 0xce, 0x91, 0x4a, 0x44, 0xb3, 0x99, 0x56, 0x90, + 0xfe, 0xbb, 0xa0, 0x19, 0xe6, 0x51, 0xbc, 0x61, 0xc6, 0xd6, 0xc9, 0xd7, 0xc9, 0x6c, 0xbc, 0x07, + 0x8d, 0x80, 0x79, 0x4a, 0x85, 0x70, 0x6d, 0x32, 0xd7, 0x8a, 0xcf, 0x8c, 0xa4, 0x53, 0xff, 0x1d, + 0xb8, 0x7a, 0x30, 0x3d, 0x8c, 0xac, 0xd0, 0xa1, 0x68, 0x38, 0x31, 0x65, 0x03, 0x68, 0x06, 0xa1, + 0x3c, 0x72, 0xce, 0x65, 0xc2, 0xc1, 0x29, 0x2c, 0xee, 0x40, 0x63, 0x82, 0xc7, 0x91, 0x99, 0x6c, + 0x64, 0x71, 0xdf, 0x53, 0xec, 0x31, 0x92, 0x01, 0xfa, 0x77, 0xe0, 0x5a, 0x71, 0x79, 0x75, 0xdd, + 0x5b, 0x50, 0x39, 0x3d, 0x8b, 0xd4, 0x2d, 0x16, 0x0b, 0x71, 0x23, 0x7d, 0x4d, 0x80, 0xbd, 0xfa, + 0x9f, 0x96, 0xa0, 0xb2, 0x37, 0x9d, 0xe4, 0x3f, 0x89, 0xaa, 0xf2, 0x27, 0x51, 0x37, 0xf2, 0x39, + 0x61, 0x0e, 0x51, 0xb2, 0xdc, 0xef, 0x5b, 0xa0, 0x1d, 0xf9, 0xe1, 0x4f, 0xcd, 0xd0, 0x96, 0xb6, + 0x32, 0x70, 0x19, 0x42, 0xdc, 0x56, 0xe6, 0x90, 0x43, 0x84, 0x45, 0x24, 0xe0, 0xde, 0x74, 0xb2, + 0xea, 0x4a, 0x33, 0x22, 0xbd, 0xcd, 0x16, 0x52, 0xbf, 0x0b, 0x5a, 0x8a, 0x42, 0x5d, 0xb3, 0x77, + 0x30, 0xde, 0xd9, 0xe2, 0x9c, 0x1a, 0x3a, 0xd3, 0x25, 0xd4, 0x33, 0xa3, 0x1f, 0xec, 0x8d, 0x47, + 0x07, 0xbd, 0xb2, 0xfe, 0x23, 0x68, 0x25, 0xac, 0xb8, 0x63, 0x53, 0x01, 0x89, 0x64, 0x61, 0xc7, + 0x2e, 0x88, 0xc6, 0x0e, 0x45, 0x3b, 0xd2, 0xb3, 0x77, 0x12, 0x1e, 0x66, 0xa0, 0x78, 0x1b, 0x55, + 0x8d, 0x4a, 0x6e, 0xa3, 0x0f, 0x61, 0xd1, 0xa0, 0x44, 0x38, 0xda, 0xb0, 0xe4, 0x79, 0xae, 0x43, + 0xdd, 0xf3, 0x6d, 0x99, 0x6e, 0xa0, 0x20, 0xdc, 0x59, 0x79, 0x1c, 0x4a, 0x3b, 0x24, 0xa0, 0x2e, + 0x61, 0x11, 0x15, 0x8e, 0x2a, 0x94, 0xaa, 0x65, 0x0a, 0x49, 0xda, 0xd2, 0x4c, 0x92, 0x16, 0x37, + 0x51, 0x95, 0x56, 0x76, 0x1d, 0x92, 0xea, 0xea, 0x00, 0x9a, 0x76, 0x14, 0x93, 0x84, 0x28, 0x35, + 0x93, 0xc2, 0xfa, 0x7d, 0xb8, 0xba, 0x1e, 0x04, 0xee, 0x45, 0x52, 0xbd, 0x52, 0x1b, 0xf5, 0xb3, + 0x12, 0x57, 0x49, 0x85, 0x58, 0x0c, 0xea, 0xdb, 0xd0, 0x4e, 0x22, 0xf2, 0xa7, 0x32, 0x36, 0x49, + 0x79, 0xb8, 0x4e, 0x21, 0x5a, 0x6d, 0x32, 0x62, 0x54, 0x4c, 0x05, 0xcf, 0xdc, 0x6f, 0x15, 0xea, + 0x4a, 0x33, 0x09, 0xa8, 0x5a, 0xbe, 0xcd, 0x1b, 0xd5, 0x0c, 0x6a, 0x23, 0x07, 0x4d, 0xa2, 0xe3, + 0xc4, 0x79, 0x9c, 0x44, 0xc7, 0xfa, 0x3f, 0x95, 0xa1, 0xb3, 0x41, 0xf9, 0x8f, 0xe4, 0x8c, 0xb9, + 0xac, 0x5f, 0xa9, 0x90, 0xf5, 0xcb, 0x67, 0xf8, 0xca, 0x85, 0x0c, 0x5f, 0xe1, 0x40, 0x95, 0xa2, + 0xc7, 0xf7, 0x26, 0x34, 0xa6, 0x9e, 0x73, 0x9e, 0xa8, 0x5c, 0xcd, 0xa8, 0x23, 0x38, 0x8a, 0xc4, + 0x32, 0xb4, 0x50, 0x2b, 0x3b, 0x1e, 0x67, 0xd5, 0x38, 0x35, 0x96, 0x47, 0xcd, 0xe4, 0xce, 0xea, + 0xaf, 0xce, 0x9d, 0x35, 0x5e, 0x9b, 0x3b, 0x6b, 0xbe, 0x2e, 0x77, 0xa6, 0xcd, 0xe6, 0xce, 0x8a, + 0xde, 0x2a, 0x5c, 0xf2, 0x56, 0xdf, 0x06, 0xe0, 0xcf, 0x41, 0x8e, 0xa6, 0xae, 0xab, 0x5c, 0x00, + 0x8d, 0x30, 0xdb, 0x53, 0xd7, 0xd5, 0x77, 0xa1, 0x9b, 0x90, 0x56, 0x89, 0xfb, 0xc7, 0x70, 0x45, + 0x65, 0xc5, 0x65, 0xa8, 0x12, 0x4b, 0xac, 0xf0, 0x49, 0xfe, 0x38, 0x71, 0xad, 0x7a, 0x8c, 0xae, + 0x9d, 0x07, 0x23, 0xfd, 0x97, 0x25, 0xe8, 0x14, 0x46, 0x88, 0x87, 0x59, 0x8e, 0xbd, 0x44, 0x52, + 0xdc, 0xbf, 0xb4, 0xca, 0xab, 0xf3, 0xec, 0xe5, 0x99, 0x3c, 0xbb, 0x7e, 0x2f, 0xcd, 0x9e, 0xab, + 0x9c, 0xf9, 0x42, 0x9a, 0x33, 0xa7, 0x34, 0xf3, 0xfa, 0x68, 0x64, 0xf4, 0xca, 0xa2, 0x0e, 0xe5, + 0xbd, 0x83, 0x5e, 0x45, 0xff, 0xcb, 0x32, 0x74, 0x86, 0xe7, 0x01, 0x7d, 0x1a, 0xf5, 0x5a, 0xd7, + 0x3f, 0xc7, 0x57, 0xe5, 0x02, 0x5f, 0xe5, 0x38, 0xa4, 0xa2, 0x8a, 0x86, 0xcc, 0x21, 0x18, 0x0c, + 0x70, 0x26, 0x4f, 0x71, 0x0e, 0x43, 0xff, 0x1f, 0x38, 0xa7, 0xa0, 0x51, 0x60, 0xb6, 0xec, 0xb3, + 0x0b, 0xdd, 0x84, 0x6c, 0x8a, 0x31, 0xbe, 0x92, 0xb0, 0xf2, 0x47, 0x8f, 0x6e, 0x9a, 0x73, 0x62, + 0x40, 0xff, 0xb3, 0x32, 0x68, 0xcc, 0x67, 0x78, 0xf8, 0x0f, 0x94, 0x5e, 0x2f, 0x65, 0x15, 0x86, + 0xb4, 0x73, 0xf5, 0x89, 0xbc, 0xc8, 0x74, 0xfb, 0xdc, 0xaa, 0x9c, 0xca, 0x4c, 0x71, 0x70, 0x4e, + 0x99, 0xa9, 0x1b, 0xa0, 0xb1, 0x87, 0x33, 0x55, 0xe9, 0xed, 0xaa, 0xc1, 0x2e, 0xcf, 0x73, 0x87, + 0xea, 0x6b, 0xb1, 0x0c, 0x27, 0xea, 0x0d, 0xa8, 0x5d, 0x0c, 0x83, 0x3a, 0x89, 0x63, 0x5e, 0xa0, + 0x48, 0x63, 0x96, 0x22, 0x27, 0xd0, 0x50, 0x67, 0x43, 0x2f, 0xf6, 0xf9, 0xde, 0x93, 0xbd, 0xfd, + 0xef, 0xef, 0x15, 0xb8, 0x2f, 0xf5, 0x73, 0xcb, 0x79, 0x3f, 0xb7, 0x82, 0xf8, 0xcd, 0xfd, 0xe7, + 0x7b, 0xa3, 0x5e, 0x55, 0x74, 0x40, 0xa3, 0xe6, 0xd8, 0x18, 0xbe, 0xe8, 0xd5, 0x28, 0xb1, 0xb3, + 0xf9, 0xc9, 0xf0, 0xe9, 0x7a, 0xaf, 0x9e, 0xd6, 0x7b, 0x1a, 0xfa, 0x9f, 0x94, 0x60, 0x91, 0x09, + 0x92, 0xcf, 0x71, 0xe4, 0x3f, 0x47, 0xae, 0xf2, 0xe7, 0xc8, 0xff, 0xb7, 0x69, 0x0d, 0x9c, 0x34, + 0x75, 0x92, 0x0a, 0x2b, 0xe7, 0xdb, 0x9a, 0x53, 0x47, 0x15, 0x56, 0xff, 0xb6, 0x04, 0x03, 0x76, + 0xaf, 0x1f, 0x87, 0x66, 0x70, 0xf2, 0xbd, 0xdd, 0x4b, 0x01, 0xf6, 0xcb, 0x9c, 0xce, 0xdb, 0xd0, + 0xa5, 0x0f, 0xb6, 0x7f, 0xe2, 0x8e, 0x55, 0x10, 0xc8, 0xaf, 0xdb, 0x51, 0x58, 0x5e, 0x48, 0x3c, + 0x82, 0x36, 0x7f, 0xd8, 0x4d, 0x59, 0xe6, 0x42, 0x75, 0xb0, 0xe0, 0xdc, 0xb7, 0x78, 0x14, 0xd7, + 0x32, 0x1f, 0xa6, 0x93, 0xb2, 0x58, 0xfc, 0x72, 0x01, 0x50, 0x4d, 0x19, 0x51, 0x84, 0x7e, 0x1f, + 0x6e, 0xcc, 0xbd, 0x87, 0x62, 0xfb, 0x5c, 0x1e, 0x94, 0xb9, 0x4d, 0xff, 0xe7, 0x12, 0x34, 0x37, + 0xa6, 0xee, 0x29, 0x19, 0xc1, 0xb7, 0x01, 0xa4, 0x7d, 0x2c, 0xd5, 0x17, 0xd2, 0x25, 0x52, 0x0e, + 0x1a, 0x62, 0xf8, 0x1b, 0xe9, 0x8f, 0x01, 0xf8, 0x8e, 0xe3, 0x89, 0x19, 0xa8, 0x27, 0xa2, 0x6a, + 0x5d, 0xb2, 0x80, 0xba, 0xcb, 0x53, 0x33, 0x50, 0xd5, 0xba, 0x28, 0x81, 0xb3, 0x2a, 0x66, 0xe5, + 0x15, 0x55, 0xcc, 0xc1, 0x1e, 0x74, 0x8b, 0x4b, 0xcc, 0xc9, 0x3f, 0xbd, 0x57, 0xfc, 0x52, 0xe4, + 0x32, 0x0d, 0x73, 0xee, 0xf0, 0xa7, 0x70, 0x65, 0x26, 0x61, 0xfd, 0x2a, 0x8d, 0x59, 0x10, 0x99, + 0xf2, 0xac, 0xc8, 0x7c, 0x08, 0x8b, 0x23, 0x33, 0x3a, 0x55, 0x21, 0x42, 0x66, 0xbc, 0x63, 0x33, + 0x3a, 0x1d, 0xa7, 0x44, 0xad, 0x23, 0xb8, 0x63, 0xeb, 0x0f, 0x41, 0xe4, 0x47, 0x2b, 0xfa, 0x63, + 0xe8, 0x87, 0xc3, 0x27, 0x32, 0x36, 0x13, 0x2f, 0x03, 0x11, 0x48, 0xbc, 0xb5, 0xbf, 0x29, 0x41, + 0x15, 0x7d, 0x6a, 0x71, 0x0f, 0xb4, 0x4f, 0xa4, 0x19, 0xc6, 0x87, 0xd2, 0x8c, 0x45, 0xc1, 0x7f, + 0x1e, 0x10, 0xdd, 0xb2, 0xaf, 0x4f, 0xf4, 0x85, 0x07, 0x25, 0xb1, 0xca, 0x5f, 0xbd, 0x26, 0x5f, + 0xf3, 0x76, 0x12, 0xdf, 0x9c, 0x7c, 0xf7, 0x41, 0x61, 0xbe, 0xbe, 0xb0, 0x42, 0xe3, 0x3f, 0xf5, + 0x1d, 0x6f, 0x93, 0xbf, 0xb5, 0x14, 0xb3, 0xbe, 0xfc, 0xec, 0x0c, 0x71, 0x0f, 0xea, 0x3b, 0x11, + 0x06, 0x0d, 0x97, 0x87, 0x12, 0xf1, 0xf3, 0xf1, 0x84, 0xbe, 0xb0, 0xf6, 0xb3, 0x1a, 0x54, 0x7f, + 0x24, 0x43, 0x5f, 0x7c, 0x08, 0x0d, 0xf5, 0xad, 0x8e, 0xc8, 0x7d, 0x93, 0x33, 0xa0, 0xfc, 0xc5, + 0xcc, 0x47, 0x3c, 0xb4, 0x4b, 0x8f, 0xdf, 0x2f, 0x2b, 0xd3, 0x88, 0xec, 0x53, 0xa2, 0x4b, 0x87, + 0xfa, 0x08, 0x7a, 0x07, 0x71, 0x28, 0xcd, 0x49, 0x6e, 0x78, 0x91, 0x54, 0xf3, 0x6a, 0x3e, 0x44, + 0xaf, 0xbb, 0x50, 0xe7, 0xc8, 0x6c, 0x66, 0xc2, 0x6c, 0x41, 0x87, 0x06, 0xbf, 0x0f, 0xad, 0x83, + 0x13, 0x7f, 0xea, 0xda, 0x07, 0x32, 0x3c, 0x93, 0x22, 0xf7, 0xd5, 0xdf, 0x20, 0xd7, 0xd6, 0x17, + 0xc4, 0xfb, 0xa0, 0xb1, 0x2f, 0x8e, 0x9e, 0x78, 0x43, 0xb9, 0xf7, 0xbc, 0x66, 0xce, 0x47, 0xd7, + 0x17, 0xc4, 0x0a, 0x40, 0x2e, 0x3e, 0x7b, 0xd5, 0xc8, 0x47, 0xd0, 0xd9, 0x24, 0xb5, 0xb6, 0x1f, + 0xae, 0x1f, 0xfa, 0x61, 0x2c, 0x66, 0x3f, 0xf3, 0x1b, 0xcc, 0x22, 0xf4, 0x05, 0xf1, 0x00, 0x9a, + 0xa3, 0xf0, 0x82, 0xc7, 0x2f, 0xaa, 0xb0, 0x36, 0xdb, 0x6f, 0xce, 0x25, 0xc5, 0x37, 0x53, 0x21, + 0x49, 0x5d, 0xf0, 0x79, 0xa5, 0x1e, 0xbe, 0x2f, 0x33, 0xb4, 0xbe, 0x20, 0x1e, 0x02, 0x64, 0xf1, + 0x81, 0x78, 0x83, 0xcb, 0x4e, 0x33, 0xf1, 0xc2, 0xe5, 0x29, 0x59, 0x2c, 0xc0, 0x53, 0x2e, 0xc5, + 0x06, 0x33, 0x53, 0xbe, 0x05, 0xed, 0xbc, 0x5f, 0x2f, 0xa8, 0xb4, 0x32, 0xc7, 0xd3, 0x2f, 0x4e, + 0x5b, 0xfb, 0xcf, 0x1a, 0xd4, 0xbf, 0xef, 0x87, 0xa7, 0x32, 0x14, 0x77, 0xa0, 0x4e, 0x05, 0x44, + 0x25, 0x18, 0x69, 0x31, 0x71, 0x1e, 0xed, 0xde, 0x05, 0x8d, 0x9e, 0x19, 0x25, 0x97, 0x99, 0x8f, + 0xfe, 0x7e, 0xc2, 0x8b, 0x73, 0xb6, 0x8f, 0x38, 0xb5, 0xcb, 0xac, 0x97, 0x16, 0xd8, 0x0b, 0x05, + 0xbe, 0x01, 0x3d, 0xe9, 0x93, 0x17, 0x07, 0x28, 0x6c, 0x0f, 0x4a, 0xe8, 0x20, 0x1c, 0xf0, 0xe3, + 0xe1, 0xa0, 0xec, 0xb3, 0x7b, 0x96, 0xe5, 0xec, 0x3b, 0x77, 0x7d, 0x41, 0xdc, 0x87, 0xba, 0xb2, + 0x17, 0x8b, 0x99, 0x56, 0x4b, 0x6e, 0xd8, 0xcb, 0xa3, 0xd4, 0x84, 0x87, 0x50, 0x67, 0xdb, 0xca, + 0x13, 0x0a, 0x81, 0xc5, 0x40, 0xe4, 0x51, 0x89, 0x78, 0x8a, 0xbb, 0xd0, 0x50, 0xe5, 0x41, 0x31, + 0xa7, 0x56, 0x78, 0xe9, 0xc5, 0xea, 0xec, 0x38, 0xf1, 0xfa, 0x05, 0xdf, 0x93, 0xd7, 0x2f, 0xfa, + 0x55, 0x2c, 0xc7, 0x86, 0xb4, 0xa4, 0x93, 0x4b, 0x32, 0x89, 0x84, 0x22, 0x73, 0x94, 0xd1, 0x47, + 0xd0, 0x29, 0x24, 0xa4, 0x44, 0x3f, 0x61, 0x8b, 0xd9, 0x1c, 0xd5, 0x25, 0x15, 0xf0, 0x1d, 0xd0, + 0x54, 0x8c, 0x7f, 0xa8, 0x18, 0x63, 0x4e, 0x46, 0x61, 0x70, 0x39, 0xc8, 0x27, 0xb9, 0xfe, 0x01, + 0x5c, 0x9d, 0x63, 0x28, 0x05, 0x7d, 0xde, 0xf9, 0x72, 0x4f, 0x60, 0xb0, 0xf4, 0xd2, 0xfe, 0x94, + 0x00, 0xbf, 0x99, 0x38, 0x7d, 0x17, 0x20, 0xb3, 0x17, 0x2c, 0x1b, 0x97, 0xac, 0xcd, 0xe0, 0xfa, + 0x2c, 0x3a, 0xd9, 0x74, 0xa3, 0xff, 0x77, 0x5f, 0xdc, 0x2c, 0xfd, 0xea, 0x8b, 0x9b, 0xa5, 0x7f, + 0xfb, 0xe2, 0x66, 0xe9, 0x97, 0xbf, 0xbe, 0xb9, 0xf0, 0xab, 0x5f, 0xdf, 0x5c, 0xf8, 0xc7, 0x5f, + 0xdf, 0x5c, 0x38, 0xac, 0xd3, 0xff, 0xc0, 0x1e, 0xfd, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, + 0xce, 0x8c, 0xbd, 0x7d, 0x36, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -6605,6 +6718,7 @@ type WorkerClient interface { Subscribe(ctx context.Context, in *SubscriptionRequest, opts ...grpc.CallOption) (Worker_SubscribeClient, error) UpdateGraphQLSchema(ctx context.Context, in *UpdateGraphQLSchemaRequest, opts ...grpc.CallOption) (*UpdateGraphQLSchemaResponse, error) DeleteNamespace(ctx context.Context, in *DeleteNsRequest, opts ...grpc.CallOption) (*Status, error) + TaskStatus(ctx context.Context, in *TaskStatusRequest, opts ...grpc.CallOption) (*TaskStatusResponse, error) } type workerClient struct { @@ -6802,6 +6916,15 @@ func (c *workerClient) DeleteNamespace(ctx context.Context, in *DeleteNsRequest, return out, nil } +func (c *workerClient) TaskStatus(ctx context.Context, in *TaskStatusRequest, opts ...grpc.CallOption) (*TaskStatusResponse, error) { + out := new(TaskStatusResponse) + err := c.cc.Invoke(ctx, "/pb.Worker/TaskStatus", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // WorkerServer is the server API for Worker service. type WorkerServer interface { // Data serving RPCs. @@ -6818,6 +6941,7 @@ type WorkerServer interface { Subscribe(*SubscriptionRequest, Worker_SubscribeServer) error UpdateGraphQLSchema(context.Context, *UpdateGraphQLSchemaRequest) (*UpdateGraphQLSchemaResponse, error) DeleteNamespace(context.Context, *DeleteNsRequest) (*Status, error) + TaskStatus(context.Context, *TaskStatusRequest) (*TaskStatusResponse, error) } // UnimplementedWorkerServer can be embedded to have forward compatible implementations. @@ -6863,6 +6987,9 @@ func (*UnimplementedWorkerServer) UpdateGraphQLSchema(ctx context.Context, req * func (*UnimplementedWorkerServer) DeleteNamespace(ctx context.Context, req *DeleteNsRequest) (*Status, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteNamespace not implemented") } +func (*UnimplementedWorkerServer) TaskStatus(ctx context.Context, req *TaskStatusRequest) (*TaskStatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method TaskStatus not implemented") +} func RegisterWorkerServer(s *grpc.Server, srv WorkerServer) { s.RegisterService(&_Worker_serviceDesc, srv) @@ -7121,6 +7248,24 @@ func _Worker_DeleteNamespace_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Worker_TaskStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TaskStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServer).TaskStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.Worker/TaskStatus", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServer).TaskStatus(ctx, req.(*TaskStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Worker_serviceDesc = grpc.ServiceDesc{ ServiceName: "pb.Worker", HandlerType: (*WorkerServer)(nil), @@ -7165,6 +7310,10 @@ var _Worker_serviceDesc = grpc.ServiceDesc{ MethodName: "DeleteNamespace", Handler: _Worker_DeleteNamespace_Handler, }, + { + MethodName: "TaskStatus", + Handler: _Worker_TaskStatus_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -10800,6 +10949,16 @@ func (m *BackupRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.ForceFull { + i-- + if m.ForceFull { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x58 + } if len(m.Predicates) > 0 { for iNdEx := len(m.Predicates) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Predicates[iNdEx]) @@ -11415,6 +11574,62 @@ func (m *DeleteNsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *TaskStatusRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TaskStatusRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TaskStatusRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TaskId != 0 { + i = encodeVarintPb(dAtA, i, uint64(m.TaskId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *TaskStatusResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TaskStatusResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TaskStatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.TaskMeta != 0 { + i = encodeVarintPb(dAtA, i, uint64(m.TaskMeta)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintPb(dAtA []byte, offset int, v uint64) int { offset -= sovPb(v) base := offset @@ -13049,6 +13264,9 @@ func (m *BackupRequest) Size() (n int) { n += 1 + l + sovPb(uint64(l)) } } + if m.ForceFull { + n += 2 + } return n } @@ -13303,6 +13521,30 @@ func (m *DeleteNsRequest) Size() (n int) { return n } +func (m *TaskStatusRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TaskId != 0 { + n += 1 + sovPb(uint64(m.TaskId)) + } + return n +} + +func (m *TaskStatusResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.TaskMeta != 0 { + n += 1 + sovPb(uint64(m.TaskMeta)) + } + return n +} + func sovPb(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -24048,6 +24290,26 @@ func (m *BackupRequest) Unmarshal(dAtA []byte) error { } m.Predicates = append(m.Predicates, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ForceFull", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.ForceFull = bool(v != 0) default: iNdEx = preIndex skippy, err := skipPb(dAtA[iNdEx:]) @@ -25749,6 +26011,144 @@ func (m *DeleteNsRequest) Unmarshal(dAtA []byte) error { } return nil } +func (m *TaskStatusRequest) Unmarshal(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 ErrIntOverflowPb + } + 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: TaskStatusRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TaskStatusRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TaskId", wireType) + } + m.TaskId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TaskId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPb(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TaskStatusResponse) Unmarshal(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 ErrIntOverflowPb + } + 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: TaskStatusResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TaskStatusResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TaskMeta", wireType) + } + m.TaskMeta = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TaskMeta |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipPb(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipPb(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/systest/backup/encryption/backup_test.go b/systest/backup/encryption/backup_test.go index 45f75581769..19c9653d781 100644 --- a/systest/backup/encryption/backup_test.go +++ b/systest/backup/encryption/backup_test.go @@ -16,6 +16,7 @@ package main import ( + "bytes" "context" "encoding/json" "fmt" @@ -258,8 +259,36 @@ func runBackup(t *testing.T, numExpectedFiles, numExpectedDirs int) []string { func runBackupInternal(t *testing.T, forceFull bool, numExpectedFiles, numExpectedDirs int) []string { - testutil.StartBackupHttps(t, backupDst, forceFull) - testutil.WaitForTask(t, "opBackup") + + backupRequest := `mutation backup($dst: String!, $ff: Boolean!) { + backup(input: {destination: $dst, forceFull: $ff}) { + response { + code + } + taskId + } + }` + + adminUrl := "https://" + testutil.SockAddrHttp + "/admin" + params := testutil.GraphQLParams{ + Query: backupRequest, + Variables: map[string]interface{}{ + "dst": backupDst, + "ff": forceFull, + }, + } + b, err := json.Marshal(params) + require.NoError(t, err) + client := testutil.GetHttpsClient(t) + resp, err := client.Post(adminUrl, "application/json", bytes.NewBuffer(b)) + require.NoError(t, err) + defer resp.Body.Close() + + var data interface{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&data)) + require.Equal(t, "Success", testutil.JsonGet(data, "data", "backup", "response", "code").(string)) + taskId := testutil.JsonGet(data, "data", "backup", "taskId").(string) + testutil.WaitForTask(t, taskId, true) // Verify that the right amount of files and directories were created. copyToLocalFs(t) @@ -274,7 +303,7 @@ func runBackupInternal(t *testing.T, forceFull bool, numExpectedFiles, }) require.Equal(t, numExpectedDirs, len(dirs)) - b, err := ioutil.ReadFile(filepath.Join(backupDir, "manifest.json")) + b, err = ioutil.ReadFile(filepath.Join(backupDir, "manifest.json")) require.NoError(t, err) var manifest worker.MasterManifest diff --git a/systest/backup/filesystem/backup_test.go b/systest/backup/filesystem/backup_test.go index 13a7381806d..57db08c7d67 100644 --- a/systest/backup/filesystem/backup_test.go +++ b/systest/backup/filesystem/backup_test.go @@ -123,9 +123,7 @@ func TestBackupOfOldRestore(t *testing.T) { } func TestBackupFilesystem(t *testing.T) { - conn, err := grpc.Dial( - testutil.SockAddr, - grpc.WithTransportCredentials(credentials.NewTLS(testutil.GetAlphaClientConfig(t)))) + conn, err := grpc.Dial(testutil.SockAddr, grpc.WithTransportCredentials(credentials.NewTLS(testutil.GetAlphaClientConfig(t)))) require.NoError(t, err) dg := dgo.NewDgraphClient(api.NewDgraphClient(conn)) @@ -141,7 +139,8 @@ func TestBackupFilesystem(t *testing.T) { var buf bytes.Buffer for i := 0; i < 10000; i++ { - fmt.Fprintf(&buf, "<_:x%d> \"ibrahim\" .\n", i) + buf.Write([]byte(fmt.Sprintf(`<_:x%d> "ibrahim" . + `, i))) } // Add initial data. _, err = dg.NewTxn().Mutate(ctx, &api.Mutation{ @@ -367,9 +366,38 @@ func runBackup(t *testing.T, numExpectedFiles, numExpectedDirs int) []string { return runBackupInternal(t, false, numExpectedFiles, numExpectedDirs) } -func runBackupInternal(t *testing.T, forceFull bool, numExpectedFiles, numExpectedDirs int) []string { - testutil.StartBackupHttps(t, alphaBackupDir, forceFull) - testutil.WaitForTask(t, "opBackup") +func runBackupInternal(t *testing.T, forceFull bool, numExpectedFiles, + numExpectedDirs int) []string { + backupRequest := `mutation backup($dst: String!, $ff: Boolean!) { + backup(input: {destination: $dst, forceFull: $ff}) { + response { + code + } + taskId + } + }` + + adminUrl := "https://" + testutil.SockAddrHttp + "/admin" + params := testutil.GraphQLParams{ + Query: backupRequest, + Variables: map[string]interface{}{ + "dst": alphaBackupDir, + "ff": forceFull, + }, + } + b, err := json.Marshal(params) + require.NoError(t, err) + + client := testutil.GetHttpsClient(t) + resp, err := client.Post(adminUrl, "application/json", bytes.NewBuffer(b)) + require.NoError(t, err) + defer resp.Body.Close() + + var data interface{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&data)) + require.Equal(t, "Success", testutil.JsonGet(data, "data", "backup", "response", "code").(string)) + taskId := testutil.JsonGet(data, "data", "backup", "taskId").(string) + testutil.WaitForTask(t, taskId, true) // Verify that the right amount of files and directories were created. common.CopyToLocalFs(t) @@ -384,7 +412,7 @@ func runBackupInternal(t *testing.T, forceFull bool, numExpectedFiles, numExpect }) require.Equal(t, numExpectedDirs, len(dirs)) - b, err := ioutil.ReadFile(filepath.Join(copyBackupDir, "manifest.json")) + b, err = ioutil.ReadFile(filepath.Join(copyBackupDir, "manifest.json")) require.NoError(t, err) var manifest worker.MasterManifest err = json.Unmarshal(b, &manifest) diff --git a/systest/backup/minio-large/backup_test.go b/systest/backup/minio-large/backup_test.go index 2a09d90b90f..137daf91c79 100644 --- a/systest/backup/minio-large/backup_test.go +++ b/systest/backup/minio-large/backup_test.go @@ -16,11 +16,11 @@ package main import ( + "bytes" "context" + "encoding/json" "fmt" - "io/ioutil" "math" - "net/url" "os" "strings" "testing" @@ -144,19 +144,36 @@ func addTriples(t *testing.T, dg *dgo.Dgraph, numTriples int) { } func runBackup(t *testing.T) { - // Using the old /admin/backup endpoint to ensure it works. Change back to using - // the GraphQL endpoint at /admin once this endpoint is deprecated. - backupUrl := "https://" + testutil.SockAddrHttp + "/admin/backup" + backupRequest := `mutation backup($dst: String!, $ff: Boolean!) { + backup(input: {destination: $dst, forceFull: $ff}) { + response { + code + } + taskId + } + }` + + adminUrl := "https://" + testutil.SockAddrHttp + "/admin" + params := testutil.GraphQLParams{ + Query: backupRequest, + Variables: map[string]interface{}{ + "dst": backupDestination, + "ff": false, + }, + } + b, err := json.Marshal(params) + require.NoError(t, err) + client := testutil.GetHttpsClient(t) - resp, err := client.PostForm(backupUrl, url.Values{ - "destination": []string{backupDestination}, - }) + resp, err := client.Post(adminUrl, "application/json", bytes.NewBuffer(b)) require.NoError(t, err) defer resp.Body.Close() - buf, err := ioutil.ReadAll(resp.Body) - require.NoError(t, err) - require.Contains(t, string(buf), "Backup queued successfully") - testutil.WaitForTask(t, "opBackup") + + var data interface{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&data)) + require.Equal(t, "Success", testutil.JsonGet(data, "data", "backup", "response", "code").(string)) + taskId := testutil.JsonGet(data, "data", "backup", "taskId").(string) + testutil.WaitForTask(t, taskId, true) // Verify that the right amount of files and directories were created. copyToLocalFs(t) diff --git a/systest/backup/minio/backup_test.go b/systest/backup/minio/backup_test.go index 7713dd6c305..b759dae2ce0 100644 --- a/systest/backup/minio/backup_test.go +++ b/systest/backup/minio/backup_test.go @@ -16,6 +16,7 @@ package main import ( + "bytes" "context" "encoding/json" "fmt" @@ -278,8 +279,37 @@ func runBackup(t *testing.T, numExpectedFiles, numExpectedDirs int) []string { func runBackupInternal(t *testing.T, forceFull bool, numExpectedFiles, numExpectedDirs int) []string { - testutil.StartBackupHttps(t, backupDst, forceFull) - testutil.WaitForTask(t, "opBackup") + + backupRequest := `mutation backup($dst: String!, $ff: Boolean!) { + backup(input: {destination: $dst, forceFull: $ff}) { + response { + code + } + taskId + } + }` + + adminUrl := "https://" + testutil.SockAddrHttp + "/admin" + params := testutil.GraphQLParams{ + Query: backupRequest, + Variables: map[string]interface{}{ + "dst": backupDst, + "ff": forceFull, + }, + } + b, err := json.Marshal(params) + require.NoError(t, err) + + client := testutil.GetHttpsClient(t) + resp, err := client.Post(adminUrl, "application/json", bytes.NewBuffer(b)) + require.NoError(t, err) + defer resp.Body.Close() + + var data interface{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&data)) + require.Equal(t, "Success", testutil.JsonGet(data, "data", "backup", "response", "code").(string)) + taskId := testutil.JsonGet(data, "data", "backup", "taskId").(string) + testutil.WaitForTask(t, taskId, true) // Verify that the right amount of files and directories were created. copyToLocalFs(t) @@ -294,7 +324,7 @@ func runBackupInternal(t *testing.T, forceFull bool, numExpectedFiles, }) require.Equal(t, numExpectedDirs, len(dirs)) - b, err := ioutil.ReadFile(filepath.Join(backupDir, "manifest.json")) + b, err = ioutil.ReadFile(filepath.Join(backupDir, "manifest.json")) require.NoError(t, err) var manifest worker.MasterManifest diff --git a/systest/backup/multi-tenancy/backup_test.go b/systest/backup/multi-tenancy/backup_test.go index 036ad43aa00..5ba453ba572 100644 --- a/systest/backup/multi-tenancy/backup_test.go +++ b/systest/backup/multi-tenancy/backup_test.go @@ -138,8 +138,8 @@ func runBackupInternal(t *testing.T, token *testutil.HttpToken, forceFull bool, backup(input: {destination: $dst, forceFull: $ff}) { response { code - message } + taskId } }` @@ -150,17 +150,13 @@ func runBackupInternal(t *testing.T, token *testutil.HttpToken, forceFull bool, "ff": forceFull, }, } + resp := testutil.MakeRequest(t, token, params) - var result struct { - Backup struct { - Response struct { - Message, Code string - } - } - } - require.NoError(t, json.Unmarshal(resp.Data, &result)) - require.Contains(t, result.Backup.Response.Message, "Backup queued successfully") - testutil.WaitForTask(t, "opBackup") + var data interface{} + require.NoError(t, json.Unmarshal(resp.Data, &data)) + require.Equal(t, "Success", testutil.JsonGet(data, "backup", "response", "code").(string)) + taskId := testutil.JsonGet(data, "backup", "taskId").(string) + testutil.WaitForTask(t, taskId, false) // Verify that the right amount of files and directories were created. common.CopyToLocalFs(t) diff --git a/systest/export/export_test.go b/systest/export/export_test.go index 15f9d7bc6fd..306fdd0d57f 100644 --- a/systest/export/export_test.go +++ b/systest/export/export_test.go @@ -24,6 +24,7 @@ import ( "net/http" "os" "path/filepath" + "strings" "testing" "github.com/dgraph-io/dgo/v210" @@ -52,20 +53,17 @@ func TestExportSchemaToMinio(t *testing.T) { mc.MakeBucket(bucketName, "") setupDgraph(t, moviesData, movieSchema) - result := requestExport(t, minioDest, "rdf") - - require.Equal(t, "Success", getFromJSON(result, "data", "export", "response", "code").(string)) - require.Equal(t, "Export completed.", - getFromJSON(result, "data", "export", "response", "message").(string)) - - var files []string - for _, f := range getFromJSON(result, "data", "export", "exportedFiles").([]interface{}) { - files = append(files, f.(string)) + requestExport(t, minioDest, "rdf") + + schemaFile := "" + doneCh := make(chan struct{}) + defer close(doneCh) + for obj := range mc.ListObjectsV2(bucketName, "dgraph.", true, doneCh) { + if strings.Contains(obj.Key, ".schema.gz") { + schemaFile = obj.Key + } } - require.Equal(t, 3, len(files)) - - schemaFile := files[1] - require.Contains(t, schemaFile, ".schema.gz") + require.NotEmpty(t, schemaFile) object, err := mc.GetObject(bucketName, schemaFile, minio.GetObjectOptions{}) require.NoError(t, err) @@ -113,16 +111,7 @@ func TestExportAndLoadJson(t *testing.T) { setupDgraph(t, moviesData, movieSchema) // Run export - result := requestExport(t, "/data/export-data", "json") - require.Equal(t, "Success", getFromJSON(result, "data", "export", "response", "code").(string)) - require.Equal(t, "Export completed.", - getFromJSON(result, "data", "export", "response", "message").(string)) - - var files []string - for _, f := range getFromJSON(result, "data", "export", "exportedFiles").([]interface{}) { - files = append(files, f.(string)) - } - require.Equal(t, 3, len(files)) + requestExport(t, "/data/export-data", "json") copyToLocalFs(t) q := `{ q(func:has(movie)) { count(uid) } }` @@ -140,8 +129,11 @@ func TestExportAndLoadJson(t *testing.T) { require.JSONEq(t, `{"data": {"q": [{"count":0}]}}`, res) // Live load the exported data - base := filepath.Dir(files[0]) - dir := filepath.Join(copyExportDir, base) + files, err := ioutil.ReadDir(copyExportDir) + require.NoError(t, err) + require.Len(t, files, 1) + exportName := files[0].Name() + dir := filepath.Join(copyExportDir, exportName) loadData(t, dir, "json") res = runQuery(t, q) @@ -175,16 +167,7 @@ func TestExportAndLoadJsonFacets(t *testing.T) { setupDgraph(t, facetsData, facetsSchema) // Run export - result := requestExport(t, "/data/export-data", "json") - require.Equal(t, "Success", getFromJSON(result, "data", "export", "response", "code").(string)) - require.Equal(t, "Export completed.", - getFromJSON(result, "data", "export", "response", "message").(string)) - - var files []string - for _, f := range getFromJSON(result, "data", "export", "exportedFiles").([]interface{}) { - files = append(files, f.(string)) - } - require.Equal(t, 3, len(files)) + requestExport(t, "/data/export-data", "json") copyToLocalFs(t) checkRes := func() { @@ -225,8 +208,11 @@ func TestExportAndLoadJsonFacets(t *testing.T) { require.JSONEq(t, `{"data": {"q": []}}`, res) // Live load the exported data and verify that exported data is loaded correctly. - base := filepath.Dir(files[0]) - dir := filepath.Join(copyExportDir, base) + files, err := ioutil.ReadDir(copyExportDir) + require.NoError(t, err) + require.Len(t, files, 1) + exportName := files[0].Name() + dir := filepath.Join(copyExportDir, exportName) loadData(t, dir, "json") // verify that the state after loading the exported data as same. @@ -299,14 +285,13 @@ func setupDgraph(t *testing.T, nquads, schema string) { require.NoError(t, err) } -func requestExport(t *testing.T, dest string, format string) map[string]interface{} { +func requestExport(t *testing.T, dest string, format string) { exportRequest := `mutation export($dst: String!, $f: String!) { export(input: {destination: $dst, format: $f}) { response { code - message } - exportedFiles + taskId } }` @@ -323,19 +308,10 @@ func requestExport(t *testing.T, dest string, format string) map[string]interfac resp, err := http.Post(adminUrl, "application/json", bytes.NewBuffer(b)) require.NoError(t, err) - buf, err := ioutil.ReadAll(resp.Body) - require.NoError(t, err) - - var result map[string]interface{} - require.NoError(t, json.Unmarshal(buf, &result)) - return result -} - -func getFromJSON(j map[string]interface{}, path ...string) interface{} { - var res interface{} = j - for _, p := range path { - res = res.(map[string]interface{})[p] - } - return res + var data interface{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&data)) + require.Equal(t, "Success", testutil.JsonGet(data, "data", "export", "response", "code").(string)) + taskId := testutil.JsonGet(data, "data", "export", "taskId").(string) + testutil.WaitForTask(t, taskId, false) } diff --git a/systest/mutations_test.go b/systest/mutations_test.go index 496e3096bb7..129e70f8083 100644 --- a/systest/mutations_test.go +++ b/systest/mutations_test.go @@ -1738,7 +1738,7 @@ func CountIndexConcurrentSetDelUIDList(t *testing.T, c *dgo.Dgraph) { CommitNow: true, } - mu.SetNquads = []byte(fmt.Sprintf("<0x1> <0x%x> .", id)) + mu.SetNquads = []byte(fmt.Sprintf("<0x1> <%#x> .", id)) _, err := dg.NewTxn().Mutate(context.Background(), mu) if err != nil && err != dgo.ErrAborted { require.Fail(t, "unable to inserted uid with err: %s", err) @@ -1789,7 +1789,7 @@ func CountIndexConcurrentSetDelUIDList(t *testing.T, c *dgo.Dgraph) { CommitNow: true, } - mu.DelNquads = []byte(fmt.Sprintf("<0x1> <0x%x> .", id)) + mu.DelNquads = []byte(fmt.Sprintf("<0x1> <%#x> .", id)) _, err := dg.NewTxn().Mutate(context.Background(), mu) if err != nil && err != dgo.ErrAborted { require.Fail(t, "unable to delete uid with err: %s", err) diff --git a/systest/online-restore/online_restore_test.go b/systest/online-restore/online_restore_test.go index 1faa1e1a398..433590974c7 100644 --- a/systest/online-restore/online_restore_test.go +++ b/systest/online-restore/online_restore_test.go @@ -563,7 +563,6 @@ func backup(t *testing.T, backupDir string) { } testutil.MakeGQLRequestWithTLS(t, backupParams, testutil.GetAlphaClientConfig(t)). RequireNoGraphQLErrors(t) - testutil.WaitForTask(t, "opBackup") } func backupRestoreAndVerify(t *testing.T, dg *dgo.Dgraph, backupDir, queryToVerify, diff --git a/testutil/backup.go b/testutil/backup.go index 98f8393fff1..f1e9f904eb0 100644 --- a/testutil/backup.go +++ b/testutil/backup.go @@ -17,9 +17,7 @@ package testutil import ( - "bytes" "context" - "encoding/json" "fmt" "io/ioutil" "net/http" @@ -62,49 +60,21 @@ func openDgraph(pdir string) (*badger.DB, error) { return badger.OpenManaged(opt) } -func StartBackupHttps(t *testing.T, backupDst string, forceFull bool) { - const backupRequest = `mutation backup($dst: String!, $ff: Boolean!) { - backup(input: {destination: $dst, forceFull: $ff}) { - response { - code - message - } - } - }` - - adminUrl := "https://" + SockAddrHttp + "/admin" - params := GraphQLParams{ - Query: backupRequest, - Variables: map[string]interface{}{ - "dst": backupDst, - "ff": forceFull, - }, - } - - var buffer bytes.Buffer - err := json.NewEncoder(&buffer).Encode(params) - require.NoError(t, err) - - client := GetHttpsClient(t) - response, err := client.Post(adminUrl, "application/json", &buffer) - require.NoError(t, err) - - responseBody, err := ioutil.ReadAll(response.Body) - require.NoError(t, err) - require.Contains(t, string(responseBody), "Backup queued successfully") -} - func WaitForRestore(t *testing.T, dg *dgo.Dgraph) { + restoreDone := false for { resp, err := http.Get("http://" + SockAddrHttp + "/health") require.NoError(t, err) buf, err := ioutil.ReadAll(resp.Body) require.NoError(t, err) - if !strings.Contains(string(buf), "opRestore") { + sbuf := string(buf) + if !strings.Contains(sbuf, "opRestore") { + restoreDone = true break } time.Sleep(4 * time.Second) } + require.True(t, restoreDone) // Wait for the client to exit draining mode. This is needed because the client might // be connected to a follower and might be behind the leader in applying the restore. @@ -132,7 +102,7 @@ func WaitForRestore(t *testing.T, dg *dgo.Dgraph) { // The server has been responsive three times in a row. break } - time.Sleep(time.Second) + time.Sleep(1 * time.Second) } } diff --git a/testutil/client.go b/testutil/client.go index 7abb9cc86aa..5641fc65971 100644 --- a/testutil/client.go +++ b/testutil/client.go @@ -33,7 +33,6 @@ import ( "time" "github.com/dgraph-io/dgraph/gql" - "github.com/dgraph-io/dgraph/protos/pb" "github.com/dgraph-io/dgo/v210" "github.com/dgraph-io/dgo/v210/protos/api" @@ -71,10 +70,6 @@ func AdminUrl() string { return "http://" + SockAddrHttp + "/admin" } -func HealthUrl() string { - return "http://" + SockAddrHttp + "/health" -} - // This allows running (most) tests against dgraph running on the default ports, for example. // Only the GRPC ports are needed and the others are deduced. func init() { @@ -533,34 +528,3 @@ func GetAlphaClientConfig(t *testing.T) *tls.Config { require.NoError(t, err) return tlsConf } - -func WaitForTask(t *testing.T, task string) { - healthUrl := "http://" + SockAddrHttp + "/health" - for { - time.Sleep(5 * time.Second) - - var health []pb.HealthInfo - func() { - // #nosec G107 - response, err := http.Get(healthUrl) - require.NoError(t, err) - defer response.Body.Close() - - decoder := json.NewDecoder(response.Body) - err = decoder.Decode(&health) - require.NoError(t, err) - require.Len(t, health, 1) - }() - - completed := true - for _, ongoingTask := range health[0].Ongoing { - if ongoingTask == task { - completed = false - break - } - } - if completed { - break - } - } -} diff --git a/testutil/utils.go b/testutil/utils.go index b88aae972f4..c0861bab533 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -16,7 +16,17 @@ package testutil -import "github.com/dgraph-io/dgraph/x" +import ( + "bytes" + "encoding/json" + "log" + "net/http" + "testing" + "time" + + "github.com/dgraph-io/dgraph/x" + "github.com/stretchr/testify/require" +) func GalaxySchemaKey(attr string) []byte { attr = x.GalaxyAttr(attr) @@ -47,3 +57,52 @@ func GalaxyCountKey(attr string, count uint32, reverse bool) []byte { attr = x.GalaxyAttr(attr) return x.CountKey(attr, count, reverse) } + +func WaitForTask(t *testing.T, taskId string, useHttps bool) { + const query = `query task($id: String!) { + task(input: {id: $id}) { + status + } + }` + params := GraphQLParams{ + Query: query, + Variables: map[string]interface{}{"id": taskId}, + } + request, err := json.Marshal(params) + require.NoError(t, err) + + for { + time.Sleep(4 * time.Second) + + var adminUrl string + var client http.Client + if useHttps { + adminUrl = "https://" + SockAddrHttp + "/admin" + client = GetHttpsClient(t) + } else { + adminUrl = "http://" + SockAddrHttp + "/admin" + client = *http.DefaultClient + } + response, err := client.Post(adminUrl, "application/json", bytes.NewBuffer(request)) + require.NoError(t, err) + defer response.Body.Close() + + var data interface{} + require.NoError(t, json.NewDecoder(response.Body).Decode(&data)) + status := JsonGet(data, "data", "task", "status").(string) + switch status { + case "Success": + log.Printf("export complete") + return + case "Failed", "Unknown": + t.Errorf("task failed with status: %s", status) + } + } +} + +func JsonGet(j interface{}, components ...string) interface{} { + for _, component := range components { + j = j.(map[string]interface{})[component] + } + return j +} diff --git a/worker/backup.go b/worker/backup.go index c1c537a87f4..7a17072c385 100644 --- a/worker/backup.go +++ b/worker/backup.go @@ -28,13 +28,6 @@ import ( "github.com/dgraph-io/dgraph/x" ) -const ( - unknownStatus = "UNKNOWN" - inProgressStatus = "IN_PROGRESS" - okStatus = "OK" - errStatus = "ERR" -) - // predicateSet is a map whose keys are predicates. It is meant to be used as a set. type predicateSet map[string]struct{} diff --git a/worker/backup_ee.go b/worker/backup_ee.go index 12a768edecc..52455b52bce 100644 --- a/worker/backup_ee.go +++ b/worker/backup_ee.go @@ -108,38 +108,16 @@ type BackupRes struct { err error } -func ProcessBackupRequest(ctx context.Context, req *pb.BackupRequest, forceFull bool) error { - if !EnterpriseEnabled() { - return errors.New("you must enable enterprise features first. " + - "Supply the appropriate license file to Dgraph Zero using the HTTP endpoint.") - } - - if req.Destination == "" { - return errors.Errorf("you must specify a 'destination' value") - } - +func ProcessBackupRequest(ctx context.Context, req *pb.BackupRequest) error { if err := x.HealthCheck(); err != nil { - glog.Errorf("Backup canceled: not ready to accept requests: %s", err) + glog.Errorf("Backup canceled, not ready to accept requests: %s", err) return err } - go func() { - // Grab the lock here to avoid more than one request to be processed at the same time. - backupLock.Lock() - defer backupLock.Unlock() + // Grab the lock here to avoid more than one request to be processed at the same time. + backupLock.Lock() + defer backupLock.Unlock() - glog.Infof("Backup started: %s", req.Destination) - if err := doBackup(ctx, req, forceFull); err != nil { - glog.Errorf("Backup error: %s: %s", err, req.Destination) - } else { - glog.Infof("Backup complete: %s", req.Destination) - } - }() - - return nil -} - -func doBackup(ctx context.Context, req *pb.BackupRequest, forceFull bool) error { backupSuccessful := false ostats.Record(ctx, x.NumBackups.M(1), x.PendingBackups.M(1)) defer func() { @@ -173,11 +151,8 @@ func doBackup(ctx context.Context, req *pb.BackupRequest, forceFull bool) error return err } - // Use the readTs as the sinceTs for the next backup. If not found, use the - // SinceTsDeprecated value from the latest manifest. req.SinceTs = latestManifest.ValidReadTs() - if forceFull { - // To force a full backup we'll set the sinceTs to zero. + if req.ForceFull { req.SinceTs = 0 } else { if x.WorkerConfig.EncryptionKey != nil { @@ -208,16 +183,13 @@ func doBackup(ctx context.Context, req *pb.BackupRequest, forceFull bool) error predMap := make(map[uint32][]string) for gid, group := range state.Groups { groups = append(groups, gid) - preds := make([]string, 0, len(group.Tablets)) + predMap[gid] = make([]string, 0) for pred := range group.Tablets { - preds = append(preds, pred) + predMap[gid] = append(predMap[gid], pred) } - predMap[gid] = preds } - glog.Infof( - "Created backup request: read_ts:%d since_ts:%d unix_ts:%q destination:%q. Groups=%v\n", - req.ReadTs, req.SinceTs, req.UnixTs, req.Destination, groups) + glog.Infof("Created backup request: read_ts:%d since_ts:%d unix_ts:\"%s\" destination:\"%s\" . Groups=%v\n", req.ReadTs, req.SinceTs, req.UnixTs, req.Destination, groups) ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -282,7 +254,11 @@ func ProcessListBackups(ctx context.Context, location string, creds *x.MinioCred return nil, errors.Wrapf(err, "cannot read manifests at location %s", location) } - return manifests, nil + res := make([]*Manifest, 0) + for _, m := range manifests { + res = append(res, m) + } + return res, nil } // BackupProcessor handles the different stages of the backup process. @@ -318,9 +294,9 @@ func NewBackupProcessor(db *badger.DB, req *pb.BackupRequest) *BackupProcessor { bp.txn = db.NewTransactionAt(req.ReadTs, false) } for i := range bp.threads { - buf, err := z.NewBufferWith(32<<20, 32<<30, z.UseCalloc, "Worker.BackupProcessor") - x.Check(err) - buf.AutoMmapAfter(1 << 30) + buf := z.NewBuffer(32<<20, "Worker.BackupProcessor"). + WithAutoMmap(1<<30, ""). + WithMaxSize(32 << 30) bp.threads[i] = &threadLocal{ Request: bp.Request, diff --git a/worker/backup_oss.go b/worker/backup_oss.go index c7d4b09d740..1472b902809 100644 --- a/worker/backup_oss.go +++ b/worker/backup_oss.go @@ -34,7 +34,7 @@ func (w *grpcWorker) Backup( return nil, x.ErrNotSupported } -func ProcessBackupRequest(ctx context.Context, req *pb.BackupRequest, forceFull bool) error { +func ProcessBackupRequest(ctx context.Context, req *pb.BackupRequest) error { glog.Warningf("Backup failed: %v", x.ErrNotSupported) return x.ErrNotSupported } diff --git a/worker/export.go b/worker/export.go index a107dd90b40..7d5c96629ff 100644 --- a/worker/export.go +++ b/worker/export.go @@ -337,7 +337,7 @@ func toSchema(attr string, update *pb.SchemaUpdate) *bpb.KV { func toType(attr string, update pb.TypeUpdate) *bpb.KV { var buf bytes.Buffer ns, attr := x.ParseNamespaceAttr(attr) - x.Check2(buf.WriteString(fmt.Sprintf("[0x%x] type <%s> {\n", ns, attr))) + x.Check2(buf.WriteString(fmt.Sprintf("[%#x] type <%s> {\n", ns, attr))) for _, field := range update.Fields { x.Check2(buf.WriteString(fieldToString(field))) } @@ -553,6 +553,7 @@ func NewExportStorage(in *pb.ExportRequest, backupName string) (ExportStorage, e // export creates a export of data by exporting it as an RDF gzip. func export(ctx context.Context, in *pb.ExportRequest) (ExportedFiles, error) { + if in.GroupId != groups().groupId() { return nil, errors.Errorf("Export request group mismatch. Mine: %d. Requested: %d", groups().groupId(), in.GroupId) diff --git a/worker/predicate_move.go b/worker/predicate_move.go index b5437d43e72..38caaa54ebf 100644 --- a/worker/predicate_move.go +++ b/worker/predicate_move.go @@ -71,7 +71,7 @@ func batchAndProposeKeyValues(ctx context.Context, kvs chan *pb.KVS) error { var pk x.ParsedKey for kvPayload := range kvs { - buf := z.BufferFrom(kvPayload.GetData()) + buf := z.NewBufferSlice(kvPayload.GetData()) err := buf.SliceIterate(func(s []byte) error { kv := &bpb.KV{} x.Check(kv.Unmarshal(s)) @@ -164,7 +164,7 @@ func (w *grpcWorker) ReceivePredicate(stream pb.Worker_ReceivePredicateServer) e } glog.V(2).Infof("Received batch of size: %s\n", humanize.IBytes(uint64(len(kvBuf.Data)))) - buf := z.BufferFrom(kvBuf.Data) + buf := z.NewBufferSlice(kvBuf.Data) buf.SliceIterate(func(_ []byte) error { count++ return nil diff --git a/worker/queue.go b/worker/queue.go new file mode 100644 index 00000000000..4e356accb55 --- /dev/null +++ b/worker/queue.go @@ -0,0 +1,411 @@ +/* + * Copyright 2021 Dgraph Labs, Inc. and Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package worker + +import ( + "context" + "fmt" + "math" + "math/rand" + "path/filepath" + "reflect" + "sync" + "time" + + "github.com/dgraph-io/dgraph/conn" + "github.com/dgraph-io/dgraph/protos/pb" + "github.com/dgraph-io/dgraph/raftwal" + "github.com/dgraph-io/dgraph/x" + "github.com/dgraph-io/ristretto/z" + "github.com/golang/glog" + "github.com/pkg/errors" +) + +// TaskStatusOverNetwork fetches the status of a task over the network. Alphas only know about the +// tasks created by them, but this function would fetch the task from the correct Alpha. +func TaskStatusOverNetwork(ctx context.Context, req *pb.TaskStatusRequest, +) (*pb.TaskStatusResponse, error) { + // Extract Raft ID from Task ID. + taskId := req.GetTaskId() + if taskId == 0 { + return nil, fmt.Errorf("invalid task ID: %#x", taskId) + } + raftId := taskId >> 32 + + // Skip the network call if the required Alpha is me. + myRaftId := State.WALstore.Uint(raftwal.RaftId) + if raftId == myRaftId { + worker := (*grpcWorker)(nil) + return worker.TaskStatus(ctx, req) + } + + // Find the Alpha with the required Raft ID. + var addr string + for _, group := range groups().state.GetGroups() { + for _, member := range group.GetMembers() { + if member.GetId() == raftId { + addr = member.GetAddr() + } + } + } + if addr == "" { + return nil, fmt.Errorf("the Alpha that served that task is not available") + } + + // Send the request to the Alpha. + pool, err := conn.GetPools().Get(addr) + if err != nil { + return nil, errors.Wrapf(err, "unable to reach the Alpha that served that task") + } + client := pb.NewWorkerClient(pool.Get()) + return client.TaskStatus(ctx, req) +} + +// TaskStatus retrieves metadata for a given task ID. +func (*grpcWorker) TaskStatus(ctx context.Context, req *pb.TaskStatusRequest, +) (*pb.TaskStatusResponse, error) { + taskId := req.GetTaskId() + meta, err := Tasks.get(taskId) + if err != nil { + return nil, err + } + + resp := &pb.TaskStatusResponse{TaskMeta: meta.uint64()} + return resp, nil +} + +var ( + // Tasks is a global persistent task queue. + // Do not use this before calling InitTasks. + Tasks *tasks +) + +// InitTasks initializes the global Tasks variable. +func InitTasks() { + path := filepath.Join(x.WorkerConfig.TmpDir, "tasks.buf") + log, err := z.NewTreePersistent(path) + x.Check(err) + + // #nosec G404: weak RNG + Tasks = &tasks{ + queue: make(chan taskRequest, 16), + log: log, + logMu: new(sync.Mutex), + rng: rand.New(rand.NewSource(time.Now().UnixNano())), + } + + // Mark all pending tasks as failed. + Tasks.logMu.Lock() + Tasks.log.IterateKV(func(id, val uint64) uint64 { + meta := TaskMeta(val) + if status := meta.Status(); status == TaskStatusQueued || status == TaskStatusRunning { + return uint64(newTaskMeta(meta.Kind(), TaskStatusFailed)) + } + return 0 + }) + Tasks.logMu.Unlock() + + // Start the task runner. + go Tasks.worker() +} + +// tasks is a persistent task queue. +type tasks struct { + // queue stores the full Protobuf request. + queue chan taskRequest + // log stores the timestamp, TaskKind, and TaskStatus. + log *z.Tree + logMu *sync.Mutex + + rng *rand.Rand +} + +// Enqueue adds a new task to the queue, waits for 3 seconds, and returns any errors that +// may have happened in that span of time. The request must be of type: +// - *pb.BackupRequest +// - *pb.ExportRequest +func (t *tasks) Enqueue(req interface{}) (uint64, error) { + if t == nil { + return 0, fmt.Errorf("task queue hasn't been initialized yet") + } + + id, err := t.enqueue(req) + if err != nil { + return 0, err + } + + // Wait for upto 3 seconds to check for errors. + for i := 0; i < 3; i++ { + time.Sleep(time.Second) + + t.logMu.Lock() + meta := TaskMeta(t.log.Get(id)) + t.logMu.Unlock() + + // Early return + switch meta.Status() { + case TaskStatusFailed: + return 0, fmt.Errorf("task failed") + case TaskStatusSuccess: + return id, nil + } + } + + return id, nil +} + +// enqueue adds a new task to the queue. This must be of type: +// - *pb.BackupRequest +// - *pb.ExportRequest +func (t *tasks) enqueue(req interface{}) (uint64, error) { + var kind TaskKind + switch req.(type) { + case *pb.BackupRequest: + kind = TaskKindBackup + case *pb.ExportRequest: + kind = TaskKindExport + default: + err := fmt.Errorf("invalid TaskKind: %d", kind) + panic(err) + } + + t.logMu.Lock() + defer t.logMu.Unlock() + + task := taskRequest{ + id: t.newId(), + req: req, + } + select { + // t.logMu must be acquired before pushing to t.queue, otherwise the worker might start the + // task, and won't be able to find it in t.log. + case t.queue <- task: + t.log.Set(task.id, newTaskMeta(kind, TaskStatusQueued).uint64()) + return task.id, nil + default: + return 0, fmt.Errorf("too many pending tasks, please try again later") + } +} + +// get retrieves metadata for a given task ID. +func (t *tasks) get(id uint64) (TaskMeta, error) { + if t == nil { + return 0, fmt.Errorf("task queue hasn't been initialized yet") + } + + if id == 0 || id == math.MaxUint64 { + return 0, fmt.Errorf("task ID is invalid: %d", id) + } + t.logMu.Lock() + defer t.logMu.Unlock() + meta := TaskMeta(t.log.Get(id)) + if meta == 0 { + return 0, fmt.Errorf("task does not exist or has expired") + } + return meta, nil +} + +// worker loops forever, running queued tasks one at a time. Any returned errors are logged. +func (t *tasks) worker() { + shouldCleanup := time.NewTicker(time.Hour) + defer shouldCleanup.Stop() + for { + // If the server is shutting down, return immediately. Else, fetch a task from the queue. + var task taskRequest + select { + case <-x.ServerCloser.HasBeenClosed(): + t.log.Close() + return + case <-shouldCleanup.C: + t.cleanup() + case task = <-t.queue: + if err := t.run(task); err != nil { + glog.Errorf("task %#x: failed: %s", task.id, err) + } else { + glog.Infof("task %#x: completed successfully", task.id) + } + } + } +} + +func (t *tasks) run(task taskRequest) error { + // Fetch the task from the log. If the task isn't found, this means it has expired (older than + // taskTtl). + t.logMu.Lock() + meta := TaskMeta(t.log.Get(task.id)) + t.logMu.Unlock() + if meta == 0 { + return fmt.Errorf("is expired, skipping") + } + + // Only proceed if the task is still queued. It's possible that the task got canceled before we + // were able to run it. + if status := meta.Status(); status != TaskStatusQueued { + return fmt.Errorf("status is set to %s, skipping", status) + } + + // Change the task status to Running. + t.logMu.Lock() + t.log.Set(task.id, newTaskMeta(meta.Kind(), TaskStatusRunning).uint64()) + t.logMu.Unlock() + + // Run the task. + var status TaskStatus + err := task.run() + if err != nil { + status = TaskStatusFailed + } else { + status = TaskStatusSuccess + } + + // Change the task status to Success / Failed. + t.logMu.Lock() + t.log.Set(task.id, newTaskMeta(meta.Kind(), status).uint64()) + t.logMu.Unlock() + + // Return the error from the task. + return err +} + +// cleanup deletes all expired tasks. +func (t *tasks) cleanup() { + const taskTtl = 7 * 24 * time.Hour // 1 week + minTs := time.Now().UTC().Add(-taskTtl).Unix() + minMeta := uint64(minTs) << 32 + + t.logMu.Lock() + defer t.logMu.Unlock() + t.log.DeleteBelow(minMeta) +} + +// newId generates a random unique task ID. logMu must be acquired before calling this function. +// +// The format of this is: +// 32 bits: raft ID +// 32 bits: random number +func (t *tasks) newId() uint64 { + myRaftId := State.WALstore.Uint(raftwal.RaftId) + for { + id := myRaftId<<32 | uint64(t.rng.Intn(math.MaxUint32)) + // z.Tree cannot store 0 or math.MaxUint64. Check that id is unique. + if id != 0 && id != math.MaxUint64 && t.log.Get(id) == 0 { + return id + } + } +} + +type taskRequest struct { + id uint64 + req interface{} // *pb.BackupRequest, *pb.ExportRequest +} + +// run starts a task and blocks till it completes. +func (t *taskRequest) run() error { + switch req := t.req.(type) { + case *pb.BackupRequest: + if err := ProcessBackupRequest(context.Background(), req); err != nil { + return err + } + case *pb.ExportRequest: + files, err := ExportOverNetwork(context.Background(), req) + if err != nil { + return err + } + glog.Infof("task %#x: exported files: %v", t.id, files) + default: + glog.Errorf( + "task %#x: received request of unknown type (%T)", t.id, reflect.TypeOf(t.req)) + } + return nil +} + +// TaskMeta stores a timestamp, a TaskKind and a Status. +// +// The format of this is: +// 32 bits: UNIX timestamp (overflows on 2106-02-07) +// 16 bits: TaskKind +// 16 bits: TaskStatus +type TaskMeta uint64 + +func newTaskMeta(kind TaskKind, status TaskStatus) TaskMeta { + now := time.Now().UTC().Unix() + return TaskMeta(now)<<32 | TaskMeta(kind)<<16 | TaskMeta(status) +} + +// Timestamp returns the timestamp of the last status change of the task. +func (t TaskMeta) Timestamp() time.Time { + return time.Unix(int64(t>>32), 0) +} + +// Kind returns the type of the task. +func (t TaskMeta) Kind() TaskKind { + return TaskKind((t >> 16) & math.MaxUint16) +} + +// Status returns the current status of the task. +func (t TaskMeta) Status() TaskStatus { + return TaskStatus(t & math.MaxUint16) +} + +// uint64 represents the TaskMeta as a uint64. +func (t TaskMeta) uint64() uint64 { + return uint64(t) +} + +const ( + // Reserve the zero value for errors. + TaskKindBackup TaskKind = iota + 1 + TaskKindExport +) + +type TaskKind uint64 + +func (k TaskKind) String() string { + switch k { + case TaskKindBackup: + return "Backup" + case TaskKindExport: + return "Export" + default: + return "Unknown" + } +} + +const ( + // Reserve the zero value for errors. + TaskStatusQueued TaskStatus = iota + 1 + TaskStatusRunning + TaskStatusFailed + TaskStatusSuccess +) + +type TaskStatus uint64 + +func (status TaskStatus) String() string { + switch status { + case TaskStatusQueued: + return "Queued" + case TaskStatusRunning: + return "Running" + case TaskStatusFailed: + return "Failed" + case TaskStatusSuccess: + return "Success" + default: + return "Unknown" + } +} diff --git a/worker/restore_map.go b/worker/restore_map.go index d98262b5d83..8fa0ba60ce5 100644 --- a/worker/restore_map.go +++ b/worker/restore_map.go @@ -229,9 +229,9 @@ func (m *mapper) writeToDisk(buf *z.Buffer) error { } func newBuffer() *z.Buffer { - buf, err := z.NewBufferWithDir(mapFileSz, 2*mapFileSz, z.UseMmap, "", "Restore.Buffer") + buf, err := z.NewBufferTmp("", mapFileSz) x.Check(err) - return buf + return buf.WithMaxSize(2 * mapFileSz) } func (mw *mapper) sendForWriting() error { diff --git a/worker/restore_reduce.go b/worker/restore_reduce.go index 43e5689ea1d..db44570c030 100644 --- a/worker/restore_reduce.go +++ b/worker/restore_reduce.go @@ -120,10 +120,7 @@ func newMapIterator(filename string) (*pb.MapHeader, *mapIterator) { func getBuf() *z.Buffer { path := filepath.Join(x.WorkerConfig.TmpDir, "buffer") x.Check(os.MkdirAll(path, 0750)) - cbuf, err := z.NewBufferWithDir(64<<20, 64<<30, z.UseCalloc, path, "Restore.GetBuf") - x.Check(err) - cbuf.AutoMmapAfter(1 << 30) - return cbuf + return z.NewBuffer(64<<20, "Restore.GetBuf").WithAutoMmap(1<<30, path).WithMaxSize(64 << 30) } type reducer struct { diff --git a/worker/snapshot.go b/worker/snapshot.go index e7fde2339de..1b6e77af156 100644 --- a/worker/snapshot.go +++ b/worker/snapshot.go @@ -103,7 +103,7 @@ func (n *node) populateSnapshot(snap pb.Snapshot, pl *conn.Pool) error { glog.V(1).Infof("Received batch of size: %s. Total so far: %s\n", humanize.IBytes(uint64(len(kvs.Data))), humanize.IBytes(uint64(size))) - buf := z.BufferFrom(kvs.Data) + buf := z.NewBufferSlice(kvs.Data) if err := writer.Write(buf); err != nil { return err } diff --git a/worker/worker.go b/worker/worker.go index 2be3103d95d..c8db45f3e3e 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -80,6 +80,9 @@ type grpcWorker struct { sync.Mutex } +// grpcWorker implements pb.WorkerServer. +var _ pb.WorkerServer = (*grpcWorker)(nil) + func (w *grpcWorker) Subscribe( req *pb.SubscriptionRequest, stream pb.Worker_SubscribeServer) error { // Subscribe on given prefixes. diff --git a/worker/worker_test.go b/worker/worker_test.go index 207d11ad9dd..13a7c4ac000 100644 --- a/worker/worker_test.go +++ b/worker/worker_test.go @@ -141,13 +141,13 @@ func populateGraph(t *testing.T) { func populateClusterGraph(t *testing.T, dg *dgo.Dgraph) { data1 := [][]int{{10, 23}, {11, 23}, {12, 23}, {12, 25}, {12, 26}, {10, 31}, {12, 31}} for _, pair := range data1 { - rdf := fmt.Sprintf(`<0x%x> <0x%x> .`, pair[0], pair[1]) + rdf := fmt.Sprintf(`<%#x> <%#x> .`, pair[0], pair[1]) setClusterEdge(t, dg, rdf) } data2 := map[int]string{12: "photon", 10: "photon"} for key, val := range data2 { - rdf := fmt.Sprintf(`<0x%x> %q .`, key, val) + rdf := fmt.Sprintf(`<%#x> %q .`, key, val) setClusterEdge(t, dg, rdf) } } @@ -211,7 +211,7 @@ func runQuery(dg *dgo.Dgraph, attr string, uids []uint64, srcFunc []string) (*ap if uids != nil { var uidv []string for _, uid := range uids { - uidv = append(uidv, fmt.Sprintf("0x%x", uid)) + uidv = append(uidv, fmt.Sprintf("%#x", uid)) } query = fmt.Sprintf(` { @@ -258,8 +258,8 @@ func TestProcessTaskIndexMLayer(t *testing.T) { // Now try changing 12's friend value from "photon" to "notphotonExtra" to // "notphoton". - setClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "notphotonExtra")) - setClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "notphoton")) + setClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "notphotonExtra")) + setClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "notphoton")) // Issue a similar query. resp, err = runQuery(dg, "friend", nil, @@ -275,12 +275,12 @@ func TestProcessTaskIndexMLayer(t *testing.T) { ) // Try redundant deletes. - delClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 10, "photon")) - delClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 10, "photon")) + delClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 10, "photon")) + delClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 10, "photon")) // Delete followed by set. - delClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "notphoton")) - setClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "ignored")) + delClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "notphoton")) + setClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "ignored")) // Issue a similar query. resp, err = runQuery(dg, "friend", nil, @@ -324,8 +324,8 @@ func TestProcessTaskIndex(t *testing.T) { // Now try changing 12's friend value from "photon" to "notphotonExtra" to // "notphoton". - setClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "notphotonExtra")) - setClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "notphoton")) + setClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "notphotonExtra")) + setClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "notphoton")) // Issue a similar query. resp, err = runQuery(dg, "friend", nil, @@ -341,12 +341,12 @@ func TestProcessTaskIndex(t *testing.T) { ) // Try redundant deletes. - delClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 10, "photon")) - delClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 10, "photon")) + delClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 10, "photon")) + delClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 10, "photon")) // Delete followed by set. - delClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "notphoton")) - setClusterEdge(t, dg, fmt.Sprintf("<0x%x> %q .", 12, "ignored")) + delClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "notphoton")) + setClusterEdge(t, dg, fmt.Sprintf("<%#x> %q .", 12, "ignored")) // Issue a similar query. resp, err = runQuery(dg, "friend", nil, diff --git a/xidmap/trie.go b/xidmap/trie.go index 3df8b132b13..d2b3e4d9eb3 100644 --- a/xidmap/trie.go +++ b/xidmap/trie.go @@ -20,7 +20,6 @@ import ( "math" "unsafe" - "github.com/dgraph-io/dgraph/x" "github.com/dgraph-io/ristretto/z" ) @@ -34,8 +33,7 @@ type Trie struct { // NewTrie would return back a Trie backed by the provided Arena. Trie would assume ownership of the // Arena. Release must be called at the end to release Arena's resources. func NewTrie() *Trie { - buf, err := z.NewBufferWith(32<<20, math.MaxUint32, z.UseMmap, "Trie") - x.Check(err) + buf := z.NewBuffer(32<<20, "Trie").WithMaxSize(math.MaxUint32) // Add additional 8 bytes at the start, because offset=0 is used for checking non-existing node. // Therefore we can't keep root at 0 offset. ro := buf.AllocateOffset(nodeSz + 8) diff --git a/xidmap/xidmap.go b/xidmap/xidmap.go index d1bc428e276..a7b59b075d8 100644 --- a/xidmap/xidmap.go +++ b/xidmap/xidmap.go @@ -103,7 +103,7 @@ func New(opts XidMapOptions) *XidMap { } for i := range xm.shards { xm.shards[i] = &shard{ - tree: z.NewTree(), + tree: z.NewTree("XidMap"), } } @@ -331,6 +331,9 @@ func (m *XidMap) Flush() error { // even during reduce phase. If bulk loader is running on large dataset, this occupies lot of // memory and causing OOM sometimes. Making shards explicitly nil in this method fixes this. // TODO: find why xidmap is not getting GCed without below line. + for _, shards := range m.shards { + shards.tree.Close() + } m.shards = nil if m.writer == nil { return nil