From b98b431e8bea611e7dd0835bad53823c795f0414 Mon Sep 17 00:00:00 2001 From: Spencer Kimball Date: Mon, 30 Oct 2017 16:43:10 -0400 Subject: [PATCH] sql: add new system table for locality locations Adds a new table, `system.locations`, which maps a string locality (i.e. "city=New York City") to geographic coordinates, specified as a latitude, longitude decimal pair, specified in degrees. A new admin API call returns the contents of the table, for use from the admin UI. Fixes #19532 Release note (ui): A system table to allow operators to designate geographic coordinates for any locality. For use with frontend cluster visualization. --- pkg/cli/cli_test.go | 10 +- pkg/config/system_test.go | 1 + pkg/keys/constants.go | 1 + pkg/server/admin.go | 45 + pkg/server/admin_test.go | 40 + pkg/server/serverpb/admin.pb.go | 839 ++++++++++++++---- pkg/server/serverpb/admin.pb.gw.go | 42 + pkg/server/serverpb/admin.proto | 23 + pkg/sql/logictest/testdata/logic_test/explain | 10 +- .../logictest/testdata/logic_test/grant_table | 5 + .../testdata/logic_test/information_schema | 12 + .../logictest/testdata/logic_test/pg_catalog | 3 + .../logictest/testdata/logic_test/show_source | 1 + pkg/sql/logictest/testdata/logic_test/system | 10 + pkg/sql/pgwire/pgwire_test.go | 2 +- pkg/sql/sqlbase/system.go | 56 ++ pkg/sql/tests/system_table_test.go | 1 + pkg/sqlmigrations/migrations.go | 10 + 18 files changed, 917 insertions(+), 194 deletions(-) diff --git a/pkg/cli/cli_test.go b/pkg/cli/cli_test.go index 50fd353545ef..d70f50a31655 100644 --- a/pkg/cli/cli_test.go +++ b/pkg/cli/cli_test.go @@ -396,7 +396,7 @@ func Example_ranges() { // 0: node-id=1 store-id=1 ///System/"tse"-"ranges3" [6] // 0: node-id=1 store-id=1 - //"ranges3"-/Table/SystemConfigSpan/Start [18] + //"ranges3"-/Table/SystemConfigSpan/Start [19] // 0: node-id=1 store-id=1 ///Table/SystemConfigSpan/Start-/Table/11 [7] // 0: node-id=1 store-id=1 @@ -418,9 +418,11 @@ func Example_ranges() { // 0: node-id=1 store-id=1 ///Table/19-/Table/20 [16] // 0: node-id=1 store-id=1 - ///Table/20-/Max [17] + ///Table/20-/Table/21 [17] // 0: node-id=1 store-id=1 - //18 result(s) + ///Table/21-/Max [18] + // 0: node-id=1 store-id=1 + //19 result(s) } @@ -1862,11 +1864,13 @@ writing ` + os.DevNull + ` debug/nodes/1/ranges/15 debug/nodes/1/ranges/16 debug/nodes/1/ranges/17 + debug/nodes/1/ranges/18 debug/schema/system@details debug/schema/system/descriptor debug/schema/system/eventlog debug/schema/system/jobs debug/schema/system/lease + debug/schema/system/locations debug/schema/system/namespace debug/schema/system/rangelog debug/schema/system/settings diff --git a/pkg/config/system_test.go b/pkg/config/system_test.go index 6f38f4e2a598..3dde5a1187f4 100644 --- a/pkg/config/system_test.go +++ b/pkg/config/system_test.go @@ -392,6 +392,7 @@ func TestGetZoneConfigForKey(t *testing.T) { {tkey(keys.ZonesTableID), keys.SystemDatabaseID}, {tkey(keys.LeaseTableID), keys.SystemDatabaseID}, {tkey(keys.JobsTableID), keys.SystemDatabaseID}, + {tkey(keys.LocationsTableID), keys.SystemDatabaseID}, {tkey(keys.MaxReservedDescID + 1), keys.MaxReservedDescID + 1}, {tkey(keys.MaxReservedDescID + 23), keys.MaxReservedDescID + 23}, {roachpb.RKeyMax, keys.RootNamespaceID}, diff --git a/pkg/keys/constants.go b/pkg/keys/constants.go index 224b6689172d..f14d4cee63af 100644 --- a/pkg/keys/constants.go +++ b/pkg/keys/constants.go @@ -315,4 +315,5 @@ const ( TimeseriesRangesID = 18 WebSessionsTableID = 19 TableStatisticsTableID = 20 + LocationsTableID = 21 ) diff --git a/pkg/server/admin.go b/pkg/server/admin.go index fdb39dafca22..e4f279fe6169 100644 --- a/pkg/server/admin.go +++ b/pkg/server/admin.go @@ -31,6 +31,7 @@ import ( "encoding/json" + "github.com/cockroachdb/apd" "github.com/cockroachdb/cockroach/pkg/base" "github.com/cockroachdb/cockroach/pkg/config" "github.com/cockroachdb/cockroach/pkg/internal/client" @@ -1088,6 +1089,43 @@ func (s *adminServer) Jobs( return &resp, nil } +func (s *adminServer) Locations( + ctx context.Context, req *serverpb.LocationsRequest, +) (*serverpb.LocationsResponse, error) { + args := sql.SessionArgs{User: s.getUser(req)} + ctx, session := s.NewContextAndSessionForRPC(ctx, args) + defer session.Finish(s.server.sqlExecutor) + + q := makeSQLQuery() + q.Append(`SELECT "localityKey", "localityValue", latitude, longitude FROM system.locations`) + r, err := s.server.sqlExecutor.ExecuteStatementsBuffered(session, q.String(), nil, 1) + if err != nil { + return nil, s.serverError(err) + } + defer r.Close(ctx) + + scanner := makeResultScanner(r.ResultList[0].Columns) + resp := serverpb.LocationsResponse{ + Locations: make([]serverpb.LocationsResponse_Location, r.ResultList[0].Rows.Len()), + } + for i := 0; i < len(resp.Locations); i++ { + loc := &resp.Locations[i] + lat, lon := new(apd.Decimal), new(apd.Decimal) + if err := scanner.ScanAll( + r.ResultList[0].Rows.At(i), &loc.LocalityKey, &loc.LocalityValue, lat, lon); err != nil { + return nil, s.serverError(err) + } + if loc.Latitude, err = lat.Float64(); err != nil { + return nil, s.serverError(err) + } + if loc.Longitude, err = lon.Float64(); err != nil { + return nil, s.serverError(err) + } + } + + return &resp, nil +} + // QueryPlan returns a JSON representation of a distsql physical query // plan. func (s *adminServer) QueryPlan( @@ -1440,6 +1478,13 @@ func (rs resultScanner) ScanIndex(row tree.Datums, index int, dst interface{}) e // Yes, this copies, but this probably isn't in the critical path. *d = []byte(*s) + case *apd.Decimal: + s, ok := src.(*tree.DDecimal) + if !ok { + return errors.Errorf("source type assertion failed") + } + *d = s.Decimal + default: return errors.Errorf("unimplemented type for scanCol: %T", dst) } diff --git a/pkg/server/admin_test.go b/pkg/server/admin_test.go index f99c75240fa4..f33855ba99d8 100644 --- a/pkg/server/admin_test.go +++ b/pkg/server/admin_test.go @@ -1182,6 +1182,46 @@ func TestAdminAPIJobs(t *testing.T) { } } +func TestAdminAPILocations(t *testing.T) { + defer leaktest.AfterTest(t)() + + s, conn, _ := serverutils.StartServer(t, base.TestServerArgs{}) + defer s.Stopper().Stop(context.TODO()) + sqlDB := sqlutils.MakeSQLRunner(conn) + + testLocations := []struct { + localityKey string + localityValue string + latitude float64 + longitude float64 + }{ + {"city", "Des Moines", 41.60054, -93.60911}, + {"city", "New York City", 40.71427, -74.00597}, + {"city", "Seattle", 47.60621, -122.33207}, + } + for _, loc := range testLocations { + sqlDB.Exec(t, + `INSERT INTO system.locations ("localityKey", "localityValue", latitude, longitude) VALUES ($1, $2, $3, $4)`, + loc.localityKey, loc.localityValue, loc.latitude, loc.longitude, + ) + } + var res serverpb.LocationsResponse + if err := getAdminJSONProto(s, "locations", &res); err != nil { + t.Fatal(err) + } + for i, loc := range testLocations { + expLoc := serverpb.LocationsResponse_Location{ + LocalityKey: loc.localityKey, + LocalityValue: loc.localityValue, + Latitude: loc.latitude, + Longitude: loc.longitude, + } + if !reflect.DeepEqual(res.Locations[i], expLoc) { + t.Errorf("%d: expected location %v, but got %v", i, expLoc, res.Locations[i]) + } + } +} + func TestAdminAPIQueryPlan(t *testing.T) { defer leaktest.AfterTest(t)() diff --git a/pkg/server/serverpb/admin.pb.go b/pkg/server/serverpb/admin.pb.go index ca19bf69ca1c..6efbdcc336ad 100644 --- a/pkg/server/serverpb/admin.pb.go +++ b/pkg/server/serverpb/admin.pb.go @@ -42,6 +42,8 @@ LivenessResponse JobsRequest JobsResponse + LocationsRequest + LocationsResponse RangeLogRequest RangeLogResponse QueryPlanRequest @@ -783,6 +785,39 @@ func (m *JobsResponse_Job) String() string { return proto.CompactText func (*JobsResponse_Job) ProtoMessage() {} func (*JobsResponse_Job) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{30, 0} } +// LocationsRequest requests system locality location information. +type LocationsRequest struct { +} + +func (m *LocationsRequest) Reset() { *m = LocationsRequest{} } +func (m *LocationsRequest) String() string { return proto.CompactTextString(m) } +func (*LocationsRequest) ProtoMessage() {} +func (*LocationsRequest) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{31} } + +// JobsResponse contains the job record for each matching job. +type LocationsResponse struct { + Locations []LocationsResponse_Location `protobuf:"bytes,1,rep,name=locations" json:"locations"` +} + +func (m *LocationsResponse) Reset() { *m = LocationsResponse{} } +func (m *LocationsResponse) String() string { return proto.CompactTextString(m) } +func (*LocationsResponse) ProtoMessage() {} +func (*LocationsResponse) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{32} } + +type LocationsResponse_Location struct { + LocalityKey string `protobuf:"bytes,1,opt,name=locality_key,json=localityKey,proto3" json:"locality_key,omitempty"` + LocalityValue string `protobuf:"bytes,2,opt,name=locality_value,json=localityValue,proto3" json:"locality_value,omitempty"` + Latitude float64 `protobuf:"fixed64,3,opt,name=latitude,proto3" json:"latitude,omitempty"` + Longitude float64 `protobuf:"fixed64,4,opt,name=longitude,proto3" json:"longitude,omitempty"` +} + +func (m *LocationsResponse_Location) Reset() { *m = LocationsResponse_Location{} } +func (m *LocationsResponse_Location) String() string { return proto.CompactTextString(m) } +func (*LocationsResponse_Location) ProtoMessage() {} +func (*LocationsResponse_Location) Descriptor() ([]byte, []int) { + return fileDescriptorAdmin, []int{32, 0} +} + // RangeLogRequest request the history of a range from the range log. type RangeLogRequest struct { // TODO(tamird): use [(gogoproto.customname) = "RangeID"] below. Need to @@ -799,7 +834,7 @@ type RangeLogRequest struct { func (m *RangeLogRequest) Reset() { *m = RangeLogRequest{} } func (m *RangeLogRequest) String() string { return proto.CompactTextString(m) } func (*RangeLogRequest) ProtoMessage() {} -func (*RangeLogRequest) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{31} } +func (*RangeLogRequest) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{33} } // RangeLogResponse contains a list of entries from the range log table. type RangeLogResponse struct { @@ -809,7 +844,7 @@ type RangeLogResponse struct { func (m *RangeLogResponse) Reset() { *m = RangeLogResponse{} } func (m *RangeLogResponse) String() string { return proto.CompactTextString(m) } func (*RangeLogResponse) ProtoMessage() {} -func (*RangeLogResponse) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{32} } +func (*RangeLogResponse) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{34} } // To avoid porting the pretty printing of keys and descriptors to // javascript, they will be precomputed on the serverside. @@ -826,7 +861,7 @@ func (m *RangeLogResponse_PrettyInfo) Reset() { *m = RangeLogResponse_Pr func (m *RangeLogResponse_PrettyInfo) String() string { return proto.CompactTextString(m) } func (*RangeLogResponse_PrettyInfo) ProtoMessage() {} func (*RangeLogResponse_PrettyInfo) Descriptor() ([]byte, []int) { - return fileDescriptorAdmin, []int{32, 0} + return fileDescriptorAdmin, []int{34, 0} } type RangeLogResponse_Event struct { @@ -837,7 +872,7 @@ type RangeLogResponse_Event struct { func (m *RangeLogResponse_Event) Reset() { *m = RangeLogResponse_Event{} } func (m *RangeLogResponse_Event) String() string { return proto.CompactTextString(m) } func (*RangeLogResponse_Event) ProtoMessage() {} -func (*RangeLogResponse_Event) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{32, 1} } +func (*RangeLogResponse_Event) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{34, 1} } // QueryPlanRequest requests the query plans for a SQL string. type QueryPlanRequest struct { @@ -848,7 +883,7 @@ type QueryPlanRequest struct { func (m *QueryPlanRequest) Reset() { *m = QueryPlanRequest{} } func (m *QueryPlanRequest) String() string { return proto.CompactTextString(m) } func (*QueryPlanRequest) ProtoMessage() {} -func (*QueryPlanRequest) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{33} } +func (*QueryPlanRequest) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{35} } // QueryPlanResponse contains the query plans for a SQL string (currently only // the distsql physical query plan). @@ -859,7 +894,7 @@ type QueryPlanResponse struct { func (m *QueryPlanResponse) Reset() { *m = QueryPlanResponse{} } func (m *QueryPlanResponse) String() string { return proto.CompactTextString(m) } func (*QueryPlanResponse) ProtoMessage() {} -func (*QueryPlanResponse) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{34} } +func (*QueryPlanResponse) Descriptor() ([]byte, []int) { return fileDescriptorAdmin, []int{36} } func init() { proto.RegisterType((*DatabasesRequest)(nil), "cockroach.server.serverpb.DatabasesRequest") @@ -904,6 +939,9 @@ func init() { proto.RegisterType((*JobsRequest)(nil), "cockroach.server.serverpb.JobsRequest") proto.RegisterType((*JobsResponse)(nil), "cockroach.server.serverpb.JobsResponse") proto.RegisterType((*JobsResponse_Job)(nil), "cockroach.server.serverpb.JobsResponse.Job") + proto.RegisterType((*LocationsRequest)(nil), "cockroach.server.serverpb.LocationsRequest") + proto.RegisterType((*LocationsResponse)(nil), "cockroach.server.serverpb.LocationsResponse") + proto.RegisterType((*LocationsResponse_Location)(nil), "cockroach.server.serverpb.LocationsResponse.Location") proto.RegisterType((*RangeLogRequest)(nil), "cockroach.server.serverpb.RangeLogRequest") proto.RegisterType((*RangeLogResponse)(nil), "cockroach.server.serverpb.RangeLogResponse") proto.RegisterType((*RangeLogResponse_PrettyInfo)(nil), "cockroach.server.serverpb.RangeLogResponse.PrettyInfo") @@ -979,6 +1017,8 @@ type AdminClient interface { Liveness(ctx context.Context, in *LivenessRequest, opts ...grpc.CallOption) (*LivenessResponse, error) // Jobs returns the job records for all jobs of the given status and type. Jobs(ctx context.Context, in *JobsRequest, opts ...grpc.CallOption) (*JobsResponse, error) + // Locations returns the locality location records. + Locations(ctx context.Context, in *LocationsRequest, opts ...grpc.CallOption) (*LocationsResponse, error) // QueryPlan returns the query plans for a SQL string. QueryPlan(ctx context.Context, in *QueryPlanRequest, opts ...grpc.CallOption) (*QueryPlanResponse, error) // Drain puts the node into the specified drain mode(s) and optionally @@ -1120,6 +1160,15 @@ func (c *adminClient) Jobs(ctx context.Context, in *JobsRequest, opts ...grpc.Ca return out, nil } +func (c *adminClient) Locations(ctx context.Context, in *LocationsRequest, opts ...grpc.CallOption) (*LocationsResponse, error) { + out := new(LocationsResponse) + err := grpc.Invoke(ctx, "/cockroach.server.serverpb.Admin/Locations", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *adminClient) QueryPlan(ctx context.Context, in *QueryPlanRequest, opts ...grpc.CallOption) (*QueryPlanResponse, error) { out := new(QueryPlanResponse) err := grpc.Invoke(ctx, "/cockroach.server.serverpb.Admin/QueryPlan", in, out, c.cc, opts...) @@ -1245,6 +1294,8 @@ type AdminServer interface { Liveness(context.Context, *LivenessRequest) (*LivenessResponse, error) // Jobs returns the job records for all jobs of the given status and type. Jobs(context.Context, *JobsRequest) (*JobsResponse, error) + // Locations returns the locality location records. + Locations(context.Context, *LocationsRequest) (*LocationsResponse, error) // QueryPlan returns the query plans for a SQL string. QueryPlan(context.Context, *QueryPlanRequest) (*QueryPlanResponse, error) // Drain puts the node into the specified drain mode(s) and optionally @@ -1499,6 +1550,24 @@ func _Admin_Jobs_Handler(srv interface{}, ctx context.Context, dec func(interfac return interceptor(ctx, in, info, handler) } +func _Admin_Locations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LocationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminServer).Locations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cockroach.server.serverpb.Admin/Locations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminServer).Locations(ctx, req.(*LocationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Admin_QueryPlan_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryPlanRequest) if err := dec(in); err != nil { @@ -1648,6 +1717,10 @@ var _Admin_serviceDesc = grpc.ServiceDesc{ MethodName: "Jobs", Handler: _Admin_Jobs_Handler, }, + { + MethodName: "Locations", + Handler: _Admin_Locations_Handler, + }, { MethodName: "QueryPlan", Handler: _Admin_QueryPlan_Handler, @@ -3316,6 +3389,96 @@ func (m *JobsResponse_Job) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *LocationsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LocationsRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *LocationsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LocationsResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Locations) > 0 { + for _, msg := range m.Locations { + dAtA[i] = 0xa + i++ + i = encodeVarintAdmin(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *LocationsResponse_Location) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *LocationsResponse_Location) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.LocalityKey) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintAdmin(dAtA, i, uint64(len(m.LocalityKey))) + i += copy(dAtA[i:], m.LocalityKey) + } + if len(m.LocalityValue) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintAdmin(dAtA, i, uint64(len(m.LocalityValue))) + i += copy(dAtA[i:], m.LocalityValue) + } + if m.Latitude != 0 { + dAtA[i] = 0x19 + i++ + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Latitude)))) + i += 8 + } + if m.Longitude != 0 { + dAtA[i] = 0x21 + i++ + binary.LittleEndian.PutUint64(dAtA[i:], uint64(math.Float64bits(float64(m.Longitude)))) + i += 8 + } + return i, nil +} + func (m *RangeLogRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -4183,6 +4346,44 @@ func (m *JobsResponse_Job) Size() (n int) { return n } +func (m *LocationsRequest) Size() (n int) { + var l int + _ = l + return n +} + +func (m *LocationsResponse) Size() (n int) { + var l int + _ = l + if len(m.Locations) > 0 { + for _, e := range m.Locations { + l = e.Size() + n += 1 + l + sovAdmin(uint64(l)) + } + } + return n +} + +func (m *LocationsResponse_Location) Size() (n int) { + var l int + _ = l + l = len(m.LocalityKey) + if l > 0 { + n += 1 + l + sovAdmin(uint64(l)) + } + l = len(m.LocalityValue) + if l > 0 { + n += 1 + l + sovAdmin(uint64(l)) + } + if m.Latitude != 0 { + n += 9 + } + if m.Longitude != 0 { + n += 9 + } + return n +} + func (m *RangeLogRequest) Size() (n int) { var l int _ = l @@ -9388,6 +9589,267 @@ func (m *JobsResponse_Job) Unmarshal(dAtA []byte) error { } return nil } +func (m *LocationsRequest) 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 ErrIntOverflowAdmin + } + 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: LocationsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LocationsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipAdmin(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthAdmin + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LocationsResponse) 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 ErrIntOverflowAdmin + } + 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: LocationsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LocationsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Locations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAdmin + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAdmin + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Locations = append(m.Locations, LocationsResponse_Location{}) + if err := m.Locations[len(m.Locations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAdmin(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthAdmin + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LocationsResponse_Location) 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 ErrIntOverflowAdmin + } + 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: Location: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Location: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalityKey", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAdmin + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAdmin + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LocalityKey = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalityValue", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAdmin + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAdmin + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LocalityValue = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Latitude", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.Latitude = float64(math.Float64frombits(v)) + case 4: + if wireType != 1 { + return fmt.Errorf("proto: wrong wireType = %d for field Longitude", wireType) + } + var v uint64 + if (iNdEx + 8) > l { + return io.ErrUnexpectedEOF + } + v = uint64(binary.LittleEndian.Uint64(dAtA[iNdEx:])) + iNdEx += 8 + m.Longitude = float64(math.Float64frombits(v)) + default: + iNdEx = preIndex + skippy, err := skipAdmin(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthAdmin + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *RangeLogRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -10157,184 +10619,191 @@ var ( func init() { proto.RegisterFile("server/serverpb/admin.proto", fileDescriptorAdmin) } var fileDescriptorAdmin = []byte{ - // 2855 bytes of a gzipped FileDescriptorProto + // 2969 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x39, 0xcd, 0x6f, 0x1b, 0xd7, - 0xf1, 0x5e, 0x7e, 0x73, 0x48, 0x4a, 0xe4, 0x93, 0x7e, 0x0a, 0x4d, 0xfb, 0x27, 0x2a, 0x6b, 0x34, - 0x56, 0x64, 0x87, 0x8c, 0x15, 0xc7, 0x4d, 0x1d, 0xf7, 0x20, 0x8a, 0x82, 0xcc, 0x44, 0x56, 0x92, - 0x95, 0xe4, 0xa0, 0x2e, 0x02, 0x76, 0xc9, 0x7d, 0xa2, 0xb6, 0x5a, 0xee, 0x52, 0xfb, 0x96, 0x72, - 0x94, 0x34, 0x45, 0x9b, 0xf6, 0xd0, 0xde, 0x02, 0xf4, 0xd0, 0x43, 0x81, 0x02, 0x2d, 0x0a, 0x14, - 0x68, 0x2f, 0xcd, 0xb1, 0xff, 0x41, 0xd0, 0x4b, 0x0b, 0xf4, 0xd2, 0x4b, 0xd5, 0x96, 0xe9, 0xa1, - 0xe8, 0x9f, 0xd0, 0x53, 0xf1, 0xbe, 0x96, 0x4b, 0x8a, 0x59, 0x93, 0x76, 0xd0, 0x83, 0xad, 0x7d, - 0xf3, 0x66, 0xe6, 0xcd, 0xcc, 0x9b, 0x37, 0x5f, 0x84, 0x2b, 0x04, 0xbb, 0xa7, 0xd8, 0xad, 0xf2, - 0x3f, 0xbd, 0x56, 0x55, 0x37, 0xba, 0xa6, 0x5d, 0xe9, 0xb9, 0x8e, 0xe7, 0xa0, 0xcb, 0x6d, 0xa7, - 0x7d, 0xec, 0x3a, 0x7a, 0xfb, 0xa8, 0xc2, 0xf7, 0x2b, 0x12, 0xad, 0x54, 0x68, 0x3b, 0xf6, 0xa1, - 0xd9, 0xa9, 0x7e, 0xe0, 0xd8, 0x98, 0x63, 0x97, 0x16, 0xc8, 0x89, 0x55, 0xfd, 0xb6, 0xd3, 0x22, - 0xec, 0x3f, 0x01, 0x54, 0x89, 0xe7, 0xb8, 0x7a, 0x07, 0x57, 0xb1, 0xdd, 0x31, 0x6d, 0xf9, 0xa7, - 0xd7, 0xaa, 0x76, 0x4f, 0xdb, 0x6d, 0x81, 0xb3, 0x24, 0x71, 0x2c, 0xf3, 0x14, 0xdb, 0x98, 0x48, - 0xda, 0x82, 0x0f, 0x77, 0x3a, 0x02, 0xb4, 0xd8, 0x71, 0x3a, 0x0e, 0xfb, 0xac, 0xd2, 0x2f, 0x01, - 0xbd, 0xda, 0x71, 0x9c, 0x8e, 0x85, 0xab, 0x7a, 0xcf, 0xac, 0xea, 0xb6, 0xed, 0x78, 0xba, 0x67, - 0x3a, 0xb6, 0x64, 0x53, 0x16, 0xbb, 0x6c, 0xd5, 0xea, 0x1f, 0x56, 0x3d, 0xb3, 0x8b, 0x89, 0xa7, - 0x77, 0x7b, 0x1c, 0x41, 0x45, 0x90, 0xaf, 0xeb, 0x9e, 0xde, 0xd2, 0x09, 0x26, 0x1a, 0x3e, 0xe9, - 0x63, 0xe2, 0xa9, 0xb7, 0xa0, 0x10, 0x80, 0x91, 0x9e, 0x63, 0x13, 0x8c, 0xae, 0x42, 0xda, 0x90, - 0xc0, 0xa2, 0xb2, 0x12, 0x5d, 0x4d, 0x6b, 0x43, 0x80, 0x7a, 0x1b, 0x96, 0x24, 0x49, 0x1d, 0x7b, - 0xba, 0x69, 0x49, 0x66, 0xa8, 0x04, 0x29, 0x89, 0x56, 0x54, 0x56, 0x94, 0xd5, 0xb4, 0xe6, 0xaf, - 0xd5, 0xdf, 0x44, 0xe1, 0xb9, 0x0b, 0x64, 0xe2, 0xbc, 0x87, 0x90, 0xe8, 0xb8, 0xba, 0xed, 0xf1, - 0xc3, 0x32, 0xeb, 0xaf, 0x55, 0xbe, 0xf0, 0x42, 0x2a, 0x5f, 0xc0, 0xa3, 0xb2, 0x4d, 0x19, 0xd4, - 0x62, 0x9f, 0x9d, 0x97, 0x2f, 0x69, 0x82, 0x1b, 0x2a, 0x43, 0xc6, 0xd3, 0x5b, 0x16, 0x6e, 0xda, - 0x7a, 0x17, 0x93, 0x62, 0x84, 0x69, 0x02, 0x0c, 0xb4, 0x4b, 0x21, 0xe8, 0x55, 0xc8, 0x19, 0x98, - 0xb4, 0x5d, 0xb3, 0xe7, 0x39, 0x6e, 0xd3, 0x34, 0x8a, 0xd1, 0x15, 0x65, 0x35, 0x5a, 0xcb, 0x0f, - 0xce, 0xcb, 0xd9, 0xba, 0xbf, 0xd1, 0xa8, 0x6b, 0xd9, 0x21, 0x5a, 0xc3, 0x40, 0x9b, 0x90, 0xa1, - 0xfe, 0xd0, 0xe4, 0xbe, 0x51, 0x8c, 0xad, 0x28, 0xab, 0x99, 0xf5, 0xab, 0x01, 0xa1, 0xf9, 0x46, - 0xe5, 0x91, 0x63, 0xe3, 0x4d, 0xf6, 0x29, 0x04, 0x83, 0x0f, 0x7c, 0x08, 0x7a, 0x0f, 0x0a, 0x01, - 0x26, 0x4d, 0x0b, 0x9f, 0x62, 0xab, 0x18, 0x5f, 0x51, 0x56, 0xe7, 0xd6, 0x6f, 0x85, 0xe8, 0x3f, - 0xe4, 0xd9, 0x77, 0xd9, 0xf5, 0xef, 0x50, 0x42, 0x6d, 0x7e, 0xc8, 0x99, 0x01, 0x4a, 0xaf, 0x43, - 0x9c, 0x99, 0x04, 0x21, 0x88, 0xf5, 0x09, 0x76, 0xc5, 0x85, 0xb0, 0x6f, 0xb4, 0x0c, 0xd0, 0x73, - 0xcd, 0x53, 0xd3, 0xc2, 0x9d, 0xa1, 0x5d, 0x86, 0x10, 0x75, 0x1b, 0x16, 0xf6, 0xa9, 0x95, 0xa6, - 0xbf, 0x5f, 0xb4, 0x08, 0x71, 0x66, 0xd8, 0x62, 0x84, 0x6d, 0xf0, 0x85, 0xfa, 0xbb, 0x24, 0x2c, - 0x8e, 0x72, 0x12, 0x57, 0xbe, 0x37, 0x76, 0xe5, 0xaf, 0x86, 0xa8, 0x3c, 0x89, 0xc1, 0xc4, 0xfb, - 0x7e, 0x08, 0xc9, 0xb6, 0x63, 0xf5, 0xbb, 0x36, 0xd7, 0x29, 0xb3, 0x7e, 0x67, 0x56, 0xae, 0x9b, - 0x8c, 0x5c, 0xb0, 0x95, 0xcc, 0xd0, 0x01, 0x24, 0x4d, 0xdb, 0xc0, 0xef, 0x63, 0x52, 0x8c, 0x3e, - 0x9d, 0xb4, 0x0d, 0x4a, 0x2e, 0xd9, 0x0a, 0x5e, 0xd4, 0x3d, 0x5d, 0xdd, 0xee, 0x50, 0x17, 0xe8, - 0xdb, 0x1e, 0x73, 0xa3, 0xa8, 0x06, 0x0c, 0xb4, 0x49, 0x21, 0xe8, 0x36, 0x2c, 0xb5, 0x5d, 0xac, - 0x7b, 0xb8, 0xc9, 0xdd, 0x98, 0x78, 0xba, 0x87, 0xbb, 0xd8, 0xf6, 0x98, 0x9f, 0xa4, 0xb5, 0x45, - 0xbe, 0xcb, 0x4e, 0xdc, 0x93, 0x7b, 0xe3, 0xde, 0x99, 0xf8, 0xf2, 0xbc, 0x33, 0xf9, 0x65, 0x79, - 0xe7, 0xc5, 0x87, 0x97, 0x9a, 0xe6, 0xe1, 0x3d, 0x93, 0x53, 0x97, 0x4e, 0x20, 0xc1, 0xaf, 0x97, - 0x52, 0xd3, 0x88, 0x20, 0xa9, 0xe9, 0x37, 0x85, 0x79, 0x67, 0x3d, 0xe9, 0xbe, 0xec, 0x9b, 0xfa, - 0xbb, 0xdd, 0xb7, 0x2c, 0xe6, 0xd6, 0x34, 0x32, 0xa4, 0x34, 0x7f, 0x8d, 0xae, 0x51, 0x0d, 0x0e, - 0xf5, 0xbe, 0xe5, 0x35, 0x4f, 0x75, 0xab, 0x8f, 0xd9, 0xf5, 0xa5, 0xa9, 0xbc, 0x0c, 0xf8, 0x90, - 0xc2, 0x4a, 0x9f, 0x2a, 0x10, 0x67, 0x57, 0x3f, 0xf1, 0xc8, 0x25, 0x48, 0xf4, 0x6d, 0xf3, 0xa4, - 0xcf, 0x0f, 0x4d, 0x69, 0x62, 0x85, 0xf2, 0x10, 0x25, 0xf8, 0x84, 0xc7, 0x22, 0x8d, 0x7e, 0x52, - 0x4c, 0xee, 0x8b, 0xe2, 0x14, 0xb1, 0x62, 0x81, 0xda, 0x74, 0x71, 0x9b, 0x5a, 0x5a, 0xf8, 0xc4, - 0x10, 0x80, 0x8a, 0x90, 0xa4, 0x99, 0xc5, 0xb4, 0xb9, 0x13, 0xa4, 0x34, 0xb9, 0xa4, 0x8a, 0x99, - 0xdd, 0x9e, 0x65, 0xb6, 0x4d, 0x8f, 0x5d, 0x6a, 0x4a, 0xf3, 0xd7, 0xea, 0x16, 0x14, 0x7c, 0x87, - 0x7a, 0x86, 0x97, 0xff, 0x71, 0x14, 0x50, 0x90, 0x8f, 0x78, 0xf7, 0x63, 0x3e, 0xaf, 0x5c, 0xf0, - 0xf9, 0x6b, 0x90, 0x73, 0x31, 0x15, 0x45, 0x17, 0x28, 0x11, 0x86, 0x92, 0x15, 0x40, 0x8e, 0xf4, - 0xff, 0x00, 0xb6, 0x63, 0x48, 0x26, 0xdc, 0x50, 0x69, 0x0a, 0xe1, 0xdb, 0xf7, 0x21, 0x4e, 0x9f, - 0x0a, 0x11, 0x91, 0xf9, 0x66, 0xd0, 0x61, 0x79, 0xaa, 0xad, 0xf0, 0xfc, 0x5c, 0x91, 0x69, 0xba, - 0xf2, 0xe0, 0xe1, 0xe6, 0x26, 0x93, 0x54, 0xbc, 0x05, 0xce, 0x00, 0x19, 0x90, 0xeb, 0x9a, 0x84, - 0x98, 0x76, 0xa7, 0x49, 0xd9, 0x93, 0x62, 0x9c, 0xbd, 0xff, 0xaf, 0x3d, 0xe9, 0xfd, 0x8f, 0x28, - 0x5d, 0x79, 0xc0, 0x59, 0xec, 0x3a, 0x06, 0x16, 0xec, 0xb3, 0xdd, 0x21, 0x88, 0x94, 0xde, 0x85, - 0x4c, 0x00, 0x05, 0x5d, 0x83, 0x24, 0xd3, 0xce, 0x34, 0xb8, 0xad, 0x6b, 0x30, 0x38, 0x2f, 0x27, - 0xe8, 0x56, 0xa3, 0xae, 0x25, 0xe8, 0x56, 0xc3, 0xa0, 0x76, 0xc2, 0xae, 0xeb, 0xb8, 0xcd, 0x2e, - 0x26, 0x44, 0xef, 0x48, 0xeb, 0x67, 0x19, 0xf0, 0x01, 0x87, 0xa9, 0x73, 0x90, 0x3d, 0x20, 0xd8, - 0xf5, 0xb3, 0xfd, 0x77, 0x21, 0x27, 0xd6, 0xe2, 0x3a, 0x1a, 0x10, 0xa7, 0x6f, 0x47, 0x46, 0xe1, - 0x97, 0x42, 0xf4, 0x1a, 0x21, 0x64, 0x2b, 0x69, 0x2a, 0xc6, 0xa1, 0xa4, 0x42, 0x8c, 0x02, 0xa9, - 0xab, 0x50, 0x40, 0xc0, 0xdb, 0xfd, 0xb5, 0xfa, 0x10, 0x72, 0x5b, 0xa7, 0xd8, 0x1e, 0xfa, 0x95, - 0x7c, 0x75, 0x4a, 0xe0, 0xd5, 0x5d, 0x81, 0xb4, 0xa7, 0xbb, 0x1d, 0xec, 0x51, 0x03, 0xf0, 0xdb, - 0x4f, 0x71, 0x40, 0xc3, 0xa0, 0xce, 0x66, 0x99, 0x5d, 0x93, 0x5f, 0x7a, 0x5c, 0xe3, 0x0b, 0xf5, - 0xdf, 0x11, 0x98, 0x93, 0x8c, 0x85, 0x66, 0x0f, 0x20, 0x81, 0x19, 0x44, 0xa8, 0x56, 0x0d, 0x51, - 0x6d, 0x94, 0x94, 0x2f, 0x65, 0x6a, 0xe1, 0x4c, 0x4a, 0x3f, 0x8a, 0x40, 0x9c, 0xc1, 0x51, 0x0d, - 0xd2, 0x7e, 0x61, 0xc5, 0xe4, 0xce, 0xac, 0x97, 0x2a, 0xbc, 0xf4, 0xaa, 0xc8, 0xd2, 0xab, 0xb2, - 0x2f, 0x31, 0x6a, 0x29, 0xca, 0xe6, 0x93, 0xbf, 0x95, 0x15, 0x6d, 0x48, 0x46, 0xfd, 0x97, 0xf1, - 0x6d, 0x06, 0x42, 0x4e, 0x9a, 0x41, 0xf6, 0xa9, 0x05, 0x5e, 0x0c, 0x5a, 0x80, 0x97, 0x24, 0xd9, - 0xc1, 0x79, 0x39, 0xb5, 0xcf, 0xad, 0x50, 0x0f, 0xd8, 0x63, 0x1d, 0xe8, 0xcb, 0x70, 0x5c, 0x8f, - 0xba, 0xa8, 0x69, 0xf0, 0x24, 0x52, 0x9b, 0x1f, 0x9c, 0x97, 0x33, 0x9a, 0x84, 0x37, 0xea, 0x5a, - 0xc6, 0x47, 0x6a, 0x18, 0xd4, 0xe8, 0xa6, 0x7d, 0xe8, 0x88, 0x80, 0xc1, 0xbe, 0xe9, 0x91, 0x3c, - 0xfa, 0x50, 0x26, 0x34, 0x5a, 0x64, 0xf9, 0x91, 0x07, 0x0c, 0x48, 0x8f, 0xe4, 0xdb, 0x0d, 0x43, - 0xfd, 0xad, 0x02, 0xf9, 0x3d, 0xec, 0x1d, 0x34, 0x68, 0x29, 0x26, 0x2f, 0xf2, 0x1b, 0x00, 0xc7, - 0xf8, 0x8c, 0x87, 0x42, 0x69, 0xf2, 0xbb, 0x21, 0x26, 0x1f, 0x67, 0x50, 0x79, 0x13, 0x9f, 0xb1, - 0x98, 0x49, 0xb6, 0x6c, 0xcf, 0x3d, 0xd3, 0xd2, 0xc7, 0x72, 0x5d, 0xba, 0x07, 0x73, 0xa3, 0x9b, - 0x34, 0x40, 0x1e, 0xe3, 0x33, 0xe1, 0x34, 0xf4, 0x93, 0xba, 0x05, 0x8f, 0xc2, 0xd4, 0x96, 0x59, - 0x8d, 0x2f, 0xee, 0x46, 0x5e, 0x53, 0xd4, 0x05, 0x28, 0x04, 0xce, 0xe2, 0x37, 0xac, 0xbe, 0x00, - 0xf9, 0xed, 0x71, 0x0d, 0x10, 0xc4, 0x8e, 0xf1, 0x99, 0xac, 0x77, 0xd9, 0xb7, 0xfa, 0xc7, 0x08, - 0x14, 0xb6, 0xc7, 0xa9, 0xd1, 0xb7, 0x26, 0xe8, 0xfa, 0x7a, 0x88, 0xae, 0x17, 0x38, 0x8c, 0x29, - 0x2b, 0x5c, 0x2d, 0xa0, 0xf2, 0x21, 0xc4, 0xd9, 0xd7, 0x50, 0x2f, 0x25, 0xa0, 0x17, 0xda, 0x86, - 0xac, 0xa5, 0x13, 0xaf, 0xd9, 0xef, 0x19, 0xba, 0x87, 0xf9, 0x23, 0x99, 0xd6, 0x0b, 0x33, 0x94, - 0xf2, 0x80, 0x13, 0x96, 0x7a, 0x53, 0x98, 0xf6, 0x7e, 0xd0, 0xb4, 0x99, 0xf5, 0xf5, 0x99, 0x14, - 0x65, 0xac, 0x83, 0xd7, 0x91, 0x87, 0xb9, 0x4d, 0xab, 0x4f, 0x3c, 0xec, 0xca, 0x98, 0xf4, 0x33, - 0x05, 0xe6, 0x7d, 0x90, 0xb0, 0xf0, 0x4d, 0x80, 0x36, 0x07, 0x0d, 0x83, 0x60, 0x6e, 0x70, 0x5e, - 0x4e, 0x0b, 0xc4, 0x46, 0x5d, 0x4b, 0x0b, 0x84, 0x86, 0x81, 0x6e, 0x40, 0x61, 0xf8, 0x06, 0xb0, - 0x4d, 0xe3, 0xaf, 0x21, 0x52, 0x6a, 0xde, 0xdf, 0xd8, 0xe2, 0x70, 0xf4, 0x12, 0x20, 0x6c, 0x7b, - 0xd8, 0xed, 0xb9, 0x26, 0xc1, 0x3e, 0x36, 0xcf, 0xee, 0x85, 0xe1, 0x8e, 0x40, 0x57, 0x77, 0x20, - 0x5b, 0x77, 0x75, 0xd3, 0x96, 0x5e, 0x32, 0x07, 0x11, 0xc7, 0x66, 0x77, 0x1e, 0xd7, 0x22, 0x8e, - 0x4d, 0xed, 0xe5, 0x1c, 0x1e, 0xb2, 0x6a, 0x23, 0xae, 0xd1, 0x4f, 0x1a, 0xff, 0xc8, 0x51, 0xdf, - 0x33, 0x9c, 0xc7, 0xb6, 0x2c, 0x1a, 0xe4, 0x5a, 0x2d, 0x43, 0x4e, 0x70, 0x13, 0x8a, 0x8e, 0xb1, - 0x53, 0x3f, 0x80, 0xcb, 0x75, 0xdc, 0x76, 0xba, 0x2c, 0x3d, 0x38, 0x36, 0x4d, 0x23, 0x7d, 0x3f, - 0x58, 0xbe, 0x07, 0x29, 0x91, 0x17, 0xb8, 0xd7, 0xc5, 0x6b, 0xb5, 0xc1, 0x79, 0x39, 0xc9, 0x13, - 0x03, 0xf9, 0xcf, 0x79, 0xf9, 0x95, 0x8e, 0xe9, 0x1d, 0xf5, 0x5b, 0x95, 0xb6, 0xd3, 0xad, 0xfa, - 0xb7, 0x64, 0xb4, 0x86, 0xdf, 0xd5, 0xde, 0x71, 0xa7, 0xca, 0xbe, 0x7a, 0xad, 0x8a, 0x48, 0x28, - 0x49, 0x9e, 0x50, 0x88, 0xfa, 0x73, 0x05, 0x16, 0x82, 0x87, 0xff, 0x6f, 0x8e, 0x45, 0xab, 0x30, - 0x6f, 0x04, 0x4e, 0xa5, 0xd5, 0x0a, 0xbf, 0xbb, 0x71, 0xb0, 0xfa, 0x79, 0x04, 0x4a, 0x93, 0xac, - 0x23, 0x6c, 0xf9, 0x08, 0x12, 0x84, 0x41, 0x44, 0xf1, 0x7f, 0x2f, 0xac, 0x8b, 0xfc, 0x42, 0x36, - 0x15, 0xbe, 0x94, 0xe1, 0x9f, 0x73, 0x2c, 0xfd, 0x4b, 0x81, 0x04, 0xdf, 0x40, 0x8f, 0x46, 0xb3, - 0x73, 0xbc, 0xb6, 0x31, 0xcc, 0xce, 0x4f, 0x6b, 0x0c, 0x99, 0xd4, 0x9f, 0x83, 0xa4, 0x49, 0x9a, - 0x96, 0x79, 0xea, 0x97, 0x84, 0x26, 0xd9, 0x31, 0x4f, 0xf1, 0xc5, 0xaa, 0x28, 0x3a, 0xa1, 0x2a, - 0x9a, 0x60, 0xc9, 0xd8, 0x44, 0x4b, 0xb2, 0x72, 0x8e, 0xfa, 0x21, 0x45, 0x89, 0x73, 0x1f, 0x95, - 0x6b, 0xf5, 0x2b, 0x30, 0xbf, 0x87, 0x3d, 0xfa, 0x64, 0x48, 0x58, 0x68, 0xfc, 0x7d, 0x84, 0x65, - 0x01, 0x81, 0x27, 0xae, 0xa0, 0x39, 0x7b, 0x16, 0x18, 0x61, 0xf0, 0xc4, 0xc0, 0xb8, 0x37, 0x31, - 0x30, 0xa6, 0x65, 0x60, 0x9c, 0x54, 0xc4, 0xaf, 0x40, 0x46, 0xf6, 0x10, 0xb4, 0x4a, 0x8e, 0xb2, - 0xad, 0x20, 0xa8, 0xe4, 0x4c, 0x11, 0x05, 0xb7, 0x47, 0xa3, 0xe0, 0xad, 0x59, 0x94, 0xba, 0x10, - 0x04, 0xe7, 0x21, 0x77, 0x1f, 0xeb, 0x96, 0x77, 0x24, 0x63, 0x60, 0x1e, 0xe6, 0x24, 0x40, 0x64, - 0xa8, 0x02, 0xcc, 0xef, 0x88, 0x29, 0x91, 0x44, 0x3a, 0x80, 0xfc, 0x10, 0x24, 0x0c, 0xbe, 0x01, - 0x20, 0x87, 0x49, 0xbe, 0xc1, 0xaf, 0x4c, 0x28, 0x77, 0x25, 0xa1, 0xec, 0xf4, 0x86, 0x44, 0xaa, - 0x09, 0x99, 0x37, 0x9c, 0x96, 0x7f, 0xd7, 0x7e, 0x81, 0xa5, 0x04, 0x0a, 0x2c, 0xda, 0x80, 0xf8, - 0x6f, 0x8b, 0x35, 0x20, 0x7c, 0x85, 0x6e, 0x0a, 0x83, 0x47, 0x59, 0x67, 0x58, 0x0c, 0x9e, 0x7c, - 0x62, 0x55, 0xd8, 0x7c, 0x8c, 0x56, 0x34, 0xfc, 0x2a, 0xd4, 0x1f, 0xc7, 0x21, 0xcb, 0xcf, 0x12, - 0xe2, 0x6f, 0x41, 0x8c, 0xe2, 0x08, 0xc1, 0x6f, 0x84, 0x18, 0x35, 0x48, 0x46, 0x17, 0x42, 0x11, - 0x46, 0x5e, 0xfa, 0x34, 0x06, 0xd1, 0x37, 0x9c, 0x16, 0x5a, 0x82, 0x88, 0x78, 0x95, 0xd1, 0x5a, - 0x62, 0x70, 0x5e, 0x8e, 0x34, 0xea, 0x5a, 0xc4, 0x34, 0x9e, 0xce, 0x2d, 0x46, 0x0a, 0xd9, 0xd8, - 0x68, 0x21, 0x8b, 0x1c, 0x98, 0x1b, 0xe9, 0x5f, 0x79, 0x63, 0x90, 0xab, 0xdd, 0x1f, 0x9c, 0x97, - 0x73, 0xc1, 0x06, 0x76, 0xfa, 0xf8, 0x48, 0x4e, 0x2c, 0xfa, 0x8f, 0xb6, 0x54, 0x95, 0x46, 0x5d, - 0xcb, 0x05, 0x1b, 0x5f, 0x12, 0xb8, 0x80, 0xc4, 0xc8, 0x05, 0xdc, 0x85, 0x24, 0x1f, 0x02, 0x18, - 0xac, 0x91, 0x0b, 0xaf, 0x02, 0x62, 0xac, 0x02, 0x90, 0x04, 0x94, 0x96, 0x78, 0xba, 0x4b, 0x69, - 0x53, 0xd3, 0xd2, 0x0a, 0x02, 0x74, 0x0f, 0x52, 0x87, 0xa6, 0x6d, 0x92, 0x23, 0x6c, 0x14, 0xd3, - 0x53, 0x12, 0xfb, 0x14, 0x94, 0xba, 0xeb, 0x18, 0xe6, 0xa1, 0x89, 0x8d, 0x22, 0x4c, 0x4b, 0x2d, - 0x29, 0x68, 0x0a, 0x3f, 0x74, 0x75, 0xd6, 0xe3, 0x36, 0xdb, 0x4e, 0xb7, 0x67, 0x61, 0xaa, 0x42, - 0x66, 0x45, 0x59, 0x8d, 0x68, 0x05, 0xb9, 0xb3, 0x29, 0x37, 0xa8, 0x47, 0xb3, 0xa6, 0xa8, 0x98, - 0xe5, 0xa1, 0x82, 0x2d, 0xd4, 0x1a, 0xcc, 0x6b, 0xb4, 0xeb, 0xdc, 0x71, 0x3a, 0xd2, 0xf5, 0x2f, - 0x43, 0x8a, 0xf7, 0xa6, 0xd2, 0x89, 0xb4, 0x24, 0x5b, 0x07, 0xdb, 0x8e, 0x48, 0xb0, 0xed, 0xf8, - 0x6b, 0x14, 0xf2, 0x43, 0x26, 0xc2, 0xa7, 0xdf, 0xf2, 0x1b, 0x0f, 0x9e, 0x86, 0xc2, 0x42, 0xc5, - 0x38, 0xf1, 0xc4, 0xd6, 0xe3, 0x0f, 0x0a, 0xc0, 0xdb, 0x2e, 0xf6, 0xbc, 0xb3, 0x06, 0xad, 0xd4, - 0x9f, 0x87, 0xac, 0xa8, 0xfb, 0x9a, 0xd4, 0x45, 0x44, 0x90, 0xca, 0x08, 0x18, 0xf5, 0x3d, 0xaa, - 0x88, 0x8d, 0x1f, 0xf3, 0x6d, 0xee, 0xf3, 0x49, 0x1b, 0x3f, 0x66, 0x5b, 0xd7, 0x20, 0xa7, 0x1b, - 0x06, 0x36, 0x9a, 0x22, 0x73, 0x08, 0xc7, 0xcf, 0x32, 0xa0, 0xc6, 0x61, 0xe8, 0x3a, 0xcc, 0xbb, - 0xb8, 0xeb, 0x9c, 0x06, 0xd0, 0xf8, 0x03, 0x98, 0x13, 0x60, 0x89, 0xb8, 0x04, 0x09, 0x17, 0xeb, - 0xc4, 0x1f, 0x3e, 0x88, 0x15, 0x2a, 0x42, 0xd2, 0xe0, 0x13, 0x30, 0xe1, 0xae, 0x72, 0x59, 0xfa, - 0x95, 0x22, 0xfb, 0xa8, 0x7b, 0x10, 0x67, 0x0a, 0x8a, 0x1e, 0x6a, 0x65, 0x42, 0xd4, 0x92, 0xe6, - 0x09, 0x5a, 0x85, 0x13, 0xa1, 0xf7, 0x20, 0xd3, 0x63, 0x36, 0x69, 0xb2, 0x56, 0x86, 0x47, 0xe5, - 0x3b, 0xb3, 0x98, 0x7a, 0x68, 0x52, 0x19, 0x14, 0x7b, 0x3e, 0xe4, 0x8d, 0x58, 0x4a, 0xc9, 0x47, - 0xd4, 0x55, 0xc8, 0xbf, 0xd3, 0xc7, 0xee, 0xd9, 0xdb, 0x96, 0x6e, 0x07, 0xe2, 0xe3, 0x09, 0x85, - 0xc9, 0xc4, 0xc3, 0x16, 0x6a, 0x0f, 0x0a, 0x01, 0x4c, 0xe1, 0x09, 0xdf, 0x84, 0x2b, 0x86, 0x49, - 0x3c, 0x72, 0x62, 0x35, 0x7b, 0x47, 0x67, 0xc4, 0x6c, 0xeb, 0x56, 0x93, 0xa1, 0x37, 0x7b, 0x96, - 0x6e, 0x8b, 0xb2, 0xf6, 0xea, 0xe0, 0xbc, 0x5c, 0xac, 0x9b, 0xc4, 0xdb, 0x7b, 0x67, 0xe7, 0x6d, - 0x81, 0x35, 0x64, 0x55, 0x14, 0x0c, 0x2e, 0xec, 0xac, 0xbd, 0x09, 0x4b, 0x93, 0x87, 0x6d, 0x28, - 0x03, 0xc9, 0x83, 0xdd, 0x37, 0x77, 0xdf, 0x7a, 0x77, 0x37, 0x7f, 0x89, 0x2e, 0x36, 0x77, 0x0e, - 0xf6, 0xf6, 0xb7, 0xb4, 0xbc, 0x82, 0xb2, 0x90, 0xaa, 0x6f, 0xec, 0x6f, 0xd4, 0x36, 0xf6, 0xb6, - 0xf2, 0x11, 0x94, 0x86, 0xf8, 0xfe, 0x46, 0x6d, 0x67, 0x2b, 0x1f, 0x5d, 0xbb, 0x06, 0x69, 0x56, - 0x97, 0x3e, 0x70, 0x0c, 0x8c, 0x00, 0x12, 0x9b, 0x3b, 0x8d, 0xad, 0xdd, 0xfd, 0xfc, 0x25, 0xfa, - 0xbd, 0xb3, 0xb5, 0xb1, 0xb7, 0xb5, 0x97, 0x57, 0xd6, 0x7f, 0xba, 0x00, 0xf1, 0x0d, 0xa3, 0x6b, - 0xda, 0xc8, 0x83, 0x38, 0x9b, 0x06, 0xa0, 0xeb, 0x4f, 0x9e, 0x17, 0x30, 0xab, 0x95, 0x56, 0xa7, - 0x1d, 0x2c, 0xa8, 0xc5, 0x8f, 0xff, 0xfc, 0xcf, 0x9f, 0x44, 0x10, 0xca, 0x57, 0x9b, 0xec, 0x27, - 0x9a, 0xea, 0xe9, 0xad, 0x2a, 0x1b, 0x30, 0xa0, 0x1f, 0x2a, 0x90, 0xf6, 0x7f, 0xab, 0x40, 0x37, - 0xa6, 0xf8, 0x8d, 0xc0, 0x3f, 0xfe, 0xe6, 0x74, 0xc8, 0x42, 0x84, 0xab, 0x4c, 0x84, 0x25, 0xb4, - 0x18, 0x10, 0xc1, 0xff, 0xf9, 0x03, 0xfd, 0x42, 0x81, 0xf9, 0xb1, 0x1f, 0x21, 0xd0, 0xad, 0x59, - 0x7e, 0xb0, 0xe0, 0x22, 0xad, 0xcf, 0xfe, 0x1b, 0x87, 0x7a, 0x9d, 0x09, 0xf6, 0x3c, 0x2a, 0x4f, - 0x12, 0xac, 0xfa, 0xa1, 0xfc, 0xfc, 0x08, 0xfd, 0x5a, 0x81, 0x6c, 0x70, 0x0e, 0x8d, 0x2a, 0x53, - 0x0f, 0xac, 0xb9, 0x74, 0xd5, 0x19, 0x07, 0xdc, 0xea, 0x1d, 0x26, 0xda, 0xcb, 0xa8, 0xf2, 0x04, - 0xd1, 0xaa, 0x6c, 0x3a, 0x48, 0xaa, 0x1f, 0xb2, 0xbf, 0x4c, 0x52, 0x18, 0x4e, 0xcc, 0xd0, 0xcd, - 0x29, 0x07, 0x6b, 0x5c, 0xca, 0x97, 0x66, 0x1a, 0xc3, 0xa9, 0xf7, 0x98, 0x8c, 0x77, 0xd0, 0xed, - 0xd9, 0x64, 0xac, 0xf2, 0x51, 0xe0, 0xfb, 0x90, 0xe0, 0x73, 0x22, 0xb4, 0x3a, 0xc5, 0x28, 0x89, - 0x0b, 0xf8, 0xe2, 0xd4, 0x43, 0x27, 0xf5, 0x32, 0x13, 0x6e, 0x01, 0x15, 0x02, 0xc2, 0xf1, 0x04, - 0xc0, 0x1c, 0xdf, 0x9f, 0x61, 0x84, 0x3a, 0xfe, 0xf8, 0x54, 0x25, 0xd4, 0xf1, 0x2f, 0x8e, 0x45, - 0x84, 0xe3, 0xab, 0x41, 0x19, 0xfa, 0x26, 0xb5, 0xcb, 0x5d, 0x65, 0x0d, 0x7d, 0x5f, 0x81, 0xf4, - 0xf6, 0x54, 0x62, 0x6c, 0xcf, 0x22, 0xc6, 0x85, 0xa1, 0xc1, 0x44, 0x53, 0x70, 0x31, 0xd0, 0x77, - 0x20, 0x29, 0x46, 0x00, 0x28, 0xcc, 0xb6, 0xa3, 0x23, 0x86, 0xd2, 0xda, 0x34, 0xa8, 0xe2, 0xf0, - 0x12, 0x3b, 0x7c, 0x11, 0xa1, 0xc0, 0xe1, 0x62, 0xd4, 0x80, 0xbe, 0xa7, 0x40, 0x4a, 0x56, 0xf7, - 0x68, 0x6d, 0xaa, 0x16, 0x80, 0x0b, 0x70, 0x63, 0x86, 0x76, 0x41, 0xbd, 0xc2, 0x24, 0xf8, 0x3f, - 0xb4, 0x10, 0x90, 0x80, 0xc8, 0x53, 0xdf, 0x87, 0x04, 0xef, 0x14, 0x42, 0xbd, 0x70, 0xa4, 0xbb, - 0x08, 0xf5, 0xc2, 0xb1, 0xb6, 0x63, 0x92, 0xe9, 0x8f, 0xf8, 0x79, 0x54, 0x79, 0xd9, 0x46, 0x84, - 0x2a, 0x3f, 0xd6, 0xb7, 0x84, 0x2a, 0x3f, 0xde, 0xd0, 0x4c, 0x54, 0x5e, 0x36, 0x2b, 0xa8, 0x07, - 0x31, 0xda, 0x07, 0xa0, 0x17, 0x9e, 0xd8, 0x28, 0xf0, 0x93, 0xaf, 0x4f, 0xd9, 0x50, 0xa8, 0xcf, - 0xb1, 0x53, 0x0b, 0x68, 0x3e, 0x70, 0x2a, 0xed, 0x2c, 0xd8, 0xd3, 0xf3, 0x73, 0x6e, 0xa8, 0xcf, - 0x8f, 0x17, 0x0a, 0xa1, 0x3e, 0x7f, 0xa1, 0x56, 0x98, 0x98, 0x73, 0x58, 0xad, 0x40, 0x4b, 0x05, - 0x74, 0x06, 0x71, 0x96, 0x9f, 0x43, 0x13, 0x6e, 0x70, 0x4e, 0x15, 0x9a, 0x70, 0x47, 0x46, 0x50, - 0xd2, 0xe2, 0x6a, 0x30, 0xe1, 0xb2, 0x61, 0xc0, 0x5d, 0x65, 0xed, 0x65, 0x05, 0x3d, 0x86, 0x6c, - 0x70, 0x58, 0x12, 0x9a, 0x49, 0x26, 0x4c, 0x8f, 0x4a, 0xaf, 0x3e, 0xd5, 0x14, 0x46, 0xbd, 0x84, - 0x7e, 0xa0, 0x00, 0xba, 0x88, 0x80, 0x6e, 0xcf, 0xc8, 0xef, 0x19, 0xa5, 0xf8, 0xa5, 0x02, 0x29, - 0x59, 0x3a, 0x86, 0x7a, 0xfd, 0x58, 0x33, 0x11, 0xea, 0xf5, 0xe3, 0xb5, 0xa8, 0xfa, 0x75, 0x76, - 0x07, 0x5f, 0x1d, 0xf1, 0x7a, 0xd6, 0x7a, 0x58, 0x4e, 0xe7, 0xd1, 0x0a, 0x5a, 0x9e, 0x00, 0xae, - 0x7e, 0x28, 0x7b, 0x95, 0x8f, 0x6a, 0xea, 0x67, 0xff, 0x58, 0xbe, 0xf4, 0xd9, 0x60, 0x59, 0xf9, - 0xd3, 0x60, 0x59, 0xf9, 0xcb, 0x60, 0x59, 0xf9, 0xfb, 0x60, 0x59, 0xf9, 0xe4, 0xf3, 0xe5, 0x4b, - 0x8f, 0x52, 0xf2, 0xcc, 0x56, 0x82, 0x35, 0x56, 0xaf, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x59, - 0x12, 0xa4, 0x72, 0x09, 0x23, 0x00, 0x00, + 0xf1, 0x5e, 0x7e, 0x73, 0x48, 0x4a, 0xe4, 0xb3, 0x7e, 0x0a, 0x4d, 0xfb, 0x27, 0x2a, 0x6b, 0x24, + 0x56, 0x64, 0x87, 0x8c, 0x15, 0xc7, 0x4d, 0x1d, 0xf7, 0x20, 0x8a, 0x82, 0xcc, 0x58, 0x56, 0x92, + 0x95, 0xe4, 0x20, 0x2e, 0x02, 0x76, 0xc9, 0x7d, 0xa2, 0xb6, 0x5a, 0xee, 0x52, 0xbb, 0x4b, 0x39, + 0x4c, 0x9a, 0xa2, 0x4d, 0x7b, 0x68, 0x2f, 0x45, 0x80, 0x1e, 0x0b, 0x04, 0x68, 0x51, 0xa0, 0x40, + 0x7b, 0x69, 0x8e, 0xfd, 0x0f, 0x82, 0x5e, 0x5a, 0xa0, 0x97, 0x5e, 0xaa, 0xb6, 0x4c, 0x0f, 0x45, + 0xff, 0x84, 0x5e, 0x5a, 0xbc, 0xaf, 0xdd, 0xe5, 0x47, 0xd6, 0xa4, 0x13, 0xf4, 0x60, 0x6b, 0xdf, + 0xbc, 0x99, 0x79, 0x33, 0xf3, 0xe6, 0xcd, 0x17, 0xe1, 0xb2, 0x83, 0xed, 0x33, 0x6c, 0x57, 0xd9, + 0x9f, 0x5e, 0xab, 0xaa, 0x6a, 0x5d, 0xdd, 0xac, 0xf4, 0x6c, 0xcb, 0xb5, 0xd0, 0xa5, 0xb6, 0xd5, + 0x3e, 0xb1, 0x2d, 0xb5, 0x7d, 0x5c, 0x61, 0xfb, 0x15, 0x81, 0x56, 0x2a, 0xb4, 0x2d, 0xf3, 0x48, + 0xef, 0x54, 0xdf, 0xb7, 0x4c, 0xcc, 0xb0, 0x4b, 0x17, 0x9d, 0x53, 0xa3, 0xfa, 0x6d, 0xab, 0xe5, + 0xd0, 0xff, 0x38, 0x50, 0x76, 0x5c, 0xcb, 0x56, 0x3b, 0xb8, 0x8a, 0xcd, 0x8e, 0x6e, 0x8a, 0x3f, + 0xbd, 0x56, 0xb5, 0x7b, 0xd6, 0x6e, 0x73, 0x9c, 0x65, 0x81, 0x63, 0xe8, 0x67, 0xd8, 0xc4, 0x8e, + 0xa0, 0x2d, 0x78, 0x70, 0xab, 0xc3, 0x41, 0x4b, 0x1d, 0xab, 0x63, 0xd1, 0xcf, 0x2a, 0xf9, 0xe2, + 0xd0, 0x2b, 0x1d, 0xcb, 0xea, 0x18, 0xb8, 0xaa, 0xf6, 0xf4, 0xaa, 0x6a, 0x9a, 0x96, 0xab, 0xba, + 0xba, 0x65, 0x0a, 0x36, 0x65, 0xbe, 0x4b, 0x57, 0xad, 0xfe, 0x51, 0xd5, 0xd5, 0xbb, 0xd8, 0x71, + 0xd5, 0x6e, 0x8f, 0x21, 0xc8, 0x08, 0xf2, 0x75, 0xd5, 0x55, 0x5b, 0xaa, 0x83, 0x1d, 0x05, 0x9f, + 0xf6, 0xb1, 0xe3, 0xca, 0x37, 0xa1, 0x10, 0x80, 0x39, 0x3d, 0xcb, 0x74, 0x30, 0xba, 0x02, 0x69, + 0x4d, 0x00, 0x8b, 0xd2, 0x6a, 0x74, 0x2d, 0xad, 0xf8, 0x00, 0xf9, 0x16, 0x2c, 0x0b, 0x92, 0x3a, + 0x76, 0x55, 0xdd, 0x10, 0xcc, 0x50, 0x09, 0x52, 0x02, 0xad, 0x28, 0xad, 0x4a, 0x6b, 0x69, 0xc5, + 0x5b, 0xcb, 0xbf, 0x8e, 0xc2, 0x33, 0x13, 0x64, 0xfc, 0xbc, 0x87, 0x90, 0xe8, 0xd8, 0xaa, 0xe9, + 0xb2, 0xc3, 0x32, 0x1b, 0xaf, 0x56, 0xbe, 0xf0, 0x42, 0x2a, 0x5f, 0xc0, 0xa3, 0xb2, 0x43, 0x18, + 0xd4, 0x62, 0x9f, 0x9d, 0x97, 0x2f, 0x28, 0x9c, 0x1b, 0x2a, 0x43, 0xc6, 0x55, 0x5b, 0x06, 0x6e, + 0x9a, 0x6a, 0x17, 0x3b, 0xc5, 0x08, 0xd5, 0x04, 0x28, 0x68, 0x8f, 0x40, 0xd0, 0x2b, 0x90, 0xd3, + 0xb0, 0xd3, 0xb6, 0xf5, 0x9e, 0x6b, 0xd9, 0x4d, 0x5d, 0x2b, 0x46, 0x57, 0xa5, 0xb5, 0x68, 0x2d, + 0x3f, 0x3c, 0x2f, 0x67, 0xeb, 0xde, 0x46, 0xa3, 0xae, 0x64, 0x7d, 0xb4, 0x86, 0x86, 0xb6, 0x20, + 0x43, 0xfc, 0xa1, 0xc9, 0x7c, 0xa3, 0x18, 0x5b, 0x95, 0xd6, 0x32, 0x1b, 0x57, 0x02, 0x42, 0xb3, + 0x8d, 0xca, 0x23, 0xcb, 0xc4, 0x5b, 0xf4, 0x93, 0x0b, 0x06, 0xef, 0x7b, 0x10, 0xf4, 0x2e, 0x14, + 0x02, 0x4c, 0x9a, 0x06, 0x3e, 0xc3, 0x46, 0x31, 0xbe, 0x2a, 0xad, 0x2d, 0x6c, 0xdc, 0x0c, 0xd1, + 0xdf, 0xe7, 0xd9, 0xb7, 0xe9, 0xf5, 0xef, 0x12, 0x42, 0x65, 0xd1, 0xe7, 0x4c, 0x01, 0xa5, 0xd7, + 0x20, 0x4e, 0x4d, 0x82, 0x10, 0xc4, 0xfa, 0x0e, 0xb6, 0xf9, 0x85, 0xd0, 0x6f, 0xb4, 0x02, 0xd0, + 0xb3, 0xf5, 0x33, 0xdd, 0xc0, 0x1d, 0xdf, 0x2e, 0x3e, 0x44, 0xde, 0x81, 0x8b, 0x07, 0xc4, 0x4a, + 0xb3, 0xdf, 0x2f, 0x5a, 0x82, 0x38, 0x35, 0x6c, 0x31, 0x42, 0x37, 0xd8, 0x42, 0xfe, 0x6d, 0x12, + 0x96, 0x46, 0x39, 0xf1, 0x2b, 0xdf, 0x1f, 0xbb, 0xf2, 0x57, 0x42, 0x54, 0x9e, 0xc6, 0x60, 0xea, + 0x7d, 0x3f, 0x84, 0x64, 0xdb, 0x32, 0xfa, 0x5d, 0x93, 0xe9, 0x94, 0xd9, 0xb8, 0x3d, 0x2f, 0xd7, + 0x2d, 0x4a, 0xce, 0xd9, 0x0a, 0x66, 0xe8, 0x10, 0x92, 0xba, 0xa9, 0xe1, 0xf7, 0xb0, 0x53, 0x8c, + 0x3e, 0x9d, 0xb4, 0x0d, 0x42, 0x2e, 0xd8, 0x72, 0x5e, 0xc4, 0x3d, 0x6d, 0xd5, 0xec, 0x10, 0x17, + 0xe8, 0x9b, 0x2e, 0x75, 0xa3, 0xa8, 0x02, 0x14, 0xb4, 0x45, 0x20, 0xe8, 0x16, 0x2c, 0xb7, 0x6d, + 0xac, 0xba, 0xb8, 0xc9, 0xdc, 0xd8, 0x71, 0x55, 0x17, 0x77, 0xb1, 0xe9, 0x52, 0x3f, 0x49, 0x2b, + 0x4b, 0x6c, 0x97, 0x9e, 0xb8, 0x2f, 0xf6, 0xc6, 0xbd, 0x33, 0xf1, 0xd5, 0x79, 0x67, 0xf2, 0xab, + 0xf2, 0xce, 0xc9, 0x87, 0x97, 0x9a, 0xe5, 0xe1, 0x7d, 0x29, 0xa7, 0x2e, 0x9d, 0x42, 0x82, 0x5d, + 0x2f, 0xa1, 0x26, 0x11, 0x41, 0x50, 0x93, 0x6f, 0x02, 0x73, 0x07, 0x3d, 0xe1, 0xbe, 0xf4, 0x9b, + 0xf8, 0xbb, 0xd9, 0x37, 0x0c, 0xea, 0xd6, 0x24, 0x32, 0xa4, 0x14, 0x6f, 0x8d, 0xae, 0x12, 0x0d, + 0x8e, 0xd4, 0xbe, 0xe1, 0x36, 0xcf, 0x54, 0xa3, 0x8f, 0xe9, 0xf5, 0xa5, 0x89, 0xbc, 0x14, 0xf8, + 0x90, 0xc0, 0x4a, 0x9f, 0x4a, 0x10, 0xa7, 0x57, 0x3f, 0xf5, 0xc8, 0x65, 0x48, 0xf4, 0x4d, 0xfd, + 0xb4, 0xcf, 0x0e, 0x4d, 0x29, 0x7c, 0x85, 0xf2, 0x10, 0x75, 0xf0, 0x29, 0x8b, 0x45, 0x0a, 0xf9, + 0x24, 0x98, 0xcc, 0x17, 0xf9, 0x29, 0x7c, 0x45, 0x03, 0xb5, 0x6e, 0xe3, 0x36, 0xb1, 0x34, 0xf7, + 0x09, 0x1f, 0x80, 0x8a, 0x90, 0x24, 0x99, 0x45, 0x37, 0x99, 0x13, 0xa4, 0x14, 0xb1, 0x24, 0x8a, + 0xe9, 0xdd, 0x9e, 0xa1, 0xb7, 0x75, 0x97, 0x5e, 0x6a, 0x4a, 0xf1, 0xd6, 0xf2, 0x36, 0x14, 0x3c, + 0x87, 0xfa, 0x12, 0x2f, 0xff, 0xa3, 0x28, 0xa0, 0x20, 0x1f, 0xfe, 0xee, 0xc7, 0x7c, 0x5e, 0x9a, + 0xf0, 0xf9, 0xab, 0x90, 0xb3, 0x31, 0x11, 0x45, 0xe5, 0x28, 0x11, 0x8a, 0x92, 0xe5, 0x40, 0x86, + 0xf4, 0xff, 0x00, 0xa6, 0xa5, 0x09, 0x26, 0xcc, 0x50, 0x69, 0x02, 0x61, 0xdb, 0xf7, 0x20, 0x4e, + 0x9e, 0x8a, 0xc3, 0x23, 0xf3, 0x8d, 0xa0, 0xc3, 0xb2, 0x54, 0x5b, 0x61, 0xf9, 0xb9, 0x22, 0xd2, + 0x74, 0xe5, 0xc1, 0xc3, 0xad, 0x2d, 0x2a, 0x29, 0x7f, 0x0b, 0x8c, 0x01, 0xd2, 0x20, 0xd7, 0xd5, + 0x1d, 0x47, 0x37, 0x3b, 0x4d, 0xc2, 0xde, 0x29, 0xc6, 0xe9, 0xfb, 0xff, 0xfa, 0x93, 0xde, 0xff, + 0x88, 0xd2, 0x95, 0x07, 0x8c, 0xc5, 0x9e, 0xa5, 0x61, 0xce, 0x3e, 0xdb, 0xf5, 0x41, 0x4e, 0xe9, + 0x6d, 0xc8, 0x04, 0x50, 0xd0, 0x55, 0x48, 0x52, 0xed, 0x74, 0x8d, 0xd9, 0xba, 0x06, 0xc3, 0xf3, + 0x72, 0x82, 0x6c, 0x35, 0xea, 0x4a, 0x82, 0x6c, 0x35, 0x34, 0x62, 0x27, 0x6c, 0xdb, 0x96, 0xdd, + 0xec, 0x62, 0xc7, 0x51, 0x3b, 0xc2, 0xfa, 0x59, 0x0a, 0x7c, 0xc0, 0x60, 0xf2, 0x02, 0x64, 0x0f, + 0x1d, 0x6c, 0x7b, 0xd9, 0xfe, 0xbb, 0x90, 0xe3, 0x6b, 0x7e, 0x1d, 0x0d, 0x88, 0x93, 0xb7, 0x23, + 0xa2, 0xf0, 0x8b, 0x21, 0x7a, 0x8d, 0x10, 0xd2, 0x95, 0x30, 0x15, 0xe5, 0x50, 0x92, 0x21, 0x46, + 0x80, 0xc4, 0x55, 0x08, 0x20, 0xe0, 0xed, 0xde, 0x5a, 0x7e, 0x08, 0xb9, 0xed, 0x33, 0x6c, 0xfa, + 0x7e, 0x25, 0x5e, 0x9d, 0x14, 0x78, 0x75, 0x97, 0x21, 0xed, 0xaa, 0x76, 0x07, 0xbb, 0xc4, 0x00, + 0xec, 0xf6, 0x53, 0x0c, 0xd0, 0xd0, 0x88, 0xb3, 0x19, 0x7a, 0x57, 0x67, 0x97, 0x1e, 0x57, 0xd8, + 0x42, 0xfe, 0x57, 0x04, 0x16, 0x04, 0x63, 0xae, 0xd9, 0x03, 0x48, 0x60, 0x0a, 0xe1, 0xaa, 0x55, + 0x43, 0x54, 0x1b, 0x25, 0x65, 0x4b, 0x91, 0x5a, 0x18, 0x93, 0xd2, 0x8f, 0x22, 0x10, 0xa7, 0x70, + 0x54, 0x83, 0xb4, 0x57, 0x58, 0x51, 0xb9, 0x33, 0x1b, 0xa5, 0x0a, 0x2b, 0xbd, 0x2a, 0xa2, 0xf4, + 0xaa, 0x1c, 0x08, 0x8c, 0x5a, 0x8a, 0xb0, 0xf9, 0xf8, 0xaf, 0x65, 0x49, 0xf1, 0xc9, 0x88, 0xff, + 0x52, 0xbe, 0xcd, 0x40, 0xc8, 0x49, 0x53, 0xc8, 0x01, 0xb1, 0xc0, 0x0b, 0x41, 0x0b, 0xb0, 0x92, + 0x24, 0x3b, 0x3c, 0x2f, 0xa7, 0x0e, 0x98, 0x15, 0xea, 0x01, 0x7b, 0x6c, 0x00, 0x79, 0x19, 0x96, + 0xed, 0x12, 0x17, 0xd5, 0x35, 0x96, 0x44, 0x6a, 0x8b, 0xc3, 0xf3, 0x72, 0x46, 0x11, 0xf0, 0x46, + 0x5d, 0xc9, 0x78, 0x48, 0x0d, 0x8d, 0x18, 0x5d, 0x37, 0x8f, 0x2c, 0x1e, 0x30, 0xe8, 0x37, 0x39, + 0x92, 0x45, 0x1f, 0xc2, 0x84, 0x44, 0x8b, 0x2c, 0x3b, 0xf2, 0x90, 0x02, 0xc9, 0x91, 0x6c, 0xbb, + 0xa1, 0xc9, 0xbf, 0x91, 0x20, 0xbf, 0x8f, 0xdd, 0xc3, 0x06, 0x29, 0xc5, 0xc4, 0x45, 0xbe, 0x03, + 0x70, 0x82, 0x07, 0x2c, 0x14, 0x0a, 0x93, 0xdf, 0x09, 0x31, 0xf9, 0x38, 0x83, 0xca, 0x7d, 0x3c, + 0xa0, 0x31, 0xd3, 0xd9, 0x36, 0x5d, 0x7b, 0xa0, 0xa4, 0x4f, 0xc4, 0xba, 0x74, 0x17, 0x16, 0x46, + 0x37, 0x49, 0x80, 0x3c, 0xc1, 0x03, 0xee, 0x34, 0xe4, 0x93, 0xb8, 0x05, 0x8b, 0xc2, 0xc4, 0x96, + 0x59, 0x85, 0x2d, 0xee, 0x44, 0x5e, 0x95, 0xe4, 0x8b, 0x50, 0x08, 0x9c, 0xc5, 0x6e, 0x58, 0x7e, + 0x1e, 0xf2, 0x3b, 0xe3, 0x1a, 0x20, 0x88, 0x9d, 0xe0, 0x81, 0xa8, 0x77, 0xe9, 0xb7, 0xfc, 0x87, + 0x08, 0x14, 0x76, 0xc6, 0xa9, 0xd1, 0xb7, 0xa6, 0xe8, 0xfa, 0x5a, 0x88, 0xae, 0x13, 0x1c, 0xc6, + 0x94, 0xe5, 0xae, 0x16, 0x50, 0xf9, 0x08, 0xe2, 0xf4, 0xcb, 0xd7, 0x4b, 0x0a, 0xe8, 0x85, 0x76, + 0x20, 0x6b, 0xa8, 0x8e, 0xdb, 0xec, 0xf7, 0x34, 0xd5, 0xc5, 0xec, 0x91, 0xcc, 0xea, 0x85, 0x19, + 0x42, 0x79, 0xc8, 0x08, 0x4b, 0xbd, 0x19, 0x4c, 0x7b, 0x2f, 0x68, 0xda, 0xcc, 0xc6, 0xc6, 0x5c, + 0x8a, 0x52, 0xd6, 0xc1, 0xeb, 0xc8, 0xc3, 0xc2, 0x96, 0xd1, 0x77, 0x5c, 0x6c, 0x8b, 0x98, 0xf4, + 0x33, 0x09, 0x16, 0x3d, 0x10, 0xb7, 0xf0, 0x0d, 0x80, 0x36, 0x03, 0xf9, 0x41, 0x30, 0x37, 0x3c, + 0x2f, 0xa7, 0x39, 0x62, 0xa3, 0xae, 0xa4, 0x39, 0x42, 0x43, 0x43, 0xd7, 0xa1, 0xe0, 0xbf, 0x01, + 0x6c, 0x92, 0xf8, 0xab, 0xf1, 0x94, 0x9a, 0xf7, 0x36, 0xb6, 0x19, 0x1c, 0xbd, 0x08, 0x08, 0x9b, + 0x2e, 0xb6, 0x7b, 0xb6, 0xee, 0x60, 0x0f, 0x9b, 0x65, 0xf7, 0x82, 0xbf, 0xc3, 0xd1, 0xe5, 0x5d, + 0xc8, 0xd6, 0x6d, 0x55, 0x37, 0x85, 0x97, 0x2c, 0x40, 0xc4, 0x32, 0xe9, 0x9d, 0xc7, 0x95, 0x88, + 0x65, 0x12, 0x7b, 0x59, 0x47, 0x47, 0xb4, 0xda, 0x88, 0x2b, 0xe4, 0x93, 0xc4, 0x3f, 0xe7, 0xb8, + 0xef, 0x6a, 0xd6, 0x63, 0x53, 0x14, 0x0d, 0x62, 0x2d, 0x97, 0x21, 0xc7, 0xb9, 0x71, 0x45, 0xc7, + 0xd8, 0xc9, 0xef, 0xc3, 0xa5, 0x3a, 0x6e, 0x5b, 0x5d, 0x9a, 0x1e, 0x2c, 0x93, 0xa4, 0x91, 0xbe, + 0x17, 0x2c, 0xdf, 0x85, 0x14, 0xcf, 0x0b, 0xcc, 0xeb, 0xe2, 0xb5, 0xda, 0xf0, 0xbc, 0x9c, 0x64, + 0x89, 0xc1, 0xf9, 0xf7, 0x79, 0xf9, 0xe5, 0x8e, 0xee, 0x1e, 0xf7, 0x5b, 0x95, 0xb6, 0xd5, 0xad, + 0x7a, 0xb7, 0xa4, 0xb5, 0xfc, 0xef, 0x6a, 0xef, 0xa4, 0x53, 0xa5, 0x5f, 0xbd, 0x56, 0x85, 0x27, + 0x94, 0x24, 0x4b, 0x28, 0x8e, 0xfc, 0x89, 0x04, 0x17, 0x83, 0x87, 0xff, 0x6f, 0x8e, 0x45, 0x6b, + 0xb0, 0xa8, 0x05, 0x4e, 0x25, 0xd5, 0x0a, 0xbb, 0xbb, 0x71, 0xb0, 0xfc, 0x79, 0x04, 0x4a, 0xd3, + 0xac, 0xc3, 0x6d, 0xf9, 0x08, 0x12, 0x0e, 0x85, 0xf0, 0xe2, 0xff, 0x6e, 0x58, 0x17, 0xf9, 0x85, + 0x6c, 0x2a, 0x6c, 0x29, 0xc2, 0x3f, 0xe3, 0x58, 0xfa, 0xa7, 0x04, 0x09, 0xb6, 0x81, 0x1e, 0x8d, + 0x66, 0xe7, 0x78, 0x6d, 0xd3, 0xcf, 0xce, 0x4f, 0x6b, 0x0c, 0x91, 0xd4, 0x9f, 0x81, 0xa4, 0xee, + 0x34, 0x0d, 0xfd, 0xcc, 0x2b, 0x09, 0x75, 0x67, 0x57, 0x3f, 0xc3, 0x93, 0x55, 0x51, 0x74, 0x4a, + 0x55, 0x34, 0xc5, 0x92, 0xb1, 0xa9, 0x96, 0xa4, 0xe5, 0x1c, 0xf1, 0x43, 0x82, 0x12, 0x67, 0x3e, + 0x2a, 0xd6, 0xf2, 0x73, 0xb0, 0xb8, 0x8f, 0x5d, 0xf2, 0x64, 0x9c, 0xb0, 0xd0, 0xf8, 0xbb, 0x08, + 0xcd, 0x02, 0x1c, 0x8f, 0x5f, 0x41, 0x73, 0xfe, 0x2c, 0x30, 0xc2, 0xe0, 0x89, 0x81, 0x71, 0x7f, + 0x6a, 0x60, 0x4c, 0x8b, 0xc0, 0x38, 0xad, 0x88, 0x5f, 0x85, 0x8c, 0xe8, 0x21, 0x48, 0x95, 0x1c, + 0xa5, 0x5b, 0x41, 0x50, 0xc9, 0x9a, 0x21, 0x0a, 0xee, 0x8c, 0x46, 0xc1, 0x9b, 0xf3, 0x28, 0x35, + 0x11, 0x04, 0x17, 0x21, 0x77, 0x0f, 0xab, 0x86, 0x7b, 0x2c, 0x62, 0x60, 0x1e, 0x16, 0x04, 0x80, + 0x67, 0xa8, 0x02, 0x2c, 0xee, 0xf2, 0x29, 0x91, 0x40, 0x3a, 0x84, 0xbc, 0x0f, 0xe2, 0x06, 0xdf, + 0x04, 0x10, 0xc3, 0x24, 0xcf, 0xe0, 0x97, 0xa7, 0x94, 0xbb, 0x82, 0x50, 0x74, 0x7a, 0x3e, 0x91, + 0xac, 0x43, 0xe6, 0x75, 0xab, 0xe5, 0xdd, 0xb5, 0x57, 0x60, 0x49, 0x81, 0x02, 0x8b, 0x34, 0x20, + 0xde, 0xdb, 0xa2, 0x0d, 0x08, 0x5b, 0xa1, 0x1b, 0xdc, 0xe0, 0x51, 0xda, 0x19, 0x16, 0x83, 0x27, + 0x9f, 0x1a, 0x15, 0x3a, 0x1f, 0x23, 0x15, 0x0d, 0xbb, 0x0a, 0xf9, 0xc7, 0x71, 0xc8, 0xb2, 0xb3, + 0xb8, 0xf8, 0xdb, 0x10, 0x23, 0x38, 0x5c, 0xf0, 0xeb, 0x21, 0x46, 0x0d, 0x92, 0x91, 0x05, 0x57, + 0x84, 0x92, 0x97, 0x3e, 0x8d, 0x41, 0xf4, 0x75, 0xab, 0x85, 0x96, 0x21, 0xc2, 0x5f, 0x65, 0xb4, + 0x96, 0x18, 0x9e, 0x97, 0x23, 0x8d, 0xba, 0x12, 0xd1, 0xb5, 0xa7, 0x73, 0x8b, 0x91, 0x42, 0x36, + 0x36, 0x5a, 0xc8, 0x22, 0x0b, 0x16, 0x46, 0xfa, 0x57, 0xd6, 0x18, 0xe4, 0x6a, 0xf7, 0x86, 0xe7, + 0xe5, 0x5c, 0xb0, 0x81, 0x9d, 0x3d, 0x3e, 0x3a, 0xa7, 0x06, 0xf9, 0x47, 0x5a, 0xaa, 0x4a, 0xa3, + 0xae, 0xe4, 0x82, 0x8d, 0xaf, 0x13, 0xb8, 0x80, 0xc4, 0xc8, 0x05, 0xdc, 0x81, 0x24, 0x1b, 0x02, + 0x68, 0xb4, 0x91, 0x0b, 0xaf, 0x02, 0x62, 0xb4, 0x02, 0x10, 0x04, 0x84, 0xd6, 0x71, 0x55, 0x9b, + 0xd0, 0xa6, 0x66, 0xa5, 0xe5, 0x04, 0xe8, 0x2e, 0xa4, 0x8e, 0x74, 0x53, 0x77, 0x8e, 0xb1, 0x56, + 0x4c, 0xcf, 0x48, 0xec, 0x51, 0x10, 0xea, 0xae, 0xa5, 0xe9, 0x47, 0x3a, 0xd6, 0x8a, 0x30, 0x2b, + 0xb5, 0xa0, 0x20, 0x29, 0xfc, 0xc8, 0x56, 0x69, 0x8f, 0xdb, 0x6c, 0x5b, 0xdd, 0x9e, 0x81, 0x89, + 0x0a, 0x99, 0x55, 0x69, 0x2d, 0xa2, 0x14, 0xc4, 0xce, 0x96, 0xd8, 0x20, 0x1e, 0x4d, 0x9b, 0xa2, + 0x62, 0x96, 0x85, 0x0a, 0xba, 0x90, 0x11, 0xe4, 0x77, 0xad, 0x36, 0x1b, 0xa0, 0x8a, 0x17, 0xf6, + 0x1f, 0x09, 0x0a, 0x01, 0x20, 0x77, 0xd2, 0x77, 0x20, 0x6d, 0x08, 0xe0, 0x0c, 0xd3, 0xaa, 0x09, + 0x06, 0x1e, 0x44, 0x84, 0x33, 0x8f, 0x5b, 0xe9, 0x27, 0x12, 0xa4, 0xc4, 0x2e, 0x7a, 0x16, 0xb2, + 0x64, 0xc7, 0xd0, 0xdd, 0x41, 0xd3, 0x8f, 0x3e, 0x19, 0x01, 0xbb, 0x8f, 0x07, 0xe8, 0x39, 0x58, + 0xf0, 0x50, 0xfc, 0x70, 0x94, 0x56, 0x72, 0x02, 0xca, 0x82, 0x63, 0x09, 0x52, 0x86, 0xea, 0xea, + 0x6e, 0x5f, 0x63, 0x2f, 0x53, 0x52, 0xbc, 0x35, 0xba, 0x42, 0xb4, 0x31, 0x3b, 0x6c, 0x33, 0x46, + 0x37, 0x7d, 0x80, 0x5c, 0x83, 0x45, 0x85, 0xf4, 0xe2, 0xbb, 0x56, 0x47, 0x04, 0x84, 0x4b, 0x90, + 0x62, 0x1d, 0xbb, 0x78, 0x5a, 0x4a, 0x92, 0xae, 0x83, 0xcd, 0x58, 0x24, 0xd8, 0x8c, 0xfd, 0x25, + 0x0a, 0x79, 0x9f, 0x09, 0x37, 0xe2, 0x1b, 0x5e, 0x3b, 0xc6, 0x92, 0x73, 0x58, 0x00, 0x1d, 0x27, + 0x9e, 0xda, 0x90, 0xfd, 0x5e, 0x02, 0x78, 0xd3, 0xc6, 0xae, 0x3b, 0x68, 0x90, 0xfe, 0xe5, 0x59, + 0xc8, 0xf2, 0x6a, 0xb8, 0x49, 0x1e, 0x8e, 0x30, 0x1e, 0x87, 0x91, 0x17, 0x49, 0x14, 0x31, 0xf1, + 0x63, 0xb6, 0xcd, 0xcc, 0x96, 0x34, 0xf1, 0x63, 0xba, 0x75, 0x15, 0x72, 0xaa, 0xa6, 0x61, 0xad, + 0xc9, 0xf3, 0x29, 0x0f, 0x07, 0x59, 0x0a, 0x54, 0x18, 0x0c, 0x5d, 0x83, 0x45, 0x1b, 0x77, 0xad, + 0xb3, 0x00, 0x1a, 0x0b, 0x0b, 0x0b, 0x1c, 0x2c, 0x10, 0x97, 0x21, 0x61, 0x63, 0xd5, 0xf1, 0x46, + 0x32, 0x7c, 0x85, 0x8a, 0x90, 0xd4, 0xd8, 0x5c, 0x90, 0x3f, 0x62, 0xb1, 0x2c, 0xfd, 0x52, 0x12, + 0xdd, 0xe5, 0x5d, 0x88, 0x53, 0x05, 0x79, 0x67, 0xb9, 0x3a, 0x25, 0x96, 0x0b, 0xf3, 0x04, 0xad, + 0xc2, 0x88, 0xd0, 0xbb, 0x90, 0xe9, 0x51, 0x9b, 0x34, 0x69, 0x83, 0xc7, 0x72, 0xd5, 0xed, 0x79, + 0x4c, 0xed, 0x9b, 0x54, 0xa4, 0x8a, 0x9e, 0x07, 0x79, 0x3d, 0x96, 0x92, 0xf2, 0x11, 0x79, 0x0d, + 0xf2, 0x6f, 0xf5, 0xb1, 0x3d, 0x78, 0xd3, 0x50, 0xcd, 0x40, 0xd6, 0x38, 0x25, 0x30, 0x91, 0x8e, + 0xe9, 0x42, 0xee, 0x41, 0x21, 0x80, 0xc9, 0x3d, 0xe1, 0x9b, 0x70, 0x59, 0xd3, 0x1d, 0xd7, 0x39, + 0x35, 0x9a, 0xbd, 0xe3, 0x81, 0xa3, 0xb7, 0x55, 0xa3, 0x49, 0xd1, 0x9b, 0x3d, 0x43, 0x35, 0x79, + 0xb1, 0x7f, 0x65, 0x78, 0x5e, 0x2e, 0xd6, 0x75, 0xc7, 0xdd, 0x7f, 0x6b, 0xf7, 0x4d, 0x8e, 0xe5, + 0xb3, 0x2a, 0x72, 0x06, 0x13, 0x3b, 0xeb, 0xf7, 0x61, 0x79, 0xfa, 0x08, 0x12, 0x65, 0x20, 0x79, + 0xb8, 0x77, 0x7f, 0xef, 0x8d, 0xb7, 0xf7, 0xf2, 0x17, 0xc8, 0x62, 0x6b, 0xf7, 0x70, 0xff, 0x60, + 0x5b, 0xc9, 0x4b, 0x28, 0x0b, 0xa9, 0xfa, 0xe6, 0xc1, 0x66, 0x6d, 0x73, 0x7f, 0x3b, 0x1f, 0x41, + 0x69, 0x88, 0x1f, 0x6c, 0xd6, 0x76, 0xb7, 0xf3, 0xd1, 0xf5, 0xab, 0x90, 0xa6, 0xd5, 0xfa, 0x03, + 0x4b, 0xc3, 0x08, 0x20, 0xb1, 0xb5, 0xdb, 0xd8, 0xde, 0x3b, 0xc8, 0x5f, 0x20, 0xdf, 0xbb, 0xdb, + 0x9b, 0xfb, 0xdb, 0xfb, 0x79, 0x69, 0xe3, 0x93, 0x25, 0x88, 0x6f, 0x6a, 0x5d, 0xdd, 0x44, 0x2e, + 0xc4, 0xe9, 0x8c, 0x04, 0x5d, 0x7b, 0xf2, 0x14, 0x85, 0x5a, 0xad, 0xb4, 0x36, 0xeb, 0xb8, 0x45, + 0x2e, 0x7e, 0xf4, 0xa7, 0x7f, 0xfc, 0x34, 0x82, 0x50, 0xbe, 0xda, 0xa4, 0x3f, 0x5c, 0x55, 0xcf, + 0x6e, 0x56, 0xe9, 0xd8, 0x05, 0xfd, 0x50, 0x82, 0xb4, 0xf7, 0x0b, 0x0e, 0xba, 0x3e, 0xc3, 0x2f, + 0x27, 0xde, 0xf1, 0x37, 0x66, 0x43, 0xe6, 0x22, 0x5c, 0xa1, 0x22, 0x2c, 0xa3, 0xa5, 0x80, 0x08, + 0xde, 0x8f, 0x42, 0xe8, 0xe7, 0x12, 0x2c, 0x8e, 0xfd, 0x34, 0x83, 0x6e, 0xce, 0xf3, 0x33, 0x0e, + 0x13, 0x69, 0x63, 0xfe, 0x5f, 0x7e, 0xe4, 0x6b, 0x54, 0xb0, 0x67, 0x51, 0x79, 0x9a, 0x60, 0xd5, + 0x0f, 0xc4, 0xe7, 0x87, 0xe8, 0x57, 0x12, 0x64, 0x83, 0xd3, 0x79, 0x54, 0x99, 0x79, 0x8c, 0xcf, + 0xa4, 0xab, 0xce, 0x39, 0xf6, 0x97, 0x6f, 0x53, 0xd1, 0x5e, 0x42, 0x95, 0x27, 0x88, 0x56, 0xa5, + 0x33, 0x53, 0xa7, 0xfa, 0x01, 0xfd, 0x4b, 0x25, 0x05, 0x7f, 0x8e, 0x88, 0x6e, 0xcc, 0x38, 0x6e, + 0x64, 0x52, 0xbe, 0x38, 0xd7, 0x70, 0x52, 0xbe, 0x4b, 0x65, 0xbc, 0x8d, 0x6e, 0xcd, 0x27, 0x63, + 0x95, 0x0d, 0x48, 0xdf, 0x83, 0x04, 0x9b, 0x9e, 0xa1, 0xb5, 0x19, 0x06, 0x6c, 0x4c, 0xc0, 0x17, + 0x66, 0x1e, 0xc5, 0xc9, 0x97, 0xa8, 0x70, 0x17, 0x51, 0x21, 0x20, 0x1c, 0x4b, 0x00, 0xd4, 0xf1, + 0xbd, 0xc9, 0x4e, 0xa8, 0xe3, 0x8f, 0xcf, 0x9a, 0x42, 0x1d, 0x7f, 0x72, 0x58, 0xc4, 0x1d, 0x5f, + 0x0e, 0xca, 0xd0, 0xd7, 0x89, 0x5d, 0xee, 0x48, 0xeb, 0xe8, 0xfb, 0x12, 0xa4, 0x77, 0x66, 0x12, + 0x63, 0x67, 0x1e, 0x31, 0x26, 0x46, 0x29, 0x53, 0x4d, 0xc1, 0xc4, 0x40, 0xdf, 0x81, 0x24, 0x1f, + 0x8c, 0xa0, 0x30, 0xdb, 0x8e, 0x0e, 0x5e, 0x4a, 0xeb, 0xb3, 0xa0, 0xf2, 0xc3, 0x4b, 0xf4, 0xf0, + 0x25, 0x84, 0x02, 0x87, 0xf3, 0x01, 0x0c, 0xfa, 0x9e, 0x04, 0x29, 0xd1, 0xf3, 0xa0, 0xf5, 0x99, + 0x1a, 0x23, 0x26, 0xc0, 0xf5, 0x39, 0x9a, 0x28, 0xf9, 0x32, 0x95, 0xe0, 0xff, 0xd0, 0xc5, 0x80, + 0x04, 0x8e, 0x38, 0xf5, 0x3d, 0x48, 0xb0, 0xfe, 0x29, 0xd4, 0x0b, 0x47, 0x7a, 0xae, 0x50, 0x2f, + 0x1c, 0x6b, 0xc6, 0xa6, 0x99, 0xfe, 0x98, 0x9d, 0x47, 0x94, 0x17, 0xcd, 0x55, 0xa8, 0xf2, 0x63, + 0xdd, 0x5c, 0xa8, 0xf2, 0xe3, 0x6d, 0xde, 0x54, 0xe5, 0x45, 0x0b, 0x87, 0x7a, 0x10, 0x23, 0xdd, + 0x11, 0x7a, 0xfe, 0x89, 0xed, 0x13, 0x3b, 0xf9, 0xda, 0x8c, 0x6d, 0x96, 0xfc, 0x0c, 0x3d, 0xb5, + 0x80, 0x16, 0x03, 0xa7, 0x92, 0x7e, 0x8b, 0x3e, 0x3d, 0xaf, 0xcc, 0x0d, 0xf5, 0xf9, 0xf1, 0x12, + 0x3b, 0xd4, 0xe7, 0x27, 0x2a, 0xe7, 0xa9, 0x39, 0xc7, 0xab, 0x9e, 0xa9, 0x18, 0x5e, 0xea, 0x0f, + 0x15, 0x63, 0xbc, 0x5e, 0x09, 0x15, 0x63, 0xa2, 0x64, 0x99, 0x2a, 0x06, 0x2d, 0x59, 0x48, 0xc5, + 0x82, 0x06, 0x10, 0xa7, 0x65, 0x42, 0x68, 0xde, 0x0f, 0x0e, 0x11, 0x43, 0xf3, 0xfe, 0xc8, 0x7c, + 0x50, 0x5c, 0xbc, 0x1c, 0xcc, 0xfb, 0x74, 0x52, 0x73, 0x47, 0x5a, 0x7f, 0x49, 0x42, 0x8f, 0x21, + 0x1b, 0x9c, 0x64, 0x85, 0x26, 0xb4, 0x29, 0xa3, 0xbd, 0xd2, 0x2b, 0x4f, 0x35, 0x22, 0x93, 0x2f, + 0xa0, 0x1f, 0x48, 0x80, 0x26, 0x11, 0xd0, 0xad, 0x39, 0xf9, 0x7d, 0x49, 0x29, 0x7e, 0x21, 0x41, + 0x4a, 0x54, 0xb0, 0xa1, 0x8f, 0x6f, 0xac, 0xa7, 0x09, 0x7d, 0x7c, 0xe3, 0x25, 0xb1, 0xfc, 0x0d, + 0x7a, 0x07, 0x5f, 0x1b, 0x79, 0x7c, 0xb4, 0x03, 0x32, 0xac, 0xce, 0xa3, 0x55, 0xb4, 0x32, 0x05, + 0x5c, 0xfd, 0x40, 0xb4, 0x4c, 0x1f, 0xd6, 0xe4, 0xcf, 0xfe, 0xbe, 0x72, 0xe1, 0xb3, 0xe1, 0x8a, + 0xf4, 0xc7, 0xe1, 0x8a, 0xf4, 0xe7, 0xe1, 0x8a, 0xf4, 0xb7, 0xe1, 0x8a, 0xf4, 0xf1, 0xe7, 0x2b, + 0x17, 0x1e, 0xa5, 0xc4, 0x99, 0xad, 0x04, 0xed, 0x7a, 0x5f, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xb1, 0x73, 0x73, 0x09, 0xa6, 0x24, 0x00, 0x00, } diff --git a/pkg/server/serverpb/admin.pb.gw.go b/pkg/server/serverpb/admin.pb.gw.go index d9ed19043913..7320dc4360f2 100644 --- a/pkg/server/serverpb/admin.pb.gw.go +++ b/pkg/server/serverpb/admin.pb.gw.go @@ -257,6 +257,15 @@ func request_Admin_Jobs_0(ctx context.Context, marshaler runtime.Marshaler, clie } +func request_Admin_Locations_0(ctx context.Context, marshaler runtime.Marshaler, client AdminClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq LocationsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Locations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + var ( filter_Admin_QueryPlan_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -762,6 +771,35 @@ func RegisterAdminHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Admin_Locations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Admin_Locations_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Admin_Locations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Admin_QueryPlan_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -908,6 +946,8 @@ var ( pattern_Admin_Jobs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"_admin", "v1", "jobs"}, "")) + pattern_Admin_Locations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"_admin", "v1", "locations"}, "")) + pattern_Admin_QueryPlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"_admin", "v1", "queryplan"}, "")) pattern_Admin_Drain_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"_admin", "v1", "drain"}, "")) @@ -944,6 +984,8 @@ var ( forward_Admin_Jobs_0 = runtime.ForwardResponseMessage + forward_Admin_Locations_0 = runtime.ForwardResponseMessage + forward_Admin_QueryPlan_0 = runtime.ForwardResponseMessage forward_Admin_Drain_0 = runtime.ForwardResponseStream diff --git a/pkg/server/serverpb/admin.proto b/pkg/server/serverpb/admin.proto index 5ce3c9c99f09..a60b0b841f44 100644 --- a/pkg/server/serverpb/admin.proto +++ b/pkg/server/serverpb/admin.proto @@ -433,6 +433,22 @@ message JobsResponse { repeated Job jobs = 1 [(gogoproto.nullable) = false]; } +// LocationsRequest requests system locality location information. +message LocationsRequest { +} + +// JobsResponse contains the job record for each matching job. +message LocationsResponse { + message Location { + string locality_key = 1; + string locality_value = 2; + double latitude = 3; + double longitude = 4; + } + + repeated Location locations = 1 [(gogoproto.nullable) = false]; +} + // RangeLogRequest request the history of a range from the range log. message RangeLogRequest { // TODO(tamird): use [(gogoproto.customname) = "RangeID"] below. Need to @@ -601,6 +617,13 @@ service Admin { }; } + // Locations returns the locality location records. + rpc Locations(LocationsRequest) returns (LocationsResponse) { + option (google.api.http) = { + get: "/_admin/v1/locations" + }; + } + // QueryPlan returns the query plans for a SQL string. rpc QueryPlan(QueryPlanRequest) returns (QueryPlanResponse) { option (google.api.http) = { diff --git a/pkg/sql/logictest/testdata/logic_test/explain b/pkg/sql/logictest/testdata/logic_test/explain index caee8dcb6b7b..e86ba5226904 100644 --- a/pkg/sql/logictest/testdata/logic_test/explain +++ b/pkg/sql/logictest/testdata/logic_test/explain @@ -137,7 +137,7 @@ EXPLAIN SHOW TABLES 1 render · · 2 filter · · 3 values · · -3 · size 5 columns, 73 rows +3 · size 5 columns, 74 rows query ITTT EXPLAIN SHOW DATABASE @@ -194,11 +194,11 @@ EXPLAIN SHOW COLUMNS FROM foo 5 render · · 6 filter · · 7 values · · -7 · size 13 columns, 617 rows +7 · size 13 columns, 621 rows 5 render · · 6 filter · · 7 values · · -7 · size 13 columns, 29 rows +7 · size 13 columns, 31 rows query ITTT EXPLAIN SHOW GRANTS ON foo @@ -208,7 +208,7 @@ EXPLAIN SHOW GRANTS ON foo 1 render · · 2 filter · · 3 values · · -3 · size 8 columns, 55 rows +3 · size 8 columns, 60 rows query ITTT @@ -217,7 +217,7 @@ EXPLAIN SHOW INDEX FROM foo 0 render · · 1 filter · · 2 values · · -2 · size 13 columns, 29 rows +2 · size 13 columns, 31 rows query ITTT EXPLAIN SHOW CONSTRAINTS FROM foo diff --git a/pkg/sql/logictest/testdata/logic_test/grant_table b/pkg/sql/logictest/testdata/logic_test/grant_table index b881d0a3ec6f..a2606f7d9c35 100644 --- a/pkg/sql/logictest/testdata/logic_test/grant_table +++ b/pkg/sql/logictest/testdata/logic_test/grant_table @@ -41,6 +41,11 @@ system lease root GRANT system lease root INSERT system lease root SELECT system lease root UPDATE +system locations root DELETE +system locations root GRANT +system locations root INSERT +system locations root SELECT +system locations root UPDATE system namespace root GRANT system namespace root SELECT system rangelog root DELETE diff --git a/pkg/sql/logictest/testdata/logic_test/information_schema b/pkg/sql/logictest/testdata/logic_test/information_schema index 0218c4fa37fd..49a845fcce81 100644 --- a/pkg/sql/logictest/testdata/logic_test/information_schema +++ b/pkg/sql/logictest/testdata/logic_test/information_schema @@ -269,6 +269,7 @@ system descriptor system eventlog system jobs system lease +system locations system namespace system rangelog system settings @@ -432,6 +433,7 @@ def system descriptor BASE TABLE 1 def system eventlog BASE TABLE 2 def system jobs BASE TABLE 1 def system lease BASE TABLE 1 +def system locations BASE TABLE 1 def system namespace BASE TABLE 1 def system rangelog BASE TABLE 1 def system settings BASE TABLE 1 @@ -496,6 +498,7 @@ def system primary def system def system primary def system eventlog PRIMARY KEY NO NO def system primary def system jobs PRIMARY KEY NO NO def system primary def system lease PRIMARY KEY NO NO +def system primary def system locations PRIMARY KEY NO NO def system primary def system namespace PRIMARY KEY NO NO def system primary def system rangelog PRIMARY KEY NO NO def system primary def system settings PRIMARY KEY NO NO @@ -565,6 +568,10 @@ def system lease descID 1 def system lease version 2 def system lease nodeID 3 def system lease expiration 4 +def system locations localityKey 1 +def system locations localityValue 2 +def system locations latitude 3 +def system locations longitude 4 def system namespace parentID 1 def system namespace name 2 def system namespace id 3 @@ -798,6 +805,11 @@ NULL root def system lease GRANT NULL root def system lease INSERT NULL NULL NULL root def system lease SELECT NULL NULL NULL root def system lease UPDATE NULL NULL +NULL root def system locations DELETE NULL NULL +NULL root def system locations GRANT NULL NULL +NULL root def system locations INSERT NULL NULL +NULL root def system locations SELECT NULL NULL +NULL root def system locations UPDATE NULL NULL NULL root def system namespace GRANT NULL NULL NULL root def system namespace SELECT NULL NULL NULL root def system rangelog DELETE NULL NULL diff --git a/pkg/sql/logictest/testdata/logic_test/pg_catalog b/pkg/sql/logictest/testdata/logic_test/pg_catalog index 356eacfec295..bddfd9e8120b 100644 --- a/pkg/sql/logictest/testdata/logic_test/pg_catalog +++ b/pkg/sql/logictest/testdata/logic_test/pg_catalog @@ -500,6 +500,7 @@ indexrelid indrelid indnatts indisunique indisprimary indisexclusion 624432001 3211628798 2 false false false 724530982 908875140 2 true true false 2557995824 780323485 2 false false false +2751284469 3570422629 2 true true false 3505585425 2199392917 2 true true false 3491800018 3270885600 2 true true false 3501101122 3640657984 2 true true false @@ -514,6 +515,7 @@ indexrelid indimmediate indisclustered indisvalid indcheckxmin indisready 624432001 false false true false false 724530982 true false true false false 2557995824 false false true false false +2751284469 true false true false false 3505585425 true false true false false 3491800018 true false true false false 3501101122 true false true false false @@ -528,6 +530,7 @@ indexrelid indrelid indislive indisreplident indkey indcollation indclas 624432001 3211628798 true false 1 2 0 0 0 NULL NULL 724530982 908875140 true false 1 6 0 0 0 NULL NULL 2557995824 780323485 true false 2 3 0 0 0 NULL NULL +2751284469 3570422629 true false 1 2 0 0 0 NULL NULL 3505585425 2199392917 true false 1 2 0 0 0 NULL NULL 3491800018 3270885600 true false 1 7 0 0 0 NULL NULL 3501101122 3640657984 true false 1 2 0 0 0 NULL NULL diff --git a/pkg/sql/logictest/testdata/logic_test/show_source b/pkg/sql/logictest/testdata/logic_test/show_source index cd1136a57453..a0d81e175a46 100644 --- a/pkg/sql/logictest/testdata/logic_test/show_source +++ b/pkg/sql/logictest/testdata/logic_test/show_source @@ -153,6 +153,7 @@ descriptor eventlog jobs lease +locations namespace rangelog settings diff --git a/pkg/sql/logictest/testdata/logic_test/system b/pkg/sql/logictest/testdata/logic_test/system index 87332ebed179..51bc71b79c74 100644 --- a/pkg/sql/logictest/testdata/logic_test/system +++ b/pkg/sql/logictest/testdata/logic_test/system @@ -16,6 +16,7 @@ descriptor eventlog jobs lease +locations namespace rangelog settings @@ -41,6 +42,8 @@ fetched: /namespace/primary/1/'jobs'/id -> 15 output row: [1 'jobs' 15] fetched: /namespace/primary/1/'lease'/id -> 11 output row: [1 'lease' 11] +fetched: /namespace/primary/1/'locations'/id -> 21 +output row: [1 'locations' 21] fetched: /namespace/primary/1/'namespace'/id -> 2 output row: [1 'namespace' 2] fetched: /namespace/primary/1/'rangelog'/id -> 13 @@ -67,6 +70,7 @@ SELECT * FROM system.namespace 1 eventlog 12 1 jobs 15 1 lease 11 +1 locations 21 1 namespace 2 1 rangelog 13 1 settings 6 @@ -92,6 +96,7 @@ SELECT id FROM system.descriptor 15 19 20 +21 50 # Verify we can read "protobuf" columns. @@ -205,6 +210,11 @@ system lease root GRANT system lease root INSERT system lease root SELECT system lease root UPDATE +system locations root DELETE +system locations root GRANT +system locations root INSERT +system locations root SELECT +system locations root UPDATE system namespace root GRANT system namespace root SELECT system rangelog root DELETE diff --git a/pkg/sql/pgwire/pgwire_test.go b/pkg/sql/pgwire/pgwire_test.go index 9a143f8ef603..923aa3b7ec09 100644 --- a/pkg/sql/pgwire/pgwire_test.go +++ b/pkg/sql/pgwire/pgwire_test.go @@ -689,7 +689,7 @@ func TestPGPreparedQuery(t *testing.T) { baseTest.Results("users", "primary", true, 1, "username", "ASC", false, false), }, "SHOW TABLES FROM system": { - baseTest.Results("descriptor").Others(11), + baseTest.Results("descriptor").Others(12), }, "SHOW CONSTRAINTS FROM system.users": { baseTest.Results("users", "primary", "PRIMARY KEY", "username", gosql.NullString{}), diff --git a/pkg/sql/sqlbase/system.go b/pkg/sql/sqlbase/system.go index a676cf85556c..f2df49229612 100644 --- a/pkg/sql/sqlbase/system.go +++ b/pkg/sql/sqlbase/system.go @@ -20,6 +20,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/config" "github.com/cockroachdb/cockroach/pkg/keys" "github.com/cockroachdb/cockroach/pkg/roachpb" + "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/sql/privilege" ) @@ -160,6 +161,18 @@ CREATE TABLE system.table_statistics ( PRIMARY KEY ("tableID", "statisticID"), FAMILY ("tableID", "statisticID", name, "columnIDs", "createdAt", "rowCount", "distinctCount", "nullCount", histogram) );` + + // locations are used to map a locality specified by a node to geographic + // latitude, longitude coordinates, specified as degrees. + LocationsTableSchema = ` +CREATE TABLE system.locations ( + "localityKey" STRING, + "localityValue" STRING, + latitude DECIMAL(18,15) NOT NULL, + longitude DECIMAL(18,15) NOT NULL, + PRIMARY KEY ("localityKey", "localityValue"), + FAMILY ("localityKey", "localityValue", latitude, longitude) +);` ) func pk(name string) IndexDescriptor { @@ -214,6 +227,7 @@ var SystemAllowedPrivileges = map[ID]privilege.Lists{ keys.JobsTableID: {privilege.ReadWriteData}, keys.WebSessionsTableID: {privilege.ReadWriteData}, keys.TableStatisticsTableID: {privilege.ReadWriteData}, + keys.LocationsTableID: {privilege.ReadWriteData}, } // SystemDesiredPrivileges returns the desired privilege list (i.e., the @@ -682,6 +696,48 @@ var ( FormatVersion: InterleavedFormatVersion, NextMutationID: 1, } + + latLonDecimal = ColumnType{ + SemanticType: ColumnType_DECIMAL, + Precision: 18, + Width: 15, + } + + // LocationsTable is the descriptor for the locations table. + LocationsTable = TableDescriptor{ + Name: "locations", + ID: keys.LocationsTableID, + ParentID: 1, + Version: 1, + Columns: []ColumnDescriptor{ + {Name: "localityKey", ID: 1, Type: colTypeString}, + {Name: "localityValue", ID: 2, Type: colTypeString}, + {Name: "latitude", ID: 3, Type: latLonDecimal}, + {Name: "longitude", ID: 4, Type: latLonDecimal}, + }, + NextColumnID: 5, + Families: []ColumnFamilyDescriptor{ + { + Name: "fam_0_localityKey_localityValue_latitude_longitude", + ID: 0, + ColumnNames: []string{"localityKey", "localityValue", "latitude", "longitude"}, + ColumnIDs: []ColumnID{1, 2, 3, 4}, + }, + }, + NextFamilyID: 1, + PrimaryIndex: IndexDescriptor{ + Name: "primary", + ID: 1, + Unique: true, + ColumnNames: []string{"localityKey", "localityValue"}, + ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, + ColumnIDs: []ColumnID{1, 2}, + }, + NextIndexID: 2, + Privileges: NewPrivilegeDescriptor(security.RootUser, SystemDesiredPrivileges(keys.LocationsTableID)), + FormatVersion: InterleavedFormatVersion, + NextMutationID: 1, + } ) // Create the key/value pair for the default zone config entry. diff --git a/pkg/sql/tests/system_table_test.go b/pkg/sql/tests/system_table_test.go index 6a0aec2d3dde..1a2723b5b07a 100644 --- a/pkg/sql/tests/system_table_test.go +++ b/pkg/sql/tests/system_table_test.go @@ -119,6 +119,7 @@ func TestSystemTableLiterals(t *testing.T) { {keys.SettingsTableID, sqlbase.SettingsTableSchema, sqlbase.SettingsTable}, {keys.WebSessionsTableID, sqlbase.WebSessionsTableSchema, sqlbase.WebSessionsTable}, {keys.TableStatisticsTableID, sqlbase.TableStatisticsTableSchema, sqlbase.TableStatisticsTable}, + {keys.LocationsTableID, sqlbase.LocationsTableSchema, sqlbase.LocationsTable}, } { gen, err := sql.CreateTestTableDescriptor( context.TODO(), diff --git a/pkg/sqlmigrations/migrations.go b/pkg/sqlmigrations/migrations.go index bd0695da1ee1..be1858541586 100644 --- a/pkg/sqlmigrations/migrations.go +++ b/pkg/sqlmigrations/migrations.go @@ -99,6 +99,12 @@ var backwardCompatibleMigrations = []migrationDescriptor{ name: "add root user", workFn: addRootUser, }, + { + name: "create system.locations table", + workFn: createLocationsTable, + newDescriptors: 1, + newRanges: 1, + }, } // migrationDescriptor describes a single migration hook that's used to modify @@ -380,6 +386,10 @@ func createTableStatisticsTable(ctx context.Context, r runner) error { return createSystemTable(ctx, r, sqlbase.TableStatisticsTable) } +func createLocationsTable(ctx context.Context, r runner) error { + return createSystemTable(ctx, r, sqlbase.LocationsTable) +} + func createSystemTable(ctx context.Context, r runner, desc sqlbase.TableDescriptor) error { // We install the table at the KV layer so that we can choose a known ID in // the reserved ID space. (The SQL layer doesn't allow this.)