diff --git a/go/cmd/vtctldclient/internal/command/tablets.go b/go/cmd/vtctldclient/internal/command/tablets.go index dcf7e832d54..65aef8298fd 100644 --- a/go/cmd/vtctldclient/internal/command/tablets.go +++ b/go/cmd/vtctldclient/internal/command/tablets.go @@ -25,6 +25,7 @@ import ( "vitess.io/vitess/go/cmd/vtctldclient/cli" "vitess.io/vitess/go/vt/topo/topoproto" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtctldatapb "vitess.io/vitess/go/vt/proto/vtctldata" ) @@ -49,7 +50,7 @@ var ( } // GetTablets makes a GetTablets gRPC call to a vtctld. GetTablets = &cobra.Command{ - Use: "GetTablets [--cell $c1, ...] [--keyspace $ks [--shard $shard]]", + Use: "GetTablets [--strict] [{--cell $c1 [--cell $c2 ...], --keyspace $ks [--shard $shard], --tablet-alias $alias}]", Args: cobra.NoArgs, RunE: commandGetTablets, } @@ -149,7 +150,10 @@ var getTabletsOptions = struct { Keyspace string Shard string + TabletAliasStrings []string + Format string + Strict bool }{} func commandGetTablets(cmd *cobra.Command, args []string) error { @@ -161,6 +165,25 @@ func commandGetTablets(cmd *cobra.Command, args []string) error { return fmt.Errorf("invalid output format, got %s", getTabletsOptions.Format) } + var aliases []*topodatapb.TabletAlias + + if len(getTabletsOptions.TabletAliasStrings) > 0 { + switch { + case getTabletsOptions.Keyspace != "": + return fmt.Errorf("--keyspace (= %s) cannot be passed when using --tablet-alias (= %v)", getTabletsOptions.Keyspace, getTabletsOptions.TabletAliasStrings) + case getTabletsOptions.Shard != "": + return fmt.Errorf("--shard (= %s) cannot be passed when using --tablet-alias (= %v)", getTabletsOptions.Shard, getTabletsOptions.TabletAliasStrings) + case len(getTabletsOptions.Cells) > 0: + return fmt.Errorf("--cell (= %v) cannot be passed when using --tablet-alias (= %v)", getTabletsOptions.Cells, getTabletsOptions.TabletAliasStrings) + } + + var err error + aliases, err = cli.TabletAliasesFromPosArgs(getTabletsOptions.TabletAliasStrings) + if err != nil { + return err + } + } + if getTabletsOptions.Keyspace == "" && getTabletsOptions.Shard != "" { return fmt.Errorf("--shard (= %s) cannot be passed without also passing --keyspace", getTabletsOptions.Shard) } @@ -168,9 +191,11 @@ func commandGetTablets(cmd *cobra.Command, args []string) error { cli.FinishedParsing(cmd) resp, err := client.GetTablets(commandCtx, &vtctldatapb.GetTabletsRequest{ - Cells: getTabletsOptions.Cells, - Keyspace: getTabletsOptions.Keyspace, - Shard: getTabletsOptions.Shard, + TabletAliases: aliases, + Cells: getTabletsOptions.Cells, + Keyspace: getTabletsOptions.Keyspace, + Shard: getTabletsOptions.Shard, + Strict: getTabletsOptions.Strict, }) if err != nil { return err @@ -202,9 +227,11 @@ func init() { Root.AddCommand(GetTablet) - GetTablets.Flags().StringSliceVarP(&getTabletsOptions.Cells, "cell", "c", nil, "list of cells to filter tablets by") - GetTablets.Flags().StringVarP(&getTabletsOptions.Keyspace, "keyspace", "k", "", "keyspace to filter tablets by") - GetTablets.Flags().StringVarP(&getTabletsOptions.Shard, "shard", "s", "", "shard to filter tablets by") + GetTablets.Flags().StringSliceVarP(&getTabletsOptions.TabletAliasStrings, "tablet-alias", "t", nil, "List of tablet aliases to filter by") + GetTablets.Flags().StringSliceVarP(&getTabletsOptions.Cells, "cell", "c", nil, "List of cells to filter tablets by") + GetTablets.Flags().StringVarP(&getTabletsOptions.Keyspace, "keyspace", "k", "", "Keyspace to filter tablets by") + GetTablets.Flags().StringVarP(&getTabletsOptions.Shard, "shard", "s", "", "Shard to filter tablets by") GetTablets.Flags().StringVar(&getTabletsOptions.Format, "format", "awk", "Output format to use; valid choices are (json, awk)") + GetTablets.Flags().BoolVar(&getTabletsOptions.Strict, "strict", false, "Require all cells to return successful tablet data. Without --strict, tablet listings may be partial.") Root.AddCommand(GetTablets) } diff --git a/go/vt/proto/vtctldata/vtctldata.pb.go b/go/vt/proto/vtctldata/vtctldata.pb.go index 77baf0e8ac3..40ec87c07e1 100644 --- a/go/vt/proto/vtctldata/vtctldata.pb.go +++ b/go/vt/proto/vtctldata/vtctldata.pb.go @@ -2921,10 +2921,21 @@ type GetTabletsRequest struct { // if Keyspace is not set. Shard string `protobuf:"bytes,2,opt,name=shard,proto3" json:"shard,omitempty"` // Cells is an optional set of cells to return tablets for. - Cells []string `protobuf:"bytes,3,rep,name=cells,proto3" json:"cells,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Cells []string `protobuf:"bytes,3,rep,name=cells,proto3" json:"cells,omitempty"` + // Strict specifies how the server should treat failures from individual + // cells. + // + // When false (the default), GetTablets will return data from any cells that + // return successfully, but will fail the request if all cells fail. When + // true, any individual cell can fail the full request. + Strict bool `protobuf:"varint,4,opt,name=strict,proto3" json:"strict,omitempty"` + // TabletAliases is an optional list of tablet aliases to fetch Tablet objects + // for. If specified, Keyspace, Shard, and Cells are ignored, and tablets are + // looked up by their respective aliases' Cells directly. + TabletAliases []*topodata.TabletAlias `protobuf:"bytes,5,rep,name=tablet_aliases,json=tabletAliases,proto3" json:"tablet_aliases,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *GetTabletsRequest) Reset() { *m = GetTabletsRequest{} } @@ -2981,6 +2992,20 @@ func (m *GetTabletsRequest) GetCells() []string { return nil } +func (m *GetTabletsRequest) GetStrict() bool { + if m != nil { + return m.Strict + } + return false +} + +func (m *GetTabletsRequest) GetTabletAliases() []*topodata.TabletAlias { + if m != nil { + return m.TabletAliases + } + return nil +} + type GetTabletsResponse struct { Tablets []*topodata.Tablet `protobuf:"bytes,1,rep,name=tablets,proto3" json:"tablets,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -4191,177 +4216,178 @@ func init() { func init() { proto.RegisterFile("vtctldata.proto", fileDescriptor_f41247b323a1ab2e) } var fileDescriptor_f41247b323a1ab2e = []byte{ - // 2712 bytes of a gzipped FileDescriptorProto + // 2731 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x1a, 0x4d, 0x6f, 0x1b, 0xc7, - 0xb5, 0x4b, 0x52, 0x94, 0xf8, 0xf8, 0x21, 0x69, 0x44, 0x49, 0x1b, 0x26, 0x56, 0x94, 0x75, 0xec, - 0xa8, 0x4e, 0x4c, 0xc5, 0x4a, 0x62, 0x18, 0x4e, 0xd2, 0xda, 0x96, 0x28, 0x43, 0x8e, 0xa3, 0xaa, - 0x4b, 0x55, 0x41, 0x53, 0xa0, 0xdb, 0x11, 0x39, 0xa2, 0x17, 0x5a, 0xee, 0x32, 0x3b, 0x43, 0x4a, - 0x4c, 0x0f, 0xbd, 0xb4, 0x87, 0x00, 0x05, 0x7a, 0x2d, 0x10, 0x14, 0xe8, 0xa9, 0x28, 0xfa, 0x03, - 0x02, 0xb4, 0x28, 0x7a, 0x2c, 0x7a, 0xe8, 0xa1, 0xd7, 0xde, 0x0a, 0xf7, 0x67, 0xf4, 0x52, 0xcc, - 0xd7, 0x72, 0xb9, 0xfc, 0xb0, 0x2c, 0x1b, 0x28, 0x7a, 0xd2, 0xce, 0x9b, 0xf7, 0xe6, 0xbd, 0x79, - 0xdf, 0x6f, 0x28, 0x98, 0xef, 0xb1, 0x06, 0xf3, 0x9a, 0x98, 0xe1, 0x6a, 0x27, 0x0c, 0x58, 0x80, - 0x72, 0x11, 0xa0, 0xb2, 0x70, 0xec, 0xfa, 0x5e, 0xd0, 0x1a, 0x6c, 0x56, 0x8a, 0x5e, 0xd0, 0xea, - 0x32, 0xd7, 0x53, 0xcb, 0x52, 0xbb, 0x4f, 0xbf, 0xf0, 0x1a, 0x4c, 0xaf, 0x97, 0x43, 0xd2, 0xf1, - 0xdc, 0x06, 0x66, 0x6e, 0xe0, 0xc7, 0xa8, 0x56, 0x19, 0x3e, 0xf6, 0x08, 0x6b, 0x63, 0x1f, 0xb7, - 0x48, 0x18, 0xdb, 0x28, 0xb1, 0xa0, 0x13, 0xc4, 0x8f, 0xef, 0xd1, 0xc6, 0x13, 0xd2, 0xd6, 0xcb, - 0x42, 0x8f, 0x31, 0xb7, 0x4d, 0xe4, 0xca, 0xfa, 0x0c, 0x2a, 0xb5, 0x73, 0xd2, 0xe8, 0x32, 0x72, - 0xc4, 0x25, 0xdc, 0x0e, 0xda, 0x6d, 0xec, 0x37, 0x6d, 0xf2, 0x45, 0x97, 0x50, 0x86, 0x10, 0x64, - 0x70, 0xd8, 0xa2, 0xa6, 0xb1, 0x9e, 0xde, 0xc8, 0xd9, 0xe2, 0x1b, 0x5d, 0x83, 0x12, 0x6e, 0x70, - 0x59, 0x1c, 0x7e, 0x4c, 0xd0, 0x65, 0x66, 0x6a, 0xdd, 0xd8, 0x48, 0xdb, 0x45, 0x09, 0x3d, 0x94, - 0x40, 0x6b, 0x1b, 0x5e, 0x1d, 0x7b, 0x30, 0xed, 0x04, 0x3e, 0x25, 0xe8, 0x4d, 0x98, 0x21, 0x3d, - 0xe2, 0x33, 0xd3, 0x58, 0x37, 0x36, 0xf2, 0x5b, 0xa5, 0xaa, 0xd6, 0x41, 0x8d, 0x43, 0x6d, 0xb9, - 0x69, 0x7d, 0x65, 0x80, 0x79, 0xc8, 0xaf, 0xf9, 0x29, 0x66, 0x24, 0x74, 0xb1, 0xe7, 0x7e, 0x49, - 0xea, 0x84, 0x31, 0xd7, 0x6f, 0x51, 0xf4, 0x06, 0x14, 0x18, 0x0e, 0x5b, 0x84, 0x39, 0x42, 0x13, - 0xe2, 0xa4, 0x9c, 0x9d, 0x97, 0x30, 0x41, 0x85, 0xde, 0x86, 0x45, 0x1a, 0x74, 0xc3, 0x06, 0x71, - 0xc8, 0x79, 0x27, 0x24, 0x94, 0xba, 0x81, 0x2f, 0xc4, 0xcd, 0xd9, 0x0b, 0x72, 0xa3, 0x16, 0xc1, - 0xd1, 0x15, 0x80, 0x46, 0x48, 0x30, 0x23, 0x4e, 0xb3, 0xe9, 0x99, 0x69, 0x81, 0x95, 0x93, 0x90, - 0x9d, 0xa6, 0x67, 0xfd, 0x33, 0x05, 0x4b, 0xe3, 0xc4, 0xa8, 0xc0, 0xdc, 0x59, 0x10, 0x9e, 0x9e, - 0x78, 0xc1, 0x99, 0x12, 0x21, 0x5a, 0xa3, 0xb7, 0x60, 0x5e, 0xf1, 0x3f, 0x25, 0x7d, 0xda, 0xc1, - 0x0d, 0xa2, 0xb8, 0x97, 0x24, 0xf8, 0x13, 0x05, 0xe5, 0x88, 0xea, 0x2e, 0x11, 0xa2, 0x14, 0xa0, - 0x24, 0xc1, 0x11, 0xe2, 0x75, 0x98, 0xa7, 0x2c, 0xe8, 0x38, 0xf8, 0x84, 0x91, 0xd0, 0x69, 0x04, - 0x9d, 0xbe, 0x99, 0x59, 0x37, 0x36, 0xe6, 0xec, 0x22, 0x07, 0xdf, 0xe7, 0xd0, 0xed, 0xa0, 0xd3, - 0x47, 0x8f, 0xa0, 0x24, 0xb4, 0xe2, 0x50, 0x25, 0xa7, 0x39, 0xb3, 0x9e, 0xde, 0xc8, 0x6f, 0x5d, - 0xad, 0x0e, 0x5c, 0x73, 0x92, 0x66, 0xed, 0xa2, 0x20, 0x8d, 0x6e, 0x88, 0x20, 0xd3, 0x20, 0x9e, - 0x67, 0x66, 0x85, 0x44, 0xe2, 0x5b, 0x2a, 0x9f, 0xfb, 0x9f, 0xc3, 0xfa, 0x1d, 0x42, 0xcd, 0x59, - 0xad, 0x7c, 0x0e, 0x3b, 0xe4, 0x20, 0xf4, 0x6d, 0x58, 0x20, 0xe7, 0x8c, 0x84, 0x3e, 0xf6, 0x9c, - 0x86, 0xd7, 0xa5, 0x8c, 0x84, 0xe6, 0x9c, 0x40, 0x9b, 0xd7, 0xf0, 0x6d, 0x09, 0xb6, 0xf6, 0x61, - 0x2e, 0xba, 0x21, 0x82, 0x8c, 0x8f, 0xdb, 0xda, 0x9c, 0xe2, 0x1b, 0x55, 0x61, 0x6e, 0x48, 0x81, - 0xf9, 0x2d, 0x54, 0x8d, 0xbc, 0x5c, 0x53, 0xda, 0x11, 0x8e, 0xf5, 0x63, 0x98, 0xa9, 0x3f, 0xc1, - 0x61, 0x93, 0x1b, 0x27, 0x22, 0x54, 0xc6, 0x39, 0x4d, 0x32, 0x4a, 0xc5, 0x18, 0x5d, 0x83, 0x19, - 0xca, 0x09, 0x85, 0xf6, 0xf3, 0x5b, 0xf3, 0x03, 0x2e, 0xe2, 0x3c, 0x5b, 0xee, 0x5a, 0xbf, 0xcf, - 0xc1, 0xdc, 0x67, 0xda, 0xc8, 0xe3, 0x04, 0xfe, 0x2e, 0x64, 0xa5, 0x85, 0x95, 0xb8, 0x6f, 0xc5, - 0xd4, 0xae, 0x09, 0xab, 0xf6, 0x20, 0xae, 0x1f, 0x07, 0xf2, 0xaf, 0xad, 0xc8, 0xf8, 0x01, 0xd2, - 0xf2, 0x4a, 0x92, 0x8b, 0x1f, 0x20, 0xc9, 0xd0, 0x2d, 0x58, 0x6e, 0xe3, 0x73, 0xa7, 0xe7, 0xc4, - 0xb2, 0x87, 0xe3, 0xe1, 0x96, 0x70, 0x97, 0xb4, 0x8d, 0xda, 0xf8, 0xfc, 0x28, 0x4e, 0x8f, 0x5b, - 0xe8, 0x11, 0x14, 0xc5, 0xf5, 0x1c, 0xca, 0x42, 0x82, 0xdb, 0xda, 0x65, 0xae, 0x8d, 0x63, 0x2d, - 0xd4, 0x51, 0x97, 0x78, 0x35, 0x9f, 0x85, 0x7d, 0xbb, 0x40, 0x63, 0xa0, 0xca, 0x4f, 0x60, 0x71, - 0x04, 0x05, 0x2d, 0x40, 0xfa, 0x94, 0xf4, 0x95, 0xa2, 0xf8, 0x27, 0xfa, 0x00, 0x66, 0x7a, 0xd8, - 0xeb, 0x6a, 0x35, 0xbd, 0xfe, 0x0c, 0x56, 0xb6, 0xc4, 0xbe, 0x9b, 0xba, 0x63, 0x54, 0xf6, 0x60, - 0x69, 0xcc, 0xfd, 0xa7, 0x5a, 0x7c, 0x05, 0xb2, 0x42, 0x48, 0x6a, 0xa6, 0x44, 0x42, 0x53, 0xab, - 0xca, 0x1f, 0x0d, 0xc8, 0xc7, 0xb8, 0xa0, 0xf7, 0x61, 0x56, 0xab, 0xc0, 0x10, 0x2a, 0xa8, 0x8c, - 0x95, 0x4b, 0x8a, 0xa4, 0x51, 0xd1, 0x2e, 0x8f, 0x61, 0x11, 0x12, 0x8d, 0xc0, 0x67, 0x61, 0xe0, - 0x49, 0x36, 0xf9, 0xad, 0x2b, 0x09, 0x2f, 0x92, 0x81, 0xc7, 0xb6, 0x25, 0x96, 0x2d, 0x03, 0x55, - 0x2f, 0x29, 0x7a, 0x07, 0x90, 0x4b, 0x9d, 0x4e, 0xe8, 0xb6, 0x71, 0xd8, 0x77, 0x28, 0x09, 0x7b, - 0xae, 0xdf, 0x12, 0x6e, 0x30, 0x67, 0x2f, 0xb8, 0xf4, 0x40, 0x6e, 0xd4, 0x25, 0xbc, 0xf2, 0x9b, - 0x0c, 0x64, 0x95, 0xd8, 0x25, 0x48, 0xb9, 0x4d, 0x71, 0xe9, 0xb4, 0x9d, 0x72, 0x9b, 0xa8, 0xac, - 0x9d, 0x59, 0x7a, 0xb8, 0x5c, 0xa0, 0x9b, 0xdc, 0xb3, 0x38, 0x43, 0xe5, 0x59, 0xcb, 0x03, 0xe9, - 0xa4, 0x5c, 0xf7, 0x3d, 0x17, 0x53, 0x5b, 0x21, 0xa1, 0x8f, 0xa1, 0x28, 0x0b, 0x96, 0xa3, 0x1c, - 0x3a, 0x23, 0xa8, 0xcc, 0x6a, 0xac, 0x8c, 0x3d, 0x10, 0x9f, 0x75, 0xb1, 0x6f, 0x17, 0x8e, 0x63, - 0x2b, 0x6e, 0x8e, 0x4e, 0x40, 0x5d, 0x6e, 0x1a, 0x73, 0x46, 0x9a, 0x43, 0xaf, 0xd1, 0x55, 0x10, - 0x49, 0xcb, 0x89, 0x10, 0x64, 0x82, 0x29, 0x70, 0xe0, 0x81, 0x46, 0xe2, 0x97, 0x60, 0x98, 0x11, - 0x95, 0x61, 0xe4, 0x02, 0xad, 0xc2, 0x6c, 0xf3, 0xd8, 0x11, 0x61, 0x27, 0x53, 0x4a, 0xb6, 0x79, - 0xbc, 0xcf, 0x03, 0xef, 0x3e, 0x2c, 0xb3, 0x10, 0xfb, 0x34, 0x56, 0xa2, 0x28, 0xc3, 0xed, 0x8e, - 0x99, 0x13, 0x62, 0x17, 0xaa, 0xaa, 0xfa, 0xf1, 0x32, 0x65, 0x97, 0x63, 0xa8, 0x87, 0x1a, 0x13, - 0x6d, 0x42, 0x81, 0xa3, 0x38, 0xdd, 0x4e, 0x13, 0x33, 0xd2, 0x34, 0x61, 0x0c, 0x65, 0x9e, 0x7f, - 0xfe, 0x40, 0x22, 0x20, 0x13, 0x66, 0xdb, 0x84, 0x52, 0xdc, 0x22, 0x66, 0x5e, 0x08, 0xa3, 0x97, - 0xa8, 0x06, 0x79, 0x9e, 0xa2, 0x1d, 0x21, 0x34, 0x35, 0x0b, 0xc2, 0x1d, 0xde, 0x9c, 0xec, 0x4c, - 0x55, 0x9e, 0xbb, 0xeb, 0x1c, 0xd9, 0x86, 0x86, 0xfe, 0xa4, 0x95, 0xbb, 0x90, 0x8b, 0x36, 0xb8, - 0x42, 0xe2, 0xf5, 0x4e, 0x2e, 0xb8, 0x42, 0x3c, 0x4c, 0x99, 0xd3, 0x39, 0x55, 0xd6, 0xce, 0xf2, - 0xe5, 0xc1, 0xa9, 0xf5, 0xb5, 0x01, 0xab, 0xdb, 0x4f, 0xb0, 0xdf, 0x22, 0x87, 0x51, 0x6e, 0xd6, - 0xe5, 0xfd, 0x4e, 0x94, 0xc4, 0x31, 0xb7, 0xb9, 0xaa, 0xc5, 0x13, 0x1c, 0x42, 0xe5, 0x76, 0xb1, - 0x40, 0x37, 0x85, 0xfe, 0x79, 0xea, 0x17, 0xec, 0x4a, 0x5b, 0xe5, 0x24, 0x91, 0xe0, 0x93, 0x6d, - 0x1e, 0xf3, 0xbf, 0xc2, 0x5c, 0x61, 0xdf, 0x09, 0xbb, 0xbe, 0xf2, 0xe3, 0x6c, 0x33, 0xec, 0xdb, - 0x5d, 0xdf, 0xfa, 0x9d, 0x01, 0xe6, 0xa8, 0x74, 0xaa, 0x47, 0xf8, 0x00, 0x8a, 0xc7, 0xe4, 0x24, - 0x08, 0x89, 0xa3, 0x1c, 0x56, 0xca, 0xb7, 0x90, 0x64, 0x65, 0x17, 0x24, 0x9a, 0x5c, 0xa1, 0xf7, - 0xa0, 0x20, 0xab, 0xa3, 0xa2, 0x4a, 0x4d, 0xa0, 0xca, 0x0b, 0x2c, 0x45, 0xb4, 0x06, 0xf9, 0x33, - 0x4c, 0x9d, 0x61, 0x29, 0x73, 0x67, 0x98, 0xee, 0x48, 0x41, 0xbf, 0x49, 0xc3, 0xf2, 0xb6, 0xe8, - 0x05, 0xa2, 0x72, 0x33, 0xe8, 0x91, 0x46, 0xd2, 0x7f, 0x19, 0x66, 0x4e, 0x02, 0x9d, 0xfd, 0xe7, - 0x6c, 0xb9, 0x40, 0x9b, 0x50, 0xc6, 0x9e, 0x17, 0x9c, 0x39, 0xa4, 0xdd, 0x61, 0x7d, 0xa7, 0xe7, - 0xc8, 0xbe, 0x4c, 0x31, 0x5b, 0x14, 0x7b, 0x35, 0xbe, 0x75, 0x54, 0x17, 0x1b, 0xe8, 0x5d, 0x28, - 0x8b, 0x98, 0x75, 0xfd, 0x96, 0xd3, 0x08, 0xbc, 0x6e, 0xdb, 0x97, 0x2e, 0x9f, 0x11, 0xac, 0x90, - 0xde, 0xdb, 0x16, 0x5b, 0xc2, 0xfd, 0x1f, 0x8d, 0x52, 0x08, 0x23, 0xcd, 0x08, 0x23, 0x99, 0xa3, - 0x45, 0x73, 0xaf, 0x29, 0x54, 0x9e, 0x38, 0x4b, 0x18, 0xed, 0x1e, 0x14, 0x78, 0xf2, 0x21, 0x4d, - 0xe7, 0x24, 0x0c, 0xda, 0xd4, 0xcc, 0x26, 0x93, 0x99, 0x3e, 0xa3, 0x5a, 0x17, 0x68, 0xbb, 0x61, - 0xd0, 0xb6, 0xf3, 0x34, 0xfa, 0xa6, 0xe8, 0x06, 0x64, 0x04, 0xf7, 0x59, 0xc1, 0x7d, 0x65, 0x94, - 0x52, 0xf0, 0x16, 0x38, 0x3c, 0x19, 0x1c, 0x63, 0x1a, 0x6b, 0x94, 0x64, 0x5c, 0x17, 0x38, 0x30, - 0xea, 0x0d, 0x6e, 0x41, 0x91, 0xfa, 0xb8, 0x43, 0x9f, 0x04, 0x4c, 0x84, 0xf6, 0xd8, 0xa8, 0x2e, - 0x68, 0x14, 0xbe, 0xb2, 0xf6, 0x60, 0x25, 0x69, 0x37, 0xe5, 0x5e, 0x9b, 0x89, 0x4a, 0x91, 0xdf, - 0x5a, 0x8a, 0x45, 0xe6, 0x98, 0xae, 0xe2, 0x97, 0x06, 0x20, 0x79, 0x96, 0x6c, 0x06, 0x94, 0x03, - 0x4c, 0xab, 0x38, 0x57, 0x00, 0x64, 0x49, 0x8d, 0x75, 0x1a, 0x39, 0x01, 0xd9, 0x1f, 0xf2, 0x93, - 0x74, 0xdc, 0x4f, 0xae, 0x41, 0xc9, 0xf5, 0x1b, 0x5e, 0xb7, 0x49, 0x9c, 0x0e, 0x0e, 0x79, 0x93, - 0xac, 0x5a, 0x3c, 0x05, 0x3d, 0x10, 0x40, 0xeb, 0xb7, 0x06, 0x2c, 0x0d, 0x89, 0x73, 0xc9, 0x7b, - 0xa1, 0xeb, 0xf1, 0x3a, 0xc1, 0x23, 0x65, 0x80, 0x1d, 0xef, 0x7a, 0x22, 0x77, 0x74, 0xb0, 0x17, - 0x12, 0xdc, 0xec, 0x3b, 0xe4, 0xdc, 0xa5, 0x8c, 0x2a, 0xe1, 0xa5, 0x0b, 0xdd, 0x97, 0x5b, 0x35, - 0xb1, 0x63, 0x7d, 0x1f, 0x96, 0x77, 0x88, 0x47, 0x46, 0x83, 0x66, 0x9a, 0xce, 0x5e, 0x83, 0x5c, - 0x48, 0x1a, 0xdd, 0x90, 0xba, 0x3d, 0x1d, 0x40, 0x03, 0x80, 0x65, 0xc2, 0x4a, 0xf2, 0x48, 0x79, - 0x6f, 0xeb, 0x17, 0x06, 0x2c, 0xc9, 0x2d, 0x21, 0x35, 0xd5, 0xbc, 0x36, 0xa2, 0xaa, 0x2f, 0x8b, - 0xf9, 0xe8, 0xfd, 0xd4, 0xfe, 0x74, 0xce, 0xbc, 0xf5, 0xe6, 0x53, 0x89, 0xe3, 0x9e, 0x44, 0x45, - 0x59, 0xd9, 0x85, 0x83, 0xf7, 0x4e, 0x54, 0x45, 0xb6, 0x56, 0xa0, 0x3c, 0x2c, 0x86, 0x92, 0xaf, - 0xaf, 0xe1, 0x32, 0xe5, 0x44, 0xf2, 0x7d, 0xa4, 0x5a, 0x75, 0x95, 0x85, 0x89, 0x96, 0x73, 0x42, - 0x1e, 0x2e, 0xc6, 0xf2, 0x30, 0xa1, 0x3c, 0x6e, 0x64, 0x52, 0x51, 0x0d, 0x83, 0x92, 0xbb, 0x20, - 0x80, 0xaa, 0x57, 0xb0, 0x56, 0xb5, 0x1d, 0x22, 0xd6, 0x4a, 0xa6, 0x5f, 0xa5, 0xe0, 0x4a, 0xad, - 0x4d, 0xc2, 0x16, 0xf1, 0x1b, 0x7d, 0x9b, 0x48, 0x77, 0xbb, 0xb0, 0x77, 0x8f, 0x6f, 0x30, 0x6e, - 0x43, 0xde, 0x27, 0x03, 0x79, 0xa6, 0x76, 0x19, 0xe0, 0x13, 0x2d, 0x24, 0xfa, 0x0e, 0xcc, 0xbb, - 0x2d, 0x9f, 0xa7, 0x7b, 0xd5, 0xb2, 0x52, 0x33, 0x33, 0x4d, 0x11, 0x25, 0x89, 0xad, 0x9a, 0x40, - 0x8a, 0x76, 0x60, 0xf9, 0x0c, 0xbb, 0x2c, 0xa2, 0x8e, 0xe6, 0xd3, 0x99, 0xc8, 0xad, 0x45, 0x92, - 0xd8, 0xe9, 0x86, 0xb2, 0x55, 0x5e, 0xe2, 0xe8, 0x9a, 0x5c, 0xcf, 0xad, 0x7f, 0x36, 0x60, 0x6d, - 0x92, 0x46, 0x54, 0x80, 0x3d, 0xbf, 0x4a, 0xee, 0xc1, 0x42, 0x27, 0x0c, 0xda, 0x01, 0x23, 0xcd, - 0x8b, 0xe9, 0x65, 0x5e, 0xa3, 0x6b, 0xe5, 0x5c, 0x87, 0xac, 0x18, 0x89, 0xb5, 0x4e, 0x92, 0x03, - 0xb3, 0xda, 0xb5, 0x3e, 0x82, 0xb5, 0x5d, 0xd7, 0x6f, 0xde, 0xf7, 0x3c, 0xe9, 0x7d, 0x7b, 0xfe, - 0x73, 0x84, 0x9e, 0xf5, 0x17, 0x03, 0x5e, 0x9f, 0x48, 0xae, 0x6e, 0xbf, 0x9f, 0x08, 0xa7, 0xdb, - 0xb1, 0x70, 0x7a, 0x06, 0xad, 0x0c, 0x37, 0x35, 0x2f, 0xe8, 0xe6, 0xfb, 0x13, 0xd5, 0x7b, 0x4f, - 0x9c, 0x11, 0xae, 0x0f, 0xcf, 0x08, 0x63, 0xd2, 0x53, 0x34, 0x14, 0x58, 0x35, 0x58, 0x7c, 0x48, - 0xd8, 0x03, 0xdc, 0x38, 0xed, 0x76, 0xe8, 0xa5, 0x5d, 0xd8, 0xda, 0x01, 0x14, 0x3f, 0x46, 0xdd, - 0xbc, 0x0a, 0xb3, 0xc7, 0x12, 0xa4, 0xae, 0x5e, 0xae, 0x46, 0x4f, 0x35, 0x12, 0x77, 0xcf, 0x3f, - 0x09, 0x6c, 0x8d, 0x64, 0xbd, 0x02, 0xab, 0x0f, 0x09, 0xdb, 0x26, 0x9e, 0xc7, 0xe1, 0x3c, 0xe1, - 0x6b, 0x91, 0xac, 0x77, 0xc1, 0x1c, 0xdd, 0x52, 0x6c, 0xca, 0x30, 0xc3, 0xab, 0x85, 0x7e, 0x75, - 0x91, 0x0b, 0x6b, 0x43, 0x88, 0xa4, 0x29, 0x62, 0xcd, 0x87, 0x18, 0xcd, 0x8d, 0xc1, 0x68, 0x6e, - 0xed, 0xc2, 0xd2, 0x10, 0x66, 0x54, 0x16, 0x72, 0x7c, 0xdb, 0x71, 0xfd, 0x93, 0x40, 0xd5, 0x85, - 0xd8, 0x10, 0x1d, 0xa1, 0xcf, 0x35, 0xd4, 0x17, 0xcf, 0xb4, 0xea, 0x1c, 0xaa, 0x92, 0x8d, 0x96, - 0xfe, 0x1b, 0x23, 0xba, 0xd9, 0x60, 0x4b, 0xb1, 0xd9, 0x83, 0xd9, 0xe1, 0x34, 0xb6, 0x19, 0xb3, - 0xd7, 0x04, 0xa2, 0xaa, 0x5a, 0x4b, 0xc7, 0xd0, 0xf4, 0x95, 0x03, 0x28, 0xc4, 0x37, 0xc6, 0xb8, - 0xc6, 0x8d, 0x61, 0xd7, 0x28, 0x0f, 0xdf, 0x47, 0xb2, 0x89, 0xbb, 0xc7, 0xb2, 0x50, 0x8d, 0x76, - 0xcb, 0xe8, 0x3e, 0x7b, 0x50, 0x1e, 0x06, 0xab, 0xbb, 0xdc, 0x82, 0x9c, 0x76, 0x14, 0x7d, 0x9b, - 0xb1, 0xa5, 0x74, 0x80, 0x65, 0xbd, 0x2b, 0xcc, 0xf4, 0x3c, 0x31, 0xb7, 0x3b, 0x24, 0xd3, 0xe5, - 0xbb, 0x93, 0x9f, 0xa7, 0x60, 0xe1, 0x21, 0x61, 0xb2, 0x75, 0x7c, 0xf1, 0x0e, 0x7f, 0x45, 0x8d, - 0x89, 0xd1, 0xac, 0x2c, 0x57, 0xbc, 0x39, 0x21, 0xe7, 0xb2, 0x39, 0x51, 0xfb, 0x69, 0xb1, 0x5f, - 0x54, 0xd0, 0x43, 0x89, 0x76, 0x15, 0x74, 0xb7, 0xe2, 0xf4, 0x5c, 0x72, 0x46, 0x55, 0xa9, 0x2c, - 0x28, 0xe0, 0x11, 0x87, 0xa1, 0x0d, 0x58, 0x90, 0x8f, 0x54, 0xc2, 0xc5, 0x9d, 0xc0, 0xf7, 0xfa, - 0x22, 0x59, 0xcf, 0xa9, 0x99, 0x58, 0xc4, 0xc5, 0xf7, 0x7c, 0xaf, 0x3f, 0xc0, 0xa4, 0xee, 0x97, - 0x1a, 0x33, 0x1b, 0xc3, 0xac, 0x73, 0x30, 0xc7, 0xb4, 0x0e, 0x44, 0x06, 0xd0, 0x5a, 0x50, 0xca, - 0xfc, 0x10, 0xb2, 0xaa, 0xd7, 0x96, 0x0a, 0xb8, 0x5a, 0x1d, 0x7d, 0x3c, 0x95, 0x24, 0x3b, 0xe4, - 0xc4, 0xf5, 0x5d, 0xf5, 0x14, 0x23, 0x20, 0xd6, 0x63, 0x98, 0xe7, 0x27, 0xbe, 0x9c, 0x96, 0xcf, - 0xba, 0x2b, 0xad, 0x34, 0x54, 0x50, 0xa2, 0x06, 0xcc, 0x98, 0xda, 0x80, 0x59, 0x8f, 0x44, 0x44, - 0xd6, 0xc3, 0x5e, 0xd2, 0x83, 0x9f, 0x95, 0xe2, 0x78, 0x4c, 0x6b, 0x43, 0xca, 0x85, 0xf5, 0x77, - 0x19, 0xc3, 0xc3, 0x87, 0x29, 0x79, 0x7e, 0x08, 0x45, 0x1a, 0xf6, 0x9c, 0xa4, 0xef, 0xbf, 0x3f, - 0x1c, 0xc9, 0xe3, 0x48, 0xab, 0x71, 0xa0, 0x7e, 0x17, 0x8a, 0x81, 0x2a, 0x47, 0xb0, 0x38, 0x82, - 0x32, 0x26, 0xb0, 0xdf, 0x1e, 0x0e, 0xec, 0x98, 0xc3, 0xc6, 0xa8, 0xe3, 0x91, 0x7d, 0x43, 0x84, - 0x70, 0x3d, 0xec, 0x1d, 0x0d, 0x07, 0xc0, 0xb8, 0x04, 0xb9, 0x0f, 0xcb, 0x09, 0xdc, 0x68, 0xe0, - 0xe4, 0xc2, 0x0e, 0x06, 0xb3, 0x28, 0xee, 0xd4, 0x03, 0x7a, 0x8c, 0x04, 0x68, 0xf4, 0x6d, 0x3d, - 0x16, 0x26, 0x55, 0x53, 0xe5, 0x8b, 0x06, 0x9e, 0xf5, 0xb1, 0x70, 0x60, 0x7d, 0x9a, 0x92, 0x6c, - 0x23, 0x7a, 0xb4, 0x99, 0x34, 0x03, 0xab, 0x7d, 0xeb, 0x47, 0x31, 0xf2, 0xcb, 0x57, 0xc0, 0x81, - 0xd3, 0xa4, 0xe3, 0x4e, 0x73, 0x4f, 0x64, 0xb7, 0x44, 0x13, 0x89, 0x6e, 0xc0, 0xac, 0x64, 0x3e, - 0xe8, 0xb0, 0x93, 0xd2, 0x69, 0x04, 0x6b, 0x53, 0x88, 0x97, 0x30, 0xd2, 0xb4, 0xf4, 0xf8, 0x40, - 0xb0, 0x4c, 0x5a, 0xea, 0x1d, 0x98, 0x4b, 0x58, 0x69, 0x31, 0xb2, 0x52, 0xe4, 0x1e, 0xb3, 0x3d, - 0x65, 0x20, 0x5b, 0xa4, 0x58, 0xfd, 0xd6, 0x72, 0x21, 0xad, 0xbc, 0x0e, 0x79, 0xdc, 0x60, 0x6e, - 0x8f, 0xc8, 0x5c, 0x23, 0x9b, 0x6a, 0x90, 0x20, 0x91, 0x67, 0x64, 0xcd, 0x88, 0x9d, 0x39, 0xa8, - 0x19, 0xfa, 0xf9, 0x7f, 0x5c, 0xcd, 0xd0, 0x04, 0xf6, 0x00, 0xcb, 0xfa, 0x8f, 0x01, 0xab, 0x7b, - 0xbe, 0x2b, 0x93, 0x82, 0x6a, 0xf8, 0x2e, 0x6f, 0x39, 0x1b, 0x2a, 0xfa, 0xed, 0x90, 0x78, 0xa4, - 0xa1, 0x7e, 0x1d, 0xd1, 0x7e, 0x38, 0xb5, 0xeb, 0x5c, 0x55, 0x84, 0x35, 0x4e, 0x17, 0xdb, 0x18, - 0xcc, 0xa9, 0x99, 0xf8, 0x9c, 0xfa, 0x72, 0x1a, 0xee, 0x07, 0x60, 0x8e, 0x5e, 0x3e, 0x4a, 0x8c, - 0xba, 0xeb, 0x35, 0xa6, 0x76, 0xbd, 0x5f, 0xa5, 0xe0, 0xd5, 0x03, 0x0f, 0xfb, 0x3e, 0x69, 0xfe, - 0x8f, 0x87, 0x98, 0xbb, 0x50, 0xc4, 0xbd, 0xc0, 0x1d, 0xb4, 0xf9, 0x99, 0x69, 0x94, 0x05, 0x81, - 0xab, 0x69, 0x5f, 0x8e, 0x3e, 0xff, 0x64, 0xc0, 0x6b, 0xe3, 0x75, 0xf1, 0x7f, 0x30, 0xbe, 0xfc, - 0x0c, 0x5e, 0xb1, 0x49, 0x3b, 0xe8, 0x45, 0xd3, 0x3d, 0xef, 0xe3, 0x2e, 0x62, 0x45, 0x9d, 0xe7, - 0x53, 0xb1, 0xdf, 0xa8, 0xc6, 0xbf, 0xae, 0x0c, 0x0d, 0xf9, 0x99, 0xe4, 0xf3, 0xc2, 0x6b, 0x50, - 0x19, 0x27, 0x80, 0x1a, 0x97, 0xbf, 0x36, 0x60, 0x45, 0x6e, 0x0b, 0x95, 0x5e, 0x54, 0xb8, 0x67, - 0xbc, 0x02, 0x69, 0xd9, 0xd3, 0xe3, 0x64, 0xcf, 0x4c, 0x94, 0x7d, 0x26, 0x29, 0xfb, 0x2b, 0xb0, - 0x3a, 0x22, 0x9c, 0x12, 0x7c, 0x17, 0x96, 0xb5, 0x33, 0x0c, 0xd7, 0xa9, 0x9b, 0x89, 0xc2, 0x32, - 0xfd, 0xd7, 0x00, 0xeb, 0xa7, 0xfc, 0xfe, 0xc3, 0xe7, 0x5c, 0xda, 0xab, 0x36, 0x61, 0xf6, 0x42, - 0xce, 0xa4, 0xb1, 0xac, 0x43, 0x58, 0x57, 0x9e, 0x1c, 0xfd, 0xec, 0xa3, 0x7f, 0x26, 0x78, 0x81, - 0x59, 0xef, 0x0f, 0x69, 0x78, 0x63, 0xca, 0xb1, 0xea, 0x7a, 0xe7, 0x50, 0x8e, 0xff, 0x90, 0x46, - 0x19, 0x66, 0xdd, 0xc1, 0x8c, 0x53, 0x1b, 0xe9, 0xd8, 0xa6, 0x9c, 0x15, 0xff, 0xd9, 0xae, 0xae, - 0xce, 0x91, 0xad, 0xd2, 0x52, 0x38, 0xba, 0x83, 0x3e, 0x07, 0x50, 0x19, 0xbc, 0x8d, 0x3b, 0xea, - 0x17, 0xa5, 0x0f, 0x9f, 0x8b, 0x9f, 0x54, 0xe6, 0xa7, 0xb8, 0x23, 0xb9, 0xe4, 0x98, 0x5e, 0x57, - 0x1c, 0x30, 0x27, 0x09, 0x33, 0xa6, 0x29, 0xbb, 0x39, 0xdc, 0x94, 0xad, 0x56, 0x93, 0xff, 0x98, - 0x20, 0x0f, 0x88, 0xff, 0x48, 0xb7, 0x0f, 0xa5, 0x61, 0xee, 0x17, 0x99, 0xef, 0x93, 0xcd, 0x43, - 0xac, 0xcd, 0xb3, 0xe1, 0x0d, 0x09, 0xac, 0xa9, 0x5f, 0x90, 0xbd, 0xe8, 0x8d, 0x86, 0x34, 0x2f, - 0xe9, 0xd3, 0x7f, 0x35, 0xc0, 0x9a, 0x76, 0xe8, 0xa5, 0x1d, 0xfc, 0xb2, 0x35, 0xe4, 0x36, 0xe4, - 0x03, 0xef, 0x82, 0x15, 0x04, 0x02, 0x4f, 0x27, 0xd9, 0x07, 0x77, 0xfe, 0xf6, 0x74, 0xcd, 0xf8, - 0xc7, 0xd3, 0x35, 0xe3, 0x5f, 0x4f, 0xd7, 0x8c, 0x5f, 0xff, 0x7b, 0xed, 0x5b, 0x9f, 0x5f, 0xef, - 0xb9, 0x8c, 0x50, 0x5a, 0x75, 0x83, 0x4d, 0xf9, 0xb5, 0xd9, 0x0a, 0x36, 0x7b, 0x6c, 0x53, 0xfc, - 0xef, 0xc7, 0x66, 0xe4, 0x43, 0xc7, 0x59, 0x01, 0x78, 0xef, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, - 0x15, 0x67, 0xb5, 0x39, 0xb8, 0x22, 0x00, 0x00, + 0xb5, 0xcb, 0x2f, 0x89, 0x8f, 0x1f, 0x92, 0x56, 0x94, 0xb4, 0x61, 0x6c, 0x59, 0x5e, 0xc7, 0x8e, + 0xea, 0xc4, 0x94, 0xad, 0x24, 0x86, 0xe1, 0x24, 0xad, 0x6d, 0x89, 0x32, 0xe4, 0x38, 0xaa, 0xba, + 0x54, 0x15, 0x34, 0x87, 0x6e, 0x47, 0xe4, 0x88, 0x5e, 0x68, 0xb9, 0xcb, 0xec, 0x0c, 0x29, 0x31, + 0x3d, 0xf4, 0xd2, 0x1e, 0x02, 0x14, 0xe8, 0xb5, 0x40, 0x50, 0xa0, 0xa7, 0xa2, 0xe8, 0xad, 0x97, + 0x00, 0x2d, 0x8a, 0x1e, 0x8b, 0x1e, 0x7a, 0xe8, 0xb5, 0xb7, 0xc2, 0xfd, 0x19, 0xbd, 0x14, 0xf3, + 0xb5, 0x5c, 0x2e, 0x97, 0xb4, 0x2c, 0x1b, 0x28, 0x7a, 0x12, 0xe7, 0xcd, 0x7b, 0xf3, 0xde, 0xbc, + 0xef, 0x37, 0x2b, 0x98, 0xeb, 0xd3, 0x26, 0x75, 0x5b, 0x88, 0xa2, 0x5a, 0x37, 0xf0, 0xa9, 0xaf, + 0xe7, 0x43, 0x40, 0x75, 0xfe, 0xc8, 0xf1, 0x5c, 0xbf, 0x3d, 0xdc, 0xac, 0x96, 0x5c, 0xbf, 0xdd, + 0xa3, 0x8e, 0x2b, 0x97, 0xe5, 0xce, 0x80, 0x7c, 0xe1, 0x36, 0xa9, 0x5a, 0x2f, 0x05, 0xb8, 0xeb, + 0x3a, 0x4d, 0x44, 0x1d, 0xdf, 0x8b, 0x50, 0xad, 0x50, 0x74, 0xe4, 0x62, 0xda, 0x41, 0x1e, 0x6a, + 0xe3, 0x20, 0xb2, 0x51, 0xa6, 0x7e, 0xd7, 0x8f, 0x1e, 0xdf, 0x27, 0xcd, 0x67, 0xb8, 0xa3, 0x96, + 0xc5, 0x3e, 0xa5, 0x4e, 0x07, 0x8b, 0x95, 0xf9, 0x19, 0x54, 0xeb, 0x67, 0xb8, 0xd9, 0xa3, 0xf8, + 0x90, 0x49, 0xb8, 0xe5, 0x77, 0x3a, 0xc8, 0x6b, 0x59, 0xf8, 0x8b, 0x1e, 0x26, 0x54, 0xd7, 0x21, + 0x83, 0x82, 0x36, 0x31, 0xb4, 0xb5, 0xf4, 0x7a, 0xde, 0xe2, 0xbf, 0xf5, 0xeb, 0x50, 0x46, 0x4d, + 0x26, 0x8b, 0xcd, 0x8e, 0xf1, 0x7b, 0xd4, 0x48, 0xad, 0x69, 0xeb, 0x69, 0xab, 0x24, 0xa0, 0x07, + 0x02, 0x68, 0x6e, 0xc1, 0x9b, 0x89, 0x07, 0x93, 0xae, 0xef, 0x11, 0xac, 0xbf, 0x05, 0x59, 0xdc, + 0xc7, 0x1e, 0x35, 0xb4, 0x35, 0x6d, 0xbd, 0xb0, 0x59, 0xae, 0x29, 0x1d, 0xd4, 0x19, 0xd4, 0x12, + 0x9b, 0xe6, 0x57, 0x1a, 0x18, 0x07, 0xec, 0x9a, 0x9f, 0x22, 0x8a, 0x03, 0x07, 0xb9, 0xce, 0x97, + 0xb8, 0x81, 0x29, 0x75, 0xbc, 0x36, 0xd1, 0xaf, 0x42, 0x91, 0xa2, 0xa0, 0x8d, 0xa9, 0xcd, 0x35, + 0xc1, 0x4f, 0xca, 0x5b, 0x05, 0x01, 0xe3, 0x54, 0xfa, 0x3b, 0xb0, 0x40, 0xfc, 0x5e, 0xd0, 0xc4, + 0x36, 0x3e, 0xeb, 0x06, 0x98, 0x10, 0xc7, 0xf7, 0xb8, 0xb8, 0x79, 0x6b, 0x5e, 0x6c, 0xd4, 0x43, + 0xb8, 0x7e, 0x19, 0xa0, 0x19, 0x60, 0x44, 0xb1, 0xdd, 0x6a, 0xb9, 0x46, 0x9a, 0x63, 0xe5, 0x05, + 0x64, 0xbb, 0xe5, 0x9a, 0xff, 0x4c, 0xc1, 0x62, 0x92, 0x18, 0x55, 0x98, 0x3d, 0xf5, 0x83, 0x93, + 0x63, 0xd7, 0x3f, 0x95, 0x22, 0x84, 0x6b, 0xfd, 0x6d, 0x98, 0x93, 0xfc, 0x4f, 0xf0, 0x80, 0x74, + 0x51, 0x13, 0x4b, 0xee, 0x65, 0x01, 0xfe, 0x44, 0x42, 0x19, 0xa2, 0xbc, 0x4b, 0x88, 0x28, 0x04, + 0x28, 0x0b, 0x70, 0x88, 0x78, 0x03, 0xe6, 0x08, 0xf5, 0xbb, 0x36, 0x3a, 0xa6, 0x38, 0xb0, 0x9b, + 0x7e, 0x77, 0x60, 0x64, 0xd6, 0xb4, 0xf5, 0x59, 0xab, 0xc4, 0xc0, 0x0f, 0x19, 0x74, 0xcb, 0xef, + 0x0e, 0xf4, 0x27, 0x50, 0xe6, 0x5a, 0xb1, 0x89, 0x94, 0xd3, 0xc8, 0xae, 0xa5, 0xd7, 0x0b, 0x9b, + 0xd7, 0x6a, 0x43, 0xd7, 0x9c, 0xa4, 0x59, 0xab, 0xc4, 0x49, 0xc3, 0x1b, 0xea, 0x90, 0x69, 0x62, + 0xd7, 0x35, 0x72, 0x5c, 0x22, 0xfe, 0x5b, 0x28, 0x9f, 0xf9, 0x9f, 0x4d, 0x07, 0x5d, 0x4c, 0x8c, + 0x19, 0xa5, 0x7c, 0x06, 0x3b, 0x60, 0x20, 0xfd, 0xdb, 0x30, 0x8f, 0xcf, 0x28, 0x0e, 0x3c, 0xe4, + 0xda, 0x4d, 0xb7, 0x47, 0x28, 0x0e, 0x8c, 0x59, 0x8e, 0x36, 0xa7, 0xe0, 0x5b, 0x02, 0x6c, 0xee, + 0xc1, 0x6c, 0x78, 0x43, 0x1d, 0x32, 0x1e, 0xea, 0x28, 0x73, 0xf2, 0xdf, 0x7a, 0x0d, 0x66, 0x47, + 0x14, 0x58, 0xd8, 0xd4, 0x6b, 0xa1, 0x97, 0x2b, 0x4a, 0x2b, 0xc4, 0x31, 0x7f, 0x04, 0xd9, 0xc6, + 0x33, 0x14, 0xb4, 0x98, 0x71, 0x42, 0x42, 0x69, 0x9c, 0x93, 0x38, 0xa3, 0x54, 0x84, 0xd1, 0x75, + 0xc8, 0x12, 0x46, 0xc8, 0xb5, 0x5f, 0xd8, 0x9c, 0x1b, 0x72, 0xe1, 0xe7, 0x59, 0x62, 0xd7, 0xfc, + 0x5d, 0x1e, 0x66, 0x3f, 0x53, 0x46, 0x4e, 0x12, 0xf8, 0xbb, 0x90, 0x13, 0x16, 0x96, 0xe2, 0xbe, + 0x1d, 0x51, 0xbb, 0x22, 0xac, 0x59, 0xc3, 0xb8, 0x7e, 0xea, 0x8b, 0xbf, 0x96, 0x24, 0x63, 0x07, + 0x08, 0xcb, 0x4b, 0x49, 0xce, 0x7f, 0x80, 0x20, 0xd3, 0xef, 0xc0, 0x52, 0x07, 0x9d, 0xd9, 0x7d, + 0x3b, 0x92, 0x3d, 0x6c, 0x17, 0xb5, 0xb9, 0xbb, 0xa4, 0x2d, 0xbd, 0x83, 0xce, 0x0e, 0xa3, 0xf4, + 0xa8, 0xad, 0x3f, 0x81, 0x12, 0xbf, 0x9e, 0x4d, 0x68, 0x80, 0x51, 0x47, 0xb9, 0xcc, 0xf5, 0x24, + 0xd6, 0x5c, 0x1d, 0x0d, 0x81, 0x57, 0xf7, 0x68, 0x30, 0xb0, 0x8a, 0x24, 0x02, 0xaa, 0xfe, 0x18, + 0x16, 0xc6, 0x50, 0xf4, 0x79, 0x48, 0x9f, 0xe0, 0x81, 0x54, 0x14, 0xfb, 0xa9, 0x7f, 0x00, 0xd9, + 0x3e, 0x72, 0x7b, 0x4a, 0x4d, 0x57, 0x5e, 0xc0, 0xca, 0x12, 0xd8, 0xf7, 0x53, 0xf7, 0xb4, 0xea, + 0x2e, 0x2c, 0x26, 0xdc, 0x7f, 0xaa, 0xc5, 0x97, 0x21, 0xc7, 0x85, 0x24, 0x46, 0x8a, 0x27, 0x34, + 0xb9, 0xaa, 0xfe, 0x51, 0x83, 0x42, 0x84, 0x8b, 0xfe, 0x3e, 0xcc, 0x28, 0x15, 0x68, 0x5c, 0x05, + 0xd5, 0x44, 0xb9, 0x84, 0x48, 0x0a, 0x55, 0xdf, 0x61, 0x31, 0xcc, 0x43, 0xa2, 0xe9, 0x7b, 0x34, + 0xf0, 0x5d, 0xc1, 0xa6, 0xb0, 0x79, 0x39, 0xe6, 0x45, 0x22, 0xf0, 0xe8, 0x96, 0xc0, 0xb2, 0x44, + 0xa0, 0xaa, 0x25, 0xd1, 0xdf, 0x05, 0xdd, 0x21, 0x76, 0x37, 0x70, 0x3a, 0x28, 0x18, 0xd8, 0x04, + 0x07, 0x7d, 0xc7, 0x6b, 0x73, 0x37, 0x98, 0xb5, 0xe6, 0x1d, 0xb2, 0x2f, 0x36, 0x1a, 0x02, 0x5e, + 0xfd, 0x75, 0x06, 0x72, 0x52, 0xec, 0x32, 0xa4, 0x9c, 0x16, 0xbf, 0x74, 0xda, 0x4a, 0x39, 0x2d, + 0xbd, 0xa2, 0x9c, 0x59, 0x78, 0xb8, 0x58, 0xe8, 0xb7, 0x98, 0x67, 0x31, 0x86, 0xd2, 0xb3, 0x96, + 0x86, 0xd2, 0x09, 0xb9, 0x1e, 0xba, 0x0e, 0x22, 0x96, 0x44, 0xd2, 0x3f, 0x86, 0x92, 0x28, 0x58, + 0xb6, 0x74, 0xe8, 0x0c, 0xa7, 0x32, 0x6a, 0x91, 0x32, 0xf6, 0x88, 0xff, 0x6c, 0xf0, 0x7d, 0xab, + 0x78, 0x14, 0x59, 0x31, 0x73, 0x74, 0x7d, 0xe2, 0x30, 0xd3, 0x18, 0x59, 0x61, 0x0e, 0xb5, 0xd6, + 0xaf, 0x01, 0x4f, 0x5a, 0x76, 0x88, 0x20, 0x12, 0x4c, 0x91, 0x01, 0xf7, 0x15, 0x12, 0xbb, 0x04, + 0x45, 0x14, 0xcb, 0x0c, 0x23, 0x16, 0xfa, 0x0a, 0xcc, 0xb4, 0x8e, 0x6c, 0x1e, 0x76, 0x22, 0xa5, + 0xe4, 0x5a, 0x47, 0x7b, 0x2c, 0xf0, 0x1e, 0xc2, 0x12, 0x0d, 0x90, 0x47, 0x22, 0x25, 0x8a, 0x50, + 0xd4, 0xe9, 0x1a, 0x79, 0x2e, 0x76, 0xb1, 0x26, 0xab, 0x1f, 0x2b, 0x53, 0x56, 0x25, 0x82, 0x7a, + 0xa0, 0x30, 0xf5, 0x0d, 0x28, 0x32, 0x14, 0xbb, 0xd7, 0x6d, 0x21, 0x8a, 0x5b, 0x06, 0x24, 0x50, + 0x16, 0xd8, 0xcf, 0x1f, 0x08, 0x04, 0xdd, 0x80, 0x99, 0x0e, 0x26, 0x04, 0xb5, 0xb1, 0x51, 0xe0, + 0xc2, 0xa8, 0xa5, 0x5e, 0x87, 0x02, 0x4b, 0xd1, 0x36, 0x17, 0x9a, 0x18, 0x45, 0xee, 0x0e, 0x6f, + 0x4d, 0x76, 0xa6, 0x1a, 0xcb, 0xdd, 0x0d, 0x86, 0x6c, 0x41, 0x53, 0xfd, 0x24, 0xd5, 0xfb, 0x90, + 0x0f, 0x37, 0x98, 0x42, 0xa2, 0xf5, 0x4e, 0x2c, 0x98, 0x42, 0x5c, 0x44, 0xa8, 0xdd, 0x3d, 0x91, + 0xd6, 0xce, 0xb1, 0xe5, 0xfe, 0x89, 0xf9, 0xb5, 0x06, 0x2b, 0x5b, 0xcf, 0x90, 0xd7, 0xc6, 0x07, + 0x61, 0x6e, 0x56, 0xe5, 0xfd, 0x5e, 0x98, 0xc4, 0x11, 0xb3, 0xb9, 0xac, 0xc5, 0x13, 0x1c, 0x42, + 0xe6, 0x76, 0xbe, 0xd0, 0x6f, 0x71, 0xfd, 0xb3, 0xd4, 0xcf, 0xd9, 0x95, 0x37, 0x2b, 0x71, 0x22, + 0xce, 0x27, 0xd7, 0x3a, 0x62, 0x7f, 0xb9, 0xb9, 0x82, 0x81, 0x1d, 0xf4, 0x3c, 0xe9, 0xc7, 0xb9, + 0x56, 0x30, 0xb0, 0x7a, 0x9e, 0xf9, 0x5b, 0x0d, 0x8c, 0x71, 0xe9, 0x64, 0x8f, 0xf0, 0x01, 0x94, + 0x8e, 0xf0, 0xb1, 0x1f, 0x60, 0x5b, 0x3a, 0xac, 0x90, 0x6f, 0x3e, 0xce, 0xca, 0x2a, 0x0a, 0x34, + 0xb1, 0xd2, 0xdf, 0x83, 0xa2, 0xa8, 0x8e, 0x92, 0x2a, 0x35, 0x81, 0xaa, 0xc0, 0xb1, 0x24, 0xd1, + 0x2a, 0x14, 0x4e, 0x11, 0xb1, 0x47, 0xa5, 0xcc, 0x9f, 0x22, 0xb2, 0x2d, 0x04, 0xfd, 0x26, 0x0d, + 0x4b, 0x5b, 0xbc, 0x17, 0x08, 0xcb, 0xcd, 0xb0, 0x47, 0x1a, 0x4b, 0xff, 0x15, 0xc8, 0x1e, 0xfb, + 0x2a, 0xfb, 0xcf, 0x5a, 0x62, 0xa1, 0x6f, 0x40, 0x05, 0xb9, 0xae, 0x7f, 0x6a, 0xe3, 0x4e, 0x97, + 0x0e, 0xec, 0xbe, 0x2d, 0xfa, 0x32, 0xc9, 0x6c, 0x81, 0xef, 0xd5, 0xd9, 0xd6, 0x61, 0x83, 0x6f, + 0xe8, 0xb7, 0xa1, 0xc2, 0x63, 0xd6, 0xf1, 0xda, 0x76, 0xd3, 0x77, 0x7b, 0x1d, 0x4f, 0xb8, 0x7c, + 0x86, 0xb3, 0xd2, 0xd5, 0xde, 0x16, 0xdf, 0xe2, 0xee, 0xff, 0x64, 0x9c, 0x82, 0x1b, 0x29, 0xcb, + 0x8d, 0x64, 0x8c, 0x17, 0xcd, 0xdd, 0x16, 0x57, 0x79, 0xec, 0x2c, 0x6e, 0xb4, 0x07, 0x50, 0x64, + 0xc9, 0x07, 0xb7, 0xec, 0xe3, 0xc0, 0xef, 0x10, 0x23, 0x17, 0x4f, 0x66, 0xea, 0x8c, 0x5a, 0x83, + 0xa3, 0xed, 0x04, 0x7e, 0xc7, 0x2a, 0x90, 0xf0, 0x37, 0xd1, 0x6f, 0x42, 0x86, 0x73, 0x9f, 0xe1, + 0xdc, 0x97, 0xc7, 0x29, 0x39, 0x6f, 0x8e, 0xc3, 0x92, 0xc1, 0x11, 0x22, 0x91, 0x46, 0x49, 0xc4, + 0x75, 0x91, 0x01, 0xc3, 0xde, 0xe0, 0x0e, 0x94, 0x88, 0x87, 0xba, 0xe4, 0x99, 0x4f, 0x79, 0x68, + 0x27, 0x46, 0x75, 0x51, 0xa1, 0xb0, 0x95, 0xb9, 0x0b, 0xcb, 0x71, 0xbb, 0x49, 0xf7, 0xda, 0x88, + 0x55, 0x8a, 0xc2, 0xe6, 0x62, 0x24, 0x32, 0x13, 0xba, 0x8a, 0x5f, 0x68, 0xa0, 0x8b, 0xb3, 0x44, + 0x33, 0x20, 0x1d, 0x60, 0x5a, 0xc5, 0xb9, 0x0c, 0x20, 0x4a, 0x6a, 0xa4, 0xd3, 0xc8, 0x73, 0xc8, + 0xde, 0x88, 0x9f, 0xa4, 0xa3, 0x7e, 0x72, 0x1d, 0xca, 0x8e, 0xd7, 0x74, 0x7b, 0x2d, 0x6c, 0x77, + 0x51, 0xc0, 0x9a, 0x64, 0xd9, 0xe2, 0x49, 0xe8, 0x3e, 0x07, 0x9a, 0xbf, 0xd1, 0x60, 0x71, 0x44, + 0x9c, 0x0b, 0xde, 0x4b, 0xbf, 0x11, 0xad, 0x13, 0x2c, 0x52, 0x86, 0xd8, 0xd1, 0xae, 0x27, 0x74, + 0x47, 0x1b, 0xb9, 0x01, 0x46, 0xad, 0x81, 0x8d, 0xcf, 0x1c, 0x42, 0x89, 0x14, 0x5e, 0xb8, 0xd0, + 0x43, 0xb1, 0x55, 0xe7, 0x3b, 0xe6, 0xf7, 0x61, 0x69, 0x1b, 0xbb, 0x78, 0x3c, 0x68, 0xa6, 0xe9, + 0xec, 0x12, 0xe4, 0x03, 0xdc, 0xec, 0x05, 0xc4, 0xe9, 0xab, 0x00, 0x1a, 0x02, 0x4c, 0x03, 0x96, + 0xe3, 0x47, 0x8a, 0x7b, 0x9b, 0x3f, 0xd7, 0x60, 0x51, 0x6c, 0x71, 0xa9, 0x89, 0xe2, 0xb5, 0x1e, + 0x56, 0x7d, 0x51, 0xcc, 0xc7, 0xef, 0x27, 0xf7, 0xa7, 0x73, 0x66, 0xad, 0x37, 0x9b, 0x4a, 0x6c, + 0xe7, 0x38, 0x2c, 0xca, 0xd2, 0x2e, 0x0c, 0xbc, 0x7b, 0x2c, 0x2b, 0xb2, 0xb9, 0x0c, 0x95, 0x51, + 0x31, 0xa4, 0x7c, 0x03, 0x05, 0x17, 0x29, 0x27, 0x94, 0xef, 0x23, 0xd9, 0xaa, 0xcb, 0x2c, 0x8c, + 0x95, 0x9c, 0x13, 0xf2, 0x70, 0x29, 0x92, 0x87, 0x31, 0x61, 0x71, 0x23, 0x92, 0x8a, 0x6c, 0x18, + 0xa4, 0xdc, 0x45, 0x0e, 0x94, 0xbd, 0x82, 0xb9, 0xa2, 0xec, 0x10, 0xb2, 0x96, 0x32, 0xfd, 0x32, + 0x05, 0x97, 0xeb, 0x1d, 0x1c, 0xb4, 0xb1, 0xd7, 0x1c, 0x58, 0x58, 0xb8, 0xdb, 0xb9, 0xbd, 0x3b, + 0xb9, 0xc1, 0xb8, 0x0b, 0x05, 0x0f, 0x0f, 0xe5, 0x99, 0xda, 0x65, 0x80, 0x87, 0x95, 0x90, 0xfa, + 0x77, 0x60, 0xce, 0x69, 0x7b, 0x2c, 0xdd, 0xcb, 0x96, 0x95, 0x18, 0x99, 0x69, 0x8a, 0x28, 0x0b, + 0x6c, 0xd9, 0x04, 0x12, 0x7d, 0x1b, 0x96, 0x4e, 0x91, 0x43, 0x43, 0xea, 0x70, 0x3e, 0xcd, 0x86, + 0x6e, 0xcd, 0x93, 0xc4, 0x76, 0x2f, 0x10, 0xad, 0xf2, 0x22, 0x43, 0x57, 0xe4, 0x6a, 0x6e, 0xfd, + 0xb3, 0x06, 0xab, 0x93, 0x34, 0x22, 0x03, 0xec, 0xe5, 0x55, 0xf2, 0x00, 0xe6, 0xbb, 0x81, 0xdf, + 0xf1, 0x29, 0x6e, 0x9d, 0x4f, 0x2f, 0x73, 0x0a, 0x5d, 0x29, 0xe7, 0x06, 0xe4, 0xf8, 0x48, 0xac, + 0x74, 0x12, 0x1f, 0x98, 0xe5, 0xae, 0xf9, 0x11, 0xac, 0xee, 0x38, 0x5e, 0xeb, 0xa1, 0xeb, 0x0a, + 0xef, 0xdb, 0xf5, 0x5e, 0x22, 0xf4, 0xcc, 0xbf, 0x68, 0x70, 0x65, 0x22, 0xb9, 0xbc, 0xfd, 0x5e, + 0x2c, 0x9c, 0xee, 0x46, 0xc2, 0xe9, 0x05, 0xb4, 0x22, 0xdc, 0xe4, 0xbc, 0xa0, 0x9a, 0xef, 0x4f, + 0x64, 0xef, 0x3d, 0x71, 0x46, 0xb8, 0x31, 0x3a, 0x23, 0x24, 0xa4, 0xa7, 0x70, 0x28, 0x30, 0xeb, + 0xb0, 0xf0, 0x18, 0xd3, 0x47, 0xa8, 0x79, 0xd2, 0xeb, 0x92, 0x0b, 0xbb, 0xb0, 0xb9, 0x0d, 0x7a, + 0xf4, 0x18, 0x79, 0xf3, 0x1a, 0xcc, 0x1c, 0x09, 0x90, 0xbc, 0x7a, 0xa5, 0x16, 0x3e, 0xd5, 0x08, + 0xdc, 0x5d, 0xef, 0xd8, 0xb7, 0x14, 0x92, 0xf9, 0x06, 0xac, 0x3c, 0xc6, 0x74, 0x0b, 0xbb, 0x2e, + 0x83, 0xb3, 0x84, 0xaf, 0x44, 0x32, 0x6f, 0x83, 0x31, 0xbe, 0x25, 0xd9, 0x54, 0x20, 0xcb, 0xaa, + 0x85, 0x7a, 0x75, 0x11, 0x0b, 0x73, 0x9d, 0x8b, 0xa4, 0x28, 0x22, 0xcd, 0x07, 0x1f, 0xcd, 0xb5, + 0xe1, 0x68, 0x6e, 0xee, 0xc0, 0xe2, 0x08, 0x66, 0x58, 0x16, 0xf2, 0x6c, 0xdb, 0x76, 0xbc, 0x63, + 0x5f, 0xd6, 0x85, 0xc8, 0x10, 0x1d, 0xa2, 0xcf, 0x36, 0xe5, 0x2f, 0x96, 0x69, 0xe5, 0x39, 0x44, + 0x26, 0x1b, 0x25, 0xfd, 0x37, 0x5a, 0x78, 0xb3, 0xe1, 0x96, 0x64, 0xb3, 0x0b, 0x33, 0xa3, 0x69, + 0x6c, 0x23, 0x62, 0xaf, 0x09, 0x44, 0x35, 0xb9, 0x16, 0x8e, 0xa1, 0xe8, 0xab, 0xfb, 0x50, 0x8c, + 0x6e, 0x24, 0xb8, 0xc6, 0xcd, 0x51, 0xd7, 0xa8, 0x8c, 0xde, 0x47, 0xb0, 0x89, 0xba, 0xc7, 0x12, + 0x57, 0x8d, 0x72, 0xcb, 0xf0, 0x3e, 0xbb, 0x50, 0x19, 0x05, 0xcb, 0xbb, 0xdc, 0x81, 0xbc, 0x72, + 0x14, 0x75, 0x9b, 0xc4, 0x52, 0x3a, 0xc4, 0x32, 0x6f, 0x73, 0x33, 0xbd, 0x4c, 0xcc, 0xed, 0x8c, + 0xc8, 0x74, 0xf1, 0xee, 0xe4, 0x67, 0x29, 0x98, 0x7f, 0x8c, 0xa9, 0x68, 0x1d, 0x5f, 0xbd, 0xc3, + 0x5f, 0x96, 0x63, 0x62, 0x38, 0x2b, 0x8b, 0x15, 0x6b, 0x4e, 0xf0, 0x99, 0x68, 0x4e, 0xe4, 0x7e, + 0x9a, 0xef, 0x97, 0x24, 0xf4, 0x40, 0xa0, 0x5d, 0x03, 0xd5, 0xad, 0xd8, 0x7d, 0x07, 0x9f, 0x12, + 0x59, 0x2a, 0x8b, 0x12, 0x78, 0xc8, 0x60, 0xfa, 0x3a, 0xcc, 0x8b, 0x47, 0x2a, 0xee, 0xe2, 0xb6, + 0xef, 0xb9, 0x03, 0x9e, 0xac, 0x67, 0xe5, 0x4c, 0xcc, 0xe3, 0xe2, 0x7b, 0x9e, 0x3b, 0x18, 0x62, + 0x12, 0xe7, 0x4b, 0x85, 0x99, 0x8b, 0x60, 0x36, 0x18, 0x98, 0x61, 0x9a, 0xfb, 0x3c, 0x03, 0x28, + 0x2d, 0x48, 0x65, 0x7e, 0x08, 0x39, 0xd9, 0x6b, 0x0b, 0x05, 0x5c, 0xab, 0x8d, 0x3f, 0x9e, 0x0a, + 0x92, 0x6d, 0x7c, 0xec, 0x78, 0x8e, 0x7c, 0x8a, 0xe1, 0x10, 0xf3, 0x29, 0xcc, 0xb1, 0x13, 0x5f, + 0x4f, 0xcb, 0x67, 0xde, 0x17, 0x56, 0x1a, 0x29, 0x28, 0x61, 0x03, 0xa6, 0x4d, 0x6d, 0xc0, 0xcc, + 0x27, 0x3c, 0x22, 0x1b, 0x41, 0x3f, 0xee, 0xc1, 0x2f, 0x4a, 0x71, 0x2c, 0xa6, 0x95, 0x21, 0xc5, + 0xc2, 0xfc, 0xbb, 0x88, 0xe1, 0xd1, 0xc3, 0xa4, 0x3c, 0x3f, 0x84, 0x12, 0x09, 0xfa, 0x76, 0xdc, + 0xf7, 0xdf, 0x1f, 0x8d, 0xe4, 0x24, 0xd2, 0x5a, 0x14, 0xa8, 0xde, 0x85, 0x22, 0xa0, 0xea, 0x21, + 0x2c, 0x8c, 0xa1, 0x24, 0x04, 0xf6, 0x3b, 0xa3, 0x81, 0x1d, 0x71, 0xd8, 0x08, 0x75, 0x34, 0xb2, + 0x6f, 0xf2, 0x10, 0x6e, 0x04, 0xfd, 0xc3, 0xd1, 0x00, 0x48, 0x4a, 0x90, 0x7b, 0xb0, 0x14, 0xc3, + 0x0d, 0x07, 0x4e, 0x26, 0xec, 0x70, 0x30, 0x0b, 0xe3, 0x4e, 0x3e, 0xa0, 0x47, 0x48, 0x80, 0x84, + 0xbf, 0xcd, 0xa7, 0xdc, 0xa4, 0x72, 0xaa, 0x7c, 0xd5, 0xc0, 0x33, 0x3f, 0xe6, 0x0e, 0xac, 0x4e, + 0x93, 0x92, 0xad, 0x87, 0x8f, 0x36, 0x93, 0x66, 0x60, 0xb9, 0x6f, 0xfe, 0x41, 0x8b, 0xd0, 0x5f, + 0xbc, 0x04, 0x0e, 0xbd, 0x26, 0x1d, 0xf1, 0x1a, 0xfe, 0x82, 0x46, 0x03, 0xa7, 0xa9, 0x46, 0x12, + 0xb9, 0x4a, 0xe8, 0x61, 0xb3, 0xe7, 0xef, 0x61, 0xcd, 0x07, 0x3c, 0x69, 0xc6, 0x7a, 0x53, 0xfd, + 0x26, 0xcc, 0x08, 0xb4, 0x61, 0xe3, 0x1e, 0xbf, 0xb4, 0x42, 0x30, 0x37, 0xf8, 0xa5, 0x63, 0xb6, + 0x9f, 0x96, 0x75, 0x1f, 0x71, 0x96, 0x71, 0x07, 0x78, 0x17, 0x66, 0x63, 0xc6, 0x5f, 0x08, 0x8d, + 0x1f, 0x7a, 0xdd, 0x4c, 0x5f, 0xda, 0xdd, 0xe2, 0x99, 0x5b, 0x3d, 0xe1, 0x9c, 0x4b, 0xd7, 0x57, + 0xa0, 0x80, 0x9a, 0xd4, 0xe9, 0x63, 0x91, 0xc2, 0x44, 0xaf, 0x0e, 0x02, 0xc4, 0xd3, 0x97, 0x28, + 0x45, 0x91, 0x33, 0x87, 0xa5, 0x48, 0x7d, 0x55, 0x48, 0x2a, 0x45, 0x8a, 0xc0, 0x1a, 0x62, 0x99, + 0xff, 0xd1, 0x60, 0x65, 0xd7, 0x73, 0x44, 0xae, 0x91, 0x7d, 0xe4, 0xc5, 0xfd, 0xc1, 0x82, 0xaa, + 0x7a, 0x92, 0xc4, 0x2e, 0x6e, 0xca, 0x8f, 0x2e, 0xca, 0xbd, 0xa7, 0x36, 0xb3, 0x2b, 0x92, 0xb0, + 0xce, 0xe8, 0x22, 0x1b, 0xc3, 0xf1, 0x37, 0x13, 0x1d, 0x7f, 0x5f, 0x4f, 0x1f, 0xff, 0x08, 0x8c, + 0xf1, 0xcb, 0x87, 0xf9, 0x56, 0x35, 0xd3, 0xda, 0xd4, 0x66, 0xfa, 0xab, 0x14, 0xbc, 0xb9, 0xef, + 0x22, 0xcf, 0xc3, 0xad, 0xff, 0xf1, 0x6c, 0x74, 0x1f, 0x4a, 0xa8, 0xef, 0x3b, 0xc3, 0xe9, 0x21, + 0x33, 0x8d, 0xb2, 0xc8, 0x71, 0x15, 0xed, 0xeb, 0xd1, 0xe7, 0x9f, 0x34, 0xb8, 0x94, 0xac, 0x8b, + 0xff, 0x83, 0xa9, 0xe8, 0xa7, 0xf0, 0x86, 0x85, 0x3b, 0x7e, 0x3f, 0x7c, 0x34, 0x60, 0xed, 0xe1, + 0x79, 0xac, 0xa8, 0xca, 0x47, 0x2a, 0xf2, 0xe9, 0x2b, 0xf9, 0xd1, 0x66, 0xe4, 0xed, 0x20, 0x13, + 0x7f, 0xb5, 0xb8, 0x04, 0xd5, 0x24, 0x01, 0xe4, 0x14, 0xfe, 0xb5, 0x06, 0xcb, 0x62, 0x9b, 0xab, + 0xf4, 0xbc, 0xc2, 0xbd, 0xe0, 0x71, 0x49, 0xc9, 0x9e, 0x4e, 0x92, 0x3d, 0x33, 0x51, 0xf6, 0x6c, + 0x5c, 0xf6, 0x37, 0x60, 0x65, 0x4c, 0x38, 0x29, 0xf8, 0x0e, 0x2c, 0x29, 0x67, 0x18, 0x2d, 0x7f, + 0xb7, 0x62, 0xf5, 0x6a, 0xfa, 0x47, 0x06, 0xf3, 0x27, 0xec, 0xfe, 0xa3, 0xe7, 0x5c, 0xd8, 0xab, + 0x36, 0x60, 0xe6, 0x5c, 0xce, 0xa4, 0xb0, 0xcc, 0x03, 0x58, 0x93, 0x9e, 0x1c, 0x7e, 0x4d, 0x52, + 0x5f, 0x1f, 0x5e, 0x61, 0x84, 0xfc, 0x7d, 0x1a, 0xae, 0x4e, 0x39, 0x56, 0x5e, 0xef, 0x0c, 0x2a, + 0xd1, 0xef, 0x73, 0x84, 0x22, 0xda, 0x1b, 0x8e, 0x4e, 0xf5, 0xb1, 0x46, 0x70, 0xca, 0x59, 0xd1, + 0xaf, 0x81, 0x0d, 0x79, 0x8e, 0xe8, 0xc0, 0x16, 0x83, 0xf1, 0x1d, 0xfd, 0x73, 0x00, 0x99, 0xc1, + 0x3b, 0xa8, 0x2b, 0x3f, 0x54, 0x7d, 0xf8, 0x52, 0xfc, 0x84, 0x32, 0x3f, 0x45, 0x5d, 0xc1, 0x25, + 0x4f, 0xd5, 0xba, 0x6a, 0x83, 0x31, 0x49, 0x98, 0x84, 0x5e, 0xef, 0xd6, 0x68, 0xaf, 0xb7, 0x52, + 0x8b, 0xff, 0xbf, 0x83, 0x38, 0x20, 0xfa, 0xed, 0x6f, 0x0f, 0xca, 0xa3, 0xdc, 0xcf, 0xf3, 0x6c, + 0x10, 0x6f, 0x1e, 0x22, 0xdd, 0xa3, 0x05, 0x57, 0x05, 0xb0, 0x2e, 0x3f, 0x4c, 0xbb, 0xe1, 0xd3, + 0x0f, 0x6e, 0x5d, 0xd0, 0xa7, 0xff, 0xaa, 0x81, 0x39, 0xed, 0xd0, 0x0b, 0x3b, 0xf8, 0x45, 0x6b, + 0xc8, 0x5d, 0x28, 0xf8, 0xee, 0x39, 0x2b, 0x08, 0xf8, 0xae, 0x4a, 0xb2, 0x8f, 0xee, 0xfd, 0xed, + 0xf9, 0xaa, 0xf6, 0x8f, 0xe7, 0xab, 0xda, 0xbf, 0x9e, 0xaf, 0x6a, 0xbf, 0xfa, 0xf7, 0xea, 0xb7, + 0x3e, 0xbf, 0xd1, 0x77, 0x28, 0x26, 0xa4, 0xe6, 0xf8, 0x1b, 0xe2, 0xd7, 0x46, 0xdb, 0xdf, 0xe8, + 0xd3, 0x0d, 0xfe, 0x2f, 0x25, 0x1b, 0xa1, 0x0f, 0x1d, 0xe5, 0x38, 0xe0, 0xbd, 0xff, 0x06, 0x00, + 0x00, 0xff, 0xff, 0xda, 0xbd, 0xf5, 0x12, 0x0f, 0x23, 0x00, 0x00, } func (m *ExecuteVtctlCommandRequest) Marshal() (dAtA []byte, err error) { @@ -6824,6 +6850,30 @@ func (m *GetTabletsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.TabletAliases) > 0 { + for iNdEx := len(m.TabletAliases) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TabletAliases[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintVtctldata(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if m.Strict { + i-- + if m.Strict { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } if len(m.Cells) > 0 { for iNdEx := len(m.Cells) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.Cells[iNdEx]) @@ -8919,6 +8969,15 @@ func (m *GetTabletsRequest) Size() (n int) { n += 1 + l + sovVtctldata(uint64(l)) } } + if m.Strict { + n += 2 + } + if len(m.TabletAliases) > 0 { + for _, e := range m.TabletAliases { + l = e.Size() + n += 1 + l + sovVtctldata(uint64(l)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -15922,6 +15981,60 @@ func (m *GetTabletsRequest) Unmarshal(dAtA []byte) error { } m.Cells = append(m.Cells, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Strict", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVtctldata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Strict = bool(v != 0) + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TabletAliases", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVtctldata + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthVtctldata + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthVtctldata + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TabletAliases = append(m.TabletAliases, &topodata.TabletAlias{}) + if err := m.TabletAliases[len(m.TabletAliases)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipVtctldata(dAtA[iNdEx:]) diff --git a/go/vt/topo/errors.go b/go/vt/topo/errors.go index 85158e358b8..8ec91532f5c 100644 --- a/go/vt/topo/errors.go +++ b/go/vt/topo/errors.go @@ -17,6 +17,7 @@ limitations under the License. package topo import ( + "errors" "fmt" ) @@ -80,8 +81,15 @@ func (e Error) Error() string { // IsErrType returns true if the error has the specified ErrorCode. func IsErrType(err error, code ErrorCode) bool { + var e Error + + if errors.As(err, &e) { + return e.code == code + } + if e, ok := err.(Error); ok { return e.code == code } + return false } diff --git a/go/vt/vtctl/grpcvtctldserver/server.go b/go/vt/vtctl/grpcvtctldserver/server.go index 0220a4e740e..7bbf73d4c1b 100644 --- a/go/vt/vtctl/grpcvtctldserver/server.go +++ b/go/vt/vtctl/grpcvtctldserver/server.go @@ -628,12 +628,49 @@ func (s *VtctldServer) GetTablets(ctx context.Context, req *vtctldatapb.GetTable } } - if req.Keyspace != "" && req.Shard != "" { - tabletMap, err := s.ts.GetTabletMapForShard(ctx, req.Keyspace, req.Shard) + // Create a context for our per-cell RPCs, with a timeout upper-bounded at + // the RemoteOperationTimeout. + // + // Per-cell goroutines may also cancel this context if they fail and the + // request specified Strict=true to allow us to fail faster. + ctx, cancel := context.WithTimeout(ctx, *topo.RemoteOperationTimeout) + defer cancel() + + var ( + tabletMap map[string]*topo.TabletInfo + err error + ) + + switch { + case len(req.TabletAliases) > 0: + tabletMap, err = s.ts.GetTabletMap(ctx, req.TabletAliases) + if err != nil { + err = fmt.Errorf("GetTabletMap(%v) failed: %w", req.TabletAliases, err) + } + case req.Keyspace != "" && req.Shard != "": + tabletMap, err = s.ts.GetTabletMapForShard(ctx, req.Keyspace, req.Shard) if err != nil { + err = fmt.Errorf("GetTabletMapForShard(%s, %s) failed: %w", req.Keyspace, req.Shard, err) + } + default: + // goto the req.Cells branch + tabletMap = nil + } + + if err != nil { + switch { + case topo.IsErrType(err, topo.PartialResult): + if req.Strict { + return nil, err + } + + log.Warningf("GetTablets encountered non-fatal error %s; continuing because Strict=false", err) + default: return nil, err } + } + if tabletMap != nil { var trueMasterTimestamp time.Time for _, ti := range tabletMap { if ti.Type == topodatapb.TabletType_MASTER { @@ -663,49 +700,81 @@ func (s *VtctldServer) GetTablets(ctx context.Context, req *vtctldatapb.GetTable cells = c } - var allTablets []*topodatapb.Tablet + var ( + m sync.Mutex + wg sync.WaitGroup + rec concurrency.AllErrorRecorder + allTablets []*topo.TabletInfo + ) for _, cell := range cells { - tablets, err := topotools.GetAllTablets(ctx, s.ts, cell) - if err != nil { - return nil, err - } - - // Collect true master term start times, and optionally filter out any - // tablets by keyspace according to the request. - masterTermStartTimes := map[string]time.Time{} - filteredTablets := make([]*topo.TabletInfo, 0, len(tablets)) + wg.Add(1) - for _, tablet := range tablets { - if req.Keyspace != "" && tablet.Keyspace != req.Keyspace { - continue - } + go func(cell string) { + defer wg.Done() - key := tablet.Keyspace + "." + tablet.Shard - if v, ok := masterTermStartTimes[key]; ok { - if tablet.GetMasterTermStartTime().After(v) { - masterTermStartTimes[key] = tablet.GetMasterTermStartTime() + tablets, err := topotools.GetAllTablets(ctx, s.ts, cell) + if err != nil { + if req.Strict { + log.Infof("GetTablets got an error from cell %s: %s. Running in strict mode, so canceling other cell RPCs", cell, err) + cancel() } - } else { - masterTermStartTimes[key] = tablet.GetMasterTermStartTime() + + rec.RecordError(fmt.Errorf("GetAllTablets(cell = %s) failed: %w", cell, err)) + + return } - filteredTablets = append(filteredTablets, tablet) + m.Lock() + defer m.Unlock() + allTablets = append(allTablets, tablets...) + }(cell) + } + + wg.Wait() + + if rec.HasErrors() { + if req.Strict || len(rec.Errors) == len(cells) { + return nil, rec.Error() } + } + + // Collect true master term start times, and optionally filter out any + // tablets by keyspace according to the request. + masterTermStartTimes := map[string]time.Time{} + filteredTablets := make([]*topo.TabletInfo, 0, len(allTablets)) - // collect the tablets with adjusted master term start times. they've - // already been filtered by the above loop, so no keyspace filtering - // here. - for _, ti := range filteredTablets { - key := ti.Keyspace + "." + ti.Shard - adjustTypeForStalePrimary(ti, masterTermStartTimes[key]) + for _, tablet := range allTablets { + if req.Keyspace != "" && tablet.Keyspace != req.Keyspace { + continue + } - allTablets = append(allTablets, ti.Tablet) + key := tablet.Keyspace + "." + tablet.Shard + if v, ok := masterTermStartTimes[key]; ok { + if tablet.GetMasterTermStartTime().After(v) { + masterTermStartTimes[key] = tablet.GetMasterTermStartTime() + } + } else { + masterTermStartTimes[key] = tablet.GetMasterTermStartTime() } + + filteredTablets = append(filteredTablets, tablet) + } + + adjustedTablets := make([]*topodatapb.Tablet, len(filteredTablets)) + + // collect the tablets with adjusted master term start times. they've + // already been filtered by the above loop, so no keyspace filtering + // here. + for i, ti := range filteredTablets { + key := ti.Keyspace + "." + ti.Shard + adjustTypeForStalePrimary(ti, masterTermStartTimes[key]) + + adjustedTablets[i] = ti.Tablet } return &vtctldatapb.GetTabletsResponse{ - Tablets: allTablets, + Tablets: adjustedTablets, }, nil } diff --git a/go/vt/vtctl/grpcvtctldserver/server_test.go b/go/vt/vtctl/grpcvtctldserver/server_test.go index 34e72baa19a..15e59059638 100644 --- a/go/vt/vtctl/grpcvtctldserver/server_test.go +++ b/go/vt/vtctl/grpcvtctldserver/server_test.go @@ -3327,7 +3327,7 @@ func TestGetTablets(t *testing.T) { shouldErr: false, }, { - name: "cells filter - error", + name: "cells filter with single error is nonfatal", cells: []string{"cell1"}, tablets: []*topodatapb.Tablet{ { @@ -3342,12 +3342,117 @@ func TestGetTablets(t *testing.T) { req: &vtctldatapb.GetTabletsRequest{ Cells: []string{"cell1", "doesnotexist"}, }, - expected: []*topodatapb.Tablet{}, + expected: []*topodatapb.Tablet{ + { + Alias: &topodatapb.TabletAlias{ + Cell: "cell1", + Uid: 100, + }, + Keyspace: "ks1", + Shard: "-", + }, + }, + shouldErr: false, + }, + { + name: "cells filter with single error is fatal in strict mode", + cells: []string{"cell1"}, + tablets: []*topodatapb.Tablet{ + { + Alias: &topodatapb.TabletAlias{ + Cell: "cell1", + Uid: 100, + }, + Keyspace: "ks1", + Shard: "-", + }, + }, + req: &vtctldatapb.GetTabletsRequest{ + Cells: []string{"cell1", "doesnotexist"}, + Strict: true, + }, + shouldErr: true, + }, + { + name: "in nonstrict mode if all cells fail the request fails", + cells: []string{"cell1"}, + tablets: []*topodatapb.Tablet{ + { + Alias: &topodatapb.TabletAlias{ + Cell: "cell1", + Uid: 100, + }, + Keyspace: "ks1", + Shard: "-", + }, + }, + req: &vtctldatapb.GetTabletsRequest{ + Cells: []string{"doesnotexist", "alsodoesnotexist"}, + }, shouldErr: true, }, + { + name: "tablet alias filtering", + cells: []string{"zone1"}, + tablets: []*topodatapb.Tablet{ + { + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace", + Shard: "-", + }, + }, + req: &vtctldatapb.GetTabletsRequest{ + TabletAliases: []*topodatapb.TabletAlias{ + { + Cell: "zone1", + Uid: 100, + }, + { + // This tablet doesn't exist, but doesn't cause a failure. + Cell: "zone404", + Uid: 404, + }, + }, + // The below filters are ignored, because TabletAliases always + // takes precedence. + Keyspace: "another_keyspace", + Shard: "-80", + Cells: []string{"zone404"}, + }, + expected: []*topodatapb.Tablet{ + { + Alias: &topodatapb.TabletAlias{ + Cell: "zone1", + Uid: 100, + }, + Keyspace: "testkeyspace", + Shard: "-", + }, + }, + shouldErr: false, + }, + { + name: "tablet alias filter with none found", + tablets: []*topodatapb.Tablet{}, + req: &vtctldatapb.GetTabletsRequest{ + TabletAliases: []*topodatapb.TabletAlias{ + { + Cell: "zone1", + Uid: 101, + }, + }, + }, + expected: []*topodatapb.Tablet{}, + shouldErr: false, + }, } for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -4989,7 +5094,7 @@ func TestTabletExternallyReparented(t *testing.T) { Cell: "zone2", Uid: 200, }, - Type: topodatapb.TabletType_MASTER, + Type: topodatapb.TabletType_UNKNOWN, Keyspace: "testkeyspace", Shard: "-", MasterTermStartTime: &vttime.Time{}, @@ -5296,6 +5401,9 @@ func TestTabletExternallyReparented(t *testing.T) { defer func() { topofactory.SetError(nil) + ctx, cancel := context.WithTimeout(ctx, time.Millisecond*10) + defer cancel() + resp, err := vtctld.GetTablets(ctx, &vtctldatapb.GetTabletsRequest{}) require.NoError(t, err, "cannot get all tablets in the topo") assert.ElementsMatch(t, tt.expectedTopo, resp.Tablets) diff --git a/go/vt/vtctl/vtctl.go b/go/vt/vtctl/vtctl.go index 5dcd20bc25c..3d39dffb5e9 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -551,81 +551,6 @@ func fmtTabletAwkable(ti *topo.TabletInfo) string { return fmt.Sprintf("%v %v %v %v %v %v %v %v", topoproto.TabletAliasString(ti.Alias), keyspace, shard, topoproto.TabletTypeLString(ti.Type), ti.Addr(), ti.MysqlAddr(), fmtMapAwkable(ti.Tags), mtst) } -func listTabletsByShard(ctx context.Context, wr *wrangler.Wrangler, keyspace, shard string) error { - tabletMap, err := wr.TopoServer().GetTabletMapForShard(ctx, keyspace, shard) - if err != nil { - return err - } - var trueMasterTimestamp time.Time - for _, ti := range tabletMap { - if ti.Type == topodatapb.TabletType_MASTER { - masterTimestamp := ti.GetMasterTermStartTime() - if masterTimestamp.After(trueMasterTimestamp) { - trueMasterTimestamp = masterTimestamp - } - } - } - for _, ti := range tabletMap { - masterTimestamp := ti.GetMasterTermStartTime() - if ti.Type == topodatapb.TabletType_MASTER && masterTimestamp.Before(trueMasterTimestamp) { - ti.Type = topodatapb.TabletType_UNKNOWN - } - wr.Logger().Printf("%v\n", fmtTabletAwkable(ti)) - } - return nil -} - -func dumpAllTablets(ctx context.Context, wr *wrangler.Wrangler, cell string) error { - tablets, err := topotools.GetAllTablets(ctx, wr.TopoServer(), cell) - if err != nil { - return err - } - // It is possible that an old master has not yet updated it's type in the topo - // In that case, report its type as UNKNOWN - // It used to be MASTER, and it is supposed to be REPLICA/SPARE eventually - trueMasterTimestamps := findTrueMasterTimestamps(tablets) - for _, ti := range tablets { - key := ti.Keyspace + "." + ti.Shard - masterTimestamp := ti.GetMasterTermStartTime() - if ti.Type == topodatapb.TabletType_MASTER && masterTimestamp.Before(trueMasterTimestamps[key]) { - ti.Type = topodatapb.TabletType_UNKNOWN - } - wr.Logger().Printf("%v\n", fmtTabletAwkable(ti)) - } - return nil -} - -func findTrueMasterTimestamps(tablets []*topo.TabletInfo) map[string]time.Time { - result := make(map[string]time.Time) - for _, ti := range tablets { - key := ti.Keyspace + "." + ti.Shard - if v, ok := result[key]; !ok { - result[key] = ti.GetMasterTermStartTime() - } else { - if ti.GetMasterTermStartTime().After(v) { - result[key] = ti.GetMasterTermStartTime() - } - } - } - return result -} - -func dumpTablets(ctx context.Context, wr *wrangler.Wrangler, tabletAliases []*topodatapb.TabletAlias) error { - tabletMap, err := wr.TopoServer().GetTabletMap(ctx, tabletAliases) - if err != nil { - return err - } - for _, tabletAlias := range tabletAliases { - ti, ok := tabletMap[topoproto.TabletAliasString(tabletAlias)] - if !ok { - wr.Logger().Warningf("failed to load tablet %v", tabletAlias) - } else { - wr.Logger().Printf("%v\n", fmtTabletAwkable(ti)) - } - } - return nil -} - // getFileParam returns a string containing either flag is not "", // or the content of the file named flagFile func getFileParam(flag, flagFile, name string) (string, error) { @@ -1348,7 +1273,21 @@ func commandListShardTablets(ctx context.Context, wr *wrangler.Wrangler, subFlag if err != nil { return err } - return listTabletsByShard(ctx, wr, keyspace, shard) + + resp, err := wr.VtctldServer().GetTablets(ctx, &vtctldatapb.GetTabletsRequest{ + Keyspace: keyspace, + Shard: shard, + Strict: false, + }) + if err != nil { + return err + } + + for _, tablet := range resp.Tablets { + wr.Logger().Printf("%v\n", cli.MarshalTabletAWK(tablet)) + } + + return nil } func commandSetShardIsMasterServing(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { @@ -2677,23 +2616,26 @@ func commandListAllTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags if err := subFlags.Parse(args); err != nil { return err } + var cells []string - var err error + if subFlags.NArg() == 1 { cells = strings.Split(subFlags.Arg(0), ",") - } else { - cells, err = wr.TopoServer().GetKnownCells(ctx) - if err != nil { - return err - } } - for _, cell := range cells { - err := dumpAllTablets(ctx, wr, cell) - if err != nil { - return err - } + resp, err := wr.VtctldServer().GetTablets(ctx, &vtctldatapb.GetTabletsRequest{ + Cells: cells, + Strict: false, + }) + + if err != nil { + return err + } + + for _, tablet := range resp.Tablets { + wr.Logger().Printf("%v\n", cli.MarshalTabletAWK(tablet)) } + return nil } @@ -2714,7 +2656,20 @@ func commandListTablets(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl return err } } - return dumpTablets(ctx, wr, aliases) + + resp, err := wr.VtctldServer().GetTablets(ctx, &vtctldatapb.GetTabletsRequest{ + TabletAliases: aliases, + Strict: false, + }) + if err != nil { + return err + } + + for _, tablet := range resp.Tablets { + wr.Logger().Printf("%v\n", cli.MarshalTabletAWK(tablet)) + } + + return nil } func commandGetSchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { diff --git a/proto/vtctldata.proto b/proto/vtctldata.proto index 9f5d535f569..8a6f321b6d8 100644 --- a/proto/vtctldata.proto +++ b/proto/vtctldata.proto @@ -389,6 +389,17 @@ message GetTabletsRequest { string shard = 2; // Cells is an optional set of cells to return tablets for. repeated string cells = 3; + // Strict specifies how the server should treat failures from individual + // cells. + // + // When false (the default), GetTablets will return data from any cells that + // return successfully, but will fail the request if all cells fail. When + // true, any individual cell can fail the full request. + bool strict = 4; + // TabletAliases is an optional list of tablet aliases to fetch Tablet objects + // for. If specified, Keyspace, Shard, and Cells are ignored, and tablets are + // looked up by their respective aliases' Cells directly. + repeated topodata.TabletAlias tablet_aliases = 5; } message GetTabletsResponse { diff --git a/web/vtadmin/src/proto/vtadmin.d.ts b/web/vtadmin/src/proto/vtadmin.d.ts index 9123315415a..85120c72c0b 100644 --- a/web/vtadmin/src/proto/vtadmin.d.ts +++ b/web/vtadmin/src/proto/vtadmin.d.ts @@ -27056,6 +27056,12 @@ export namespace vtctldata { /** GetTabletsRequest cells */ cells?: (string[]|null); + + /** GetTabletsRequest strict */ + strict?: (boolean|null); + + /** GetTabletsRequest tablet_aliases */ + tablet_aliases?: (topodata.ITabletAlias[]|null); } /** Represents a GetTabletsRequest. */ @@ -27076,6 +27082,12 @@ export namespace vtctldata { /** GetTabletsRequest cells. */ public cells: string[]; + /** GetTabletsRequest strict. */ + public strict: boolean; + + /** GetTabletsRequest tablet_aliases. */ + public tablet_aliases: topodata.ITabletAlias[]; + /** * Creates a new GetTabletsRequest instance using the specified properties. * @param [properties] Properties to set diff --git a/web/vtadmin/src/proto/vtadmin.js b/web/vtadmin/src/proto/vtadmin.js index 5e4b266fa26..f5e63252ed0 100644 --- a/web/vtadmin/src/proto/vtadmin.js +++ b/web/vtadmin/src/proto/vtadmin.js @@ -64667,6 +64667,8 @@ $root.vtctldata = (function() { * @property {string|null} [keyspace] GetTabletsRequest keyspace * @property {string|null} [shard] GetTabletsRequest shard * @property {Array.|null} [cells] GetTabletsRequest cells + * @property {boolean|null} [strict] GetTabletsRequest strict + * @property {Array.|null} [tablet_aliases] GetTabletsRequest tablet_aliases */ /** @@ -64679,6 +64681,7 @@ $root.vtctldata = (function() { */ function GetTabletsRequest(properties) { this.cells = []; + this.tablet_aliases = []; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -64709,6 +64712,22 @@ $root.vtctldata = (function() { */ GetTabletsRequest.prototype.cells = $util.emptyArray; + /** + * GetTabletsRequest strict. + * @member {boolean} strict + * @memberof vtctldata.GetTabletsRequest + * @instance + */ + GetTabletsRequest.prototype.strict = false; + + /** + * GetTabletsRequest tablet_aliases. + * @member {Array.} tablet_aliases + * @memberof vtctldata.GetTabletsRequest + * @instance + */ + GetTabletsRequest.prototype.tablet_aliases = $util.emptyArray; + /** * Creates a new GetTabletsRequest instance using the specified properties. * @function create @@ -64740,6 +64759,11 @@ $root.vtctldata = (function() { if (message.cells != null && message.cells.length) for (var i = 0; i < message.cells.length; ++i) writer.uint32(/* id 3, wireType 2 =*/26).string(message.cells[i]); + if (message.strict != null && Object.hasOwnProperty.call(message, "strict")) + writer.uint32(/* id 4, wireType 0 =*/32).bool(message.strict); + if (message.tablet_aliases != null && message.tablet_aliases.length) + for (var i = 0; i < message.tablet_aliases.length; ++i) + $root.topodata.TabletAlias.encode(message.tablet_aliases[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); return writer; }; @@ -64785,6 +64809,14 @@ $root.vtctldata = (function() { message.cells = []; message.cells.push(reader.string()); break; + case 4: + message.strict = reader.bool(); + break; + case 5: + if (!(message.tablet_aliases && message.tablet_aliases.length)) + message.tablet_aliases = []; + message.tablet_aliases.push($root.topodata.TabletAlias.decode(reader, reader.uint32())); + break; default: reader.skipType(tag & 7); break; @@ -64833,6 +64865,18 @@ $root.vtctldata = (function() { if (!$util.isString(message.cells[i])) return "cells: string[] expected"; } + if (message.strict != null && message.hasOwnProperty("strict")) + if (typeof message.strict !== "boolean") + return "strict: boolean expected"; + if (message.tablet_aliases != null && message.hasOwnProperty("tablet_aliases")) { + if (!Array.isArray(message.tablet_aliases)) + return "tablet_aliases: array expected"; + for (var i = 0; i < message.tablet_aliases.length; ++i) { + var error = $root.topodata.TabletAlias.verify(message.tablet_aliases[i]); + if (error) + return "tablet_aliases." + error; + } + } return null; }; @@ -64859,6 +64903,18 @@ $root.vtctldata = (function() { for (var i = 0; i < object.cells.length; ++i) message.cells[i] = String(object.cells[i]); } + if (object.strict != null) + message.strict = Boolean(object.strict); + if (object.tablet_aliases) { + if (!Array.isArray(object.tablet_aliases)) + throw TypeError(".vtctldata.GetTabletsRequest.tablet_aliases: array expected"); + message.tablet_aliases = []; + for (var i = 0; i < object.tablet_aliases.length; ++i) { + if (typeof object.tablet_aliases[i] !== "object") + throw TypeError(".vtctldata.GetTabletsRequest.tablet_aliases: object expected"); + message.tablet_aliases[i] = $root.topodata.TabletAlias.fromObject(object.tablet_aliases[i]); + } + } return message; }; @@ -64875,11 +64931,14 @@ $root.vtctldata = (function() { if (!options) options = {}; var object = {}; - if (options.arrays || options.defaults) + if (options.arrays || options.defaults) { object.cells = []; + object.tablet_aliases = []; + } if (options.defaults) { object.keyspace = ""; object.shard = ""; + object.strict = false; } if (message.keyspace != null && message.hasOwnProperty("keyspace")) object.keyspace = message.keyspace; @@ -64890,6 +64949,13 @@ $root.vtctldata = (function() { for (var j = 0; j < message.cells.length; ++j) object.cells[j] = message.cells[j]; } + if (message.strict != null && message.hasOwnProperty("strict")) + object.strict = message.strict; + if (message.tablet_aliases && message.tablet_aliases.length) { + object.tablet_aliases = []; + for (var j = 0; j < message.tablet_aliases.length; ++j) + object.tablet_aliases[j] = $root.topodata.TabletAlias.toObject(message.tablet_aliases[j], options); + } return object; };