change filer API to gRPC

This commit is contained in:
Chris Lu
2018-05-08 01:59:43 -07:00
parent 4936d6c342
commit 43a69d20bf
11 changed files with 951 additions and 255 deletions

View File

@@ -1,125 +0,0 @@
package filer
import (
"encoding/json"
"errors"
"fmt"
"net/url"
"github.com/chrislusf/seaweedfs/weed/util"
)
type ApiRequest struct {
Command string //"listFiles", "listDirectories", "getFileSize"
Directory string
FileName string
FileId string
}
type ListFilesResult struct {
Files []FileEntry
Error string `json:"error,omitempty"`
}
func ListFiles(server string, directory string, fileName string) (ret *ListFilesResult, err error) {
ret = new(ListFilesResult)
if err = call(server, ApiRequest{Command: "listFiles", Directory: directory, FileName: fileName}, ret); err == nil {
if ret.Error != "" {
return nil, errors.New(ret.Error)
}
return ret, nil
}
return nil, err
}
type GetFileSizeResult struct {
Size uint64
Error string `json:"error,omitempty"`
}
func GetFileSize(server string, fileId string) (ret *GetFileSizeResult, err error) {
ret = new(GetFileSizeResult)
if err = call(server, ApiRequest{Command: "getFileSize", FileId: fileId}, ret); err == nil {
if ret.Error != "" {
return nil, errors.New(ret.Error)
}
return ret, nil
}
return nil, err
}
type GetFileContentResult struct {
Content []byte
Error string `json:"error,omitempty"`
}
func GetFileContent(server string, fileId string) (ret *GetFileContentResult, err error) {
ret = new(GetFileContentResult)
if err = call(server, ApiRequest{Command: "getFileContent", FileId: fileId}, ret); err == nil {
if ret.Error != "" {
return nil, errors.New(ret.Error)
}
return ret, nil
}
return nil, err
}
type ListDirectoriesResult struct {
Directories []DirectoryName
Error string `json:"error,omitempty"`
}
func ListDirectories(server string, directory string) (ret *ListDirectoriesResult, err error) {
ret = new(ListDirectoriesResult)
if err := call(server, ApiRequest{Command: "listDirectories", Directory: directory}, ret); err == nil {
if ret.Error != "" {
return nil, errors.New(ret.Error)
}
return ret, nil
}
return nil, err
}
type LookupDirectoryEntryResult struct {
Found bool
FileId string
Error string `json:"error,omitempty"`
}
func LookupDirectoryEntry(server string, directory string, name string) (ret *LookupDirectoryEntryResult, err error) {
ret = new(LookupDirectoryEntryResult)
if err := call(server, ApiRequest{Command: "lookupDirectoryEntry", Directory: directory, FileName: name}, ret); err == nil {
if ret.Error != "" {
return nil, errors.New(ret.Error)
}
return ret, nil
}
return nil, err
}
func DeleteDirectoryOrFile(server string, path string, isDir bool) error {
destUrl := fmt.Sprintf("http://%s%s", server, path)
if isDir {
destUrl += "/?recursive=true"
}
return util.Delete(destUrl, "")
}
func call(server string, request ApiRequest, ret interface{}) error {
b, err := json.Marshal(request)
if err != nil {
fmt.Println("error:", err)
return nil
}
values := make(url.Values)
values.Add("request", string(b))
jsonBlob, err := util.Post("http://"+server+"/__api__", values)
if err != nil {
return err
}
err = json.Unmarshal(jsonBlob, ret)
if err != nil {
return err
}
return nil
}

583
weed/filer/filer.pb.go Normal file
View File

@@ -0,0 +1,583 @@
// Code generated by protoc-gen-go.
// source: filer.proto
// DO NOT EDIT!
/*
Package filer is a generated protocol buffer package.
It is generated from these files:
filer.proto
It has these top-level messages:
LookupDirectoryEntryRequest
LookupDirectoryEntryResponse
ListEntriesRequest
ListEntriesResponse
Entry
FuseAttributes
GetFileAttributesRequest
GetFileAttributesResponse
GetFileContentRequest
GetFileContentResponse
DeleteEntryRequest
DeleteEntryResponse
*/
package filer
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type LookupDirectoryEntryRequest struct {
Directory string `protobuf:"bytes,1,opt,name=directory" json:"directory,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
}
func (m *LookupDirectoryEntryRequest) Reset() { *m = LookupDirectoryEntryRequest{} }
func (m *LookupDirectoryEntryRequest) String() string { return proto.CompactTextString(m) }
func (*LookupDirectoryEntryRequest) ProtoMessage() {}
func (*LookupDirectoryEntryRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *LookupDirectoryEntryRequest) GetDirectory() string {
if m != nil {
return m.Directory
}
return ""
}
func (m *LookupDirectoryEntryRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
type LookupDirectoryEntryResponse struct {
Entry *Entry `protobuf:"bytes,1,opt,name=entry" json:"entry,omitempty"`
}
func (m *LookupDirectoryEntryResponse) Reset() { *m = LookupDirectoryEntryResponse{} }
func (m *LookupDirectoryEntryResponse) String() string { return proto.CompactTextString(m) }
func (*LookupDirectoryEntryResponse) ProtoMessage() {}
func (*LookupDirectoryEntryResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *LookupDirectoryEntryResponse) GetEntry() *Entry {
if m != nil {
return m.Entry
}
return nil
}
type ListEntriesRequest struct {
Directory string `protobuf:"bytes,1,opt,name=directory" json:"directory,omitempty"`
}
func (m *ListEntriesRequest) Reset() { *m = ListEntriesRequest{} }
func (m *ListEntriesRequest) String() string { return proto.CompactTextString(m) }
func (*ListEntriesRequest) ProtoMessage() {}
func (*ListEntriesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *ListEntriesRequest) GetDirectory() string {
if m != nil {
return m.Directory
}
return ""
}
type ListEntriesResponse struct {
Entries []*Entry `protobuf:"bytes,1,rep,name=entries" json:"entries,omitempty"`
}
func (m *ListEntriesResponse) Reset() { *m = ListEntriesResponse{} }
func (m *ListEntriesResponse) String() string { return proto.CompactTextString(m) }
func (*ListEntriesResponse) ProtoMessage() {}
func (*ListEntriesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *ListEntriesResponse) GetEntries() []*Entry {
if m != nil {
return m.Entries
}
return nil
}
type Entry struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
IsDirectory bool `protobuf:"varint,2,opt,name=is_directory,json=isDirectory" json:"is_directory,omitempty"`
FileId string `protobuf:"bytes,3,opt,name=file_id,json=fileId" json:"file_id,omitempty"`
Attributes *FuseAttributes `protobuf:"bytes,4,opt,name=attributes" json:"attributes,omitempty"`
}
func (m *Entry) Reset() { *m = Entry{} }
func (m *Entry) String() string { return proto.CompactTextString(m) }
func (*Entry) ProtoMessage() {}
func (*Entry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *Entry) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *Entry) GetIsDirectory() bool {
if m != nil {
return m.IsDirectory
}
return false
}
func (m *Entry) GetFileId() string {
if m != nil {
return m.FileId
}
return ""
}
func (m *Entry) GetAttributes() *FuseAttributes {
if m != nil {
return m.Attributes
}
return nil
}
type FuseAttributes struct {
FileSize uint64 `protobuf:"varint,1,opt,name=file_size,json=fileSize" json:"file_size,omitempty"`
Mtime int64 `protobuf:"varint,2,opt,name=mtime" json:"mtime,omitempty"`
FileMode uint32 `protobuf:"varint,3,opt,name=file_mode,json=fileMode" json:"file_mode,omitempty"`
Uid uint32 `protobuf:"varint,4,opt,name=uid" json:"uid,omitempty"`
Gid uint32 `protobuf:"varint,5,opt,name=gid" json:"gid,omitempty"`
}
func (m *FuseAttributes) Reset() { *m = FuseAttributes{} }
func (m *FuseAttributes) String() string { return proto.CompactTextString(m) }
func (*FuseAttributes) ProtoMessage() {}
func (*FuseAttributes) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *FuseAttributes) GetFileSize() uint64 {
if m != nil {
return m.FileSize
}
return 0
}
func (m *FuseAttributes) GetMtime() int64 {
if m != nil {
return m.Mtime
}
return 0
}
func (m *FuseAttributes) GetFileMode() uint32 {
if m != nil {
return m.FileMode
}
return 0
}
func (m *FuseAttributes) GetUid() uint32 {
if m != nil {
return m.Uid
}
return 0
}
func (m *FuseAttributes) GetGid() uint32 {
if m != nil {
return m.Gid
}
return 0
}
type GetFileAttributesRequest struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
ParentDir string `protobuf:"bytes,2,opt,name=parent_dir,json=parentDir" json:"parent_dir,omitempty"`
FileId string `protobuf:"bytes,3,opt,name=file_id,json=fileId" json:"file_id,omitempty"`
}
func (m *GetFileAttributesRequest) Reset() { *m = GetFileAttributesRequest{} }
func (m *GetFileAttributesRequest) String() string { return proto.CompactTextString(m) }
func (*GetFileAttributesRequest) ProtoMessage() {}
func (*GetFileAttributesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *GetFileAttributesRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *GetFileAttributesRequest) GetParentDir() string {
if m != nil {
return m.ParentDir
}
return ""
}
func (m *GetFileAttributesRequest) GetFileId() string {
if m != nil {
return m.FileId
}
return ""
}
type GetFileAttributesResponse struct {
Attributes *FuseAttributes `protobuf:"bytes,1,opt,name=attributes" json:"attributes,omitempty"`
}
func (m *GetFileAttributesResponse) Reset() { *m = GetFileAttributesResponse{} }
func (m *GetFileAttributesResponse) String() string { return proto.CompactTextString(m) }
func (*GetFileAttributesResponse) ProtoMessage() {}
func (*GetFileAttributesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (m *GetFileAttributesResponse) GetAttributes() *FuseAttributes {
if m != nil {
return m.Attributes
}
return nil
}
type GetFileContentRequest struct {
FileId string `protobuf:"bytes,1,opt,name=file_id,json=fileId" json:"file_id,omitempty"`
}
func (m *GetFileContentRequest) Reset() { *m = GetFileContentRequest{} }
func (m *GetFileContentRequest) String() string { return proto.CompactTextString(m) }
func (*GetFileContentRequest) ProtoMessage() {}
func (*GetFileContentRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
func (m *GetFileContentRequest) GetFileId() string {
if m != nil {
return m.FileId
}
return ""
}
type GetFileContentResponse struct {
Content []byte `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"`
}
func (m *GetFileContentResponse) Reset() { *m = GetFileContentResponse{} }
func (m *GetFileContentResponse) String() string { return proto.CompactTextString(m) }
func (*GetFileContentResponse) ProtoMessage() {}
func (*GetFileContentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *GetFileContentResponse) GetContent() []byte {
if m != nil {
return m.Content
}
return nil
}
type DeleteEntryRequest struct {
Directory string `protobuf:"bytes,1,opt,name=directory" json:"directory,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
IsDirectory bool `protobuf:"varint,3,opt,name=is_directory,json=isDirectory" json:"is_directory,omitempty"`
}
func (m *DeleteEntryRequest) Reset() { *m = DeleteEntryRequest{} }
func (m *DeleteEntryRequest) String() string { return proto.CompactTextString(m) }
func (*DeleteEntryRequest) ProtoMessage() {}
func (*DeleteEntryRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
func (m *DeleteEntryRequest) GetDirectory() string {
if m != nil {
return m.Directory
}
return ""
}
func (m *DeleteEntryRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *DeleteEntryRequest) GetIsDirectory() bool {
if m != nil {
return m.IsDirectory
}
return false
}
type DeleteEntryResponse struct {
}
func (m *DeleteEntryResponse) Reset() { *m = DeleteEntryResponse{} }
func (m *DeleteEntryResponse) String() string { return proto.CompactTextString(m) }
func (*DeleteEntryResponse) ProtoMessage() {}
func (*DeleteEntryResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
func init() {
proto.RegisterType((*LookupDirectoryEntryRequest)(nil), "filer.LookupDirectoryEntryRequest")
proto.RegisterType((*LookupDirectoryEntryResponse)(nil), "filer.LookupDirectoryEntryResponse")
proto.RegisterType((*ListEntriesRequest)(nil), "filer.ListEntriesRequest")
proto.RegisterType((*ListEntriesResponse)(nil), "filer.ListEntriesResponse")
proto.RegisterType((*Entry)(nil), "filer.Entry")
proto.RegisterType((*FuseAttributes)(nil), "filer.FuseAttributes")
proto.RegisterType((*GetFileAttributesRequest)(nil), "filer.GetFileAttributesRequest")
proto.RegisterType((*GetFileAttributesResponse)(nil), "filer.GetFileAttributesResponse")
proto.RegisterType((*GetFileContentRequest)(nil), "filer.GetFileContentRequest")
proto.RegisterType((*GetFileContentResponse)(nil), "filer.GetFileContentResponse")
proto.RegisterType((*DeleteEntryRequest)(nil), "filer.DeleteEntryRequest")
proto.RegisterType((*DeleteEntryResponse)(nil), "filer.DeleteEntryResponse")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// Client API for SeaweedFiler service
type SeaweedFilerClient interface {
LookupDirectoryEntry(ctx context.Context, in *LookupDirectoryEntryRequest, opts ...grpc.CallOption) (*LookupDirectoryEntryResponse, error)
ListEntries(ctx context.Context, in *ListEntriesRequest, opts ...grpc.CallOption) (*ListEntriesResponse, error)
GetFileAttributes(ctx context.Context, in *GetFileAttributesRequest, opts ...grpc.CallOption) (*GetFileAttributesResponse, error)
GetFileContent(ctx context.Context, in *GetFileContentRequest, opts ...grpc.CallOption) (*GetFileContentResponse, error)
DeleteEntry(ctx context.Context, in *DeleteEntryRequest, opts ...grpc.CallOption) (*DeleteEntryResponse, error)
}
type seaweedFilerClient struct {
cc *grpc.ClientConn
}
func NewSeaweedFilerClient(cc *grpc.ClientConn) SeaweedFilerClient {
return &seaweedFilerClient{cc}
}
func (c *seaweedFilerClient) LookupDirectoryEntry(ctx context.Context, in *LookupDirectoryEntryRequest, opts ...grpc.CallOption) (*LookupDirectoryEntryResponse, error) {
out := new(LookupDirectoryEntryResponse)
err := grpc.Invoke(ctx, "/filer.SeaweedFiler/LookupDirectoryEntry", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *seaweedFilerClient) ListEntries(ctx context.Context, in *ListEntriesRequest, opts ...grpc.CallOption) (*ListEntriesResponse, error) {
out := new(ListEntriesResponse)
err := grpc.Invoke(ctx, "/filer.SeaweedFiler/ListEntries", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *seaweedFilerClient) GetFileAttributes(ctx context.Context, in *GetFileAttributesRequest, opts ...grpc.CallOption) (*GetFileAttributesResponse, error) {
out := new(GetFileAttributesResponse)
err := grpc.Invoke(ctx, "/filer.SeaweedFiler/GetFileAttributes", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *seaweedFilerClient) GetFileContent(ctx context.Context, in *GetFileContentRequest, opts ...grpc.CallOption) (*GetFileContentResponse, error) {
out := new(GetFileContentResponse)
err := grpc.Invoke(ctx, "/filer.SeaweedFiler/GetFileContent", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *seaweedFilerClient) DeleteEntry(ctx context.Context, in *DeleteEntryRequest, opts ...grpc.CallOption) (*DeleteEntryResponse, error) {
out := new(DeleteEntryResponse)
err := grpc.Invoke(ctx, "/filer.SeaweedFiler/DeleteEntry", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for SeaweedFiler service
type SeaweedFilerServer interface {
LookupDirectoryEntry(context.Context, *LookupDirectoryEntryRequest) (*LookupDirectoryEntryResponse, error)
ListEntries(context.Context, *ListEntriesRequest) (*ListEntriesResponse, error)
GetFileAttributes(context.Context, *GetFileAttributesRequest) (*GetFileAttributesResponse, error)
GetFileContent(context.Context, *GetFileContentRequest) (*GetFileContentResponse, error)
DeleteEntry(context.Context, *DeleteEntryRequest) (*DeleteEntryResponse, error)
}
func RegisterSeaweedFilerServer(s *grpc.Server, srv SeaweedFilerServer) {
s.RegisterService(&_SeaweedFiler_serviceDesc, srv)
}
func _SeaweedFiler_LookupDirectoryEntry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LookupDirectoryEntryRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SeaweedFilerServer).LookupDirectoryEntry(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/filer.SeaweedFiler/LookupDirectoryEntry",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SeaweedFilerServer).LookupDirectoryEntry(ctx, req.(*LookupDirectoryEntryRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SeaweedFiler_ListEntries_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListEntriesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SeaweedFilerServer).ListEntries(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/filer.SeaweedFiler/ListEntries",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SeaweedFilerServer).ListEntries(ctx, req.(*ListEntriesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SeaweedFiler_GetFileAttributes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetFileAttributesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SeaweedFilerServer).GetFileAttributes(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/filer.SeaweedFiler/GetFileAttributes",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SeaweedFilerServer).GetFileAttributes(ctx, req.(*GetFileAttributesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SeaweedFiler_GetFileContent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetFileContentRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SeaweedFilerServer).GetFileContent(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/filer.SeaweedFiler/GetFileContent",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SeaweedFilerServer).GetFileContent(ctx, req.(*GetFileContentRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SeaweedFiler_DeleteEntry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteEntryRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SeaweedFilerServer).DeleteEntry(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/filer.SeaweedFiler/DeleteEntry",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SeaweedFilerServer).DeleteEntry(ctx, req.(*DeleteEntryRequest))
}
return interceptor(ctx, in, info, handler)
}
var _SeaweedFiler_serviceDesc = grpc.ServiceDesc{
ServiceName: "filer.SeaweedFiler",
HandlerType: (*SeaweedFilerServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "LookupDirectoryEntry",
Handler: _SeaweedFiler_LookupDirectoryEntry_Handler,
},
{
MethodName: "ListEntries",
Handler: _SeaweedFiler_ListEntries_Handler,
},
{
MethodName: "GetFileAttributes",
Handler: _SeaweedFiler_GetFileAttributes_Handler,
},
{
MethodName: "GetFileContent",
Handler: _SeaweedFiler_GetFileContent_Handler,
},
{
MethodName: "DeleteEntry",
Handler: _SeaweedFiler_DeleteEntry_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "filer.proto",
}
func init() { proto.RegisterFile("filer.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 523 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x54, 0x4d, 0x6f, 0xd3, 0x40,
0x10, 0xad, 0x71, 0xdc, 0x34, 0x93, 0xb4, 0x82, 0x69, 0x03, 0xae, 0x9b, 0x8a, 0xb0, 0x48, 0x88,
0x53, 0x85, 0x82, 0x38, 0x72, 0x00, 0x42, 0x10, 0x52, 0x51, 0x25, 0xf7, 0xc2, 0xad, 0x72, 0xeb,
0x69, 0xb5, 0x22, 0xb1, 0x83, 0x77, 0x2d, 0xd4, 0x9e, 0x39, 0xf3, 0x4b, 0xf8, 0x91, 0x68, 0x3f,
0xec, 0xd8, 0xd8, 0xa9, 0x22, 0xf5, 0xe6, 0x7d, 0x33, 0x6f, 0xe6, 0xcd, 0x97, 0xa1, 0x7f, 0xcd,
0xe7, 0x94, 0x9d, 0x2c, 0xb3, 0x54, 0xa6, 0xe8, 0xe9, 0x07, 0x3b, 0x83, 0xa3, 0xd3, 0x34, 0xfd,
0x91, 0x2f, 0xa7, 0x3c, 0xa3, 0x2b, 0x99, 0x66, 0xb7, 0x9f, 0x13, 0x99, 0xdd, 0x86, 0xf4, 0x33,
0x27, 0x21, 0x71, 0x04, 0xbd, 0xb8, 0x30, 0xf8, 0xce, 0xd8, 0x79, 0xdd, 0x0b, 0x57, 0x00, 0x22,
0x74, 0x92, 0x68, 0x41, 0xfe, 0x23, 0x6d, 0xd0, 0xdf, 0xec, 0x23, 0x8c, 0xda, 0x03, 0x8a, 0x65,
0x9a, 0x08, 0x42, 0x06, 0x1e, 0x29, 0x40, 0x47, 0xeb, 0x4f, 0x06, 0x27, 0x46, 0x94, 0x71, 0x32,
0x26, 0x36, 0x01, 0x3c, 0xe5, 0x42, 0x2a, 0x8c, 0x93, 0xd8, 0x48, 0x0b, 0x7b, 0x0f, 0xfb, 0x35,
0x8e, 0x4d, 0xf7, 0x0a, 0xba, 0x64, 0x20, 0xdf, 0x19, 0xbb, 0x8d, 0x84, 0x85, 0x91, 0xfd, 0x71,
0xc0, 0xd3, 0x50, 0x59, 0x94, 0xb3, 0x2a, 0x0a, 0x5f, 0xc0, 0x80, 0x8b, 0x8b, 0x55, 0x76, 0x55,
0xf0, 0x4e, 0xd8, 0xe7, 0xa2, 0x2c, 0x12, 0x9f, 0x41, 0x57, 0x05, 0xbe, 0xe0, 0xb1, 0xef, 0x6a,
0xe6, 0xb6, 0x7a, 0x7e, 0x8d, 0xf1, 0x1d, 0x40, 0x24, 0x65, 0xc6, 0x2f, 0x73, 0x49, 0xc2, 0xef,
0xe8, 0xaa, 0x87, 0x56, 0xc4, 0x2c, 0x17, 0xf4, 0xa1, 0x34, 0x86, 0x15, 0x47, 0xf6, 0xdb, 0x81,
0xbd, 0xba, 0x19, 0x8f, 0xa0, 0xa7, 0x53, 0x08, 0x7e, 0x67, 0xe4, 0x75, 0xc2, 0x1d, 0x05, 0x9c,
0xf3, 0x3b, 0xc2, 0x03, 0xf0, 0x16, 0x92, 0xdb, 0x61, 0xb8, 0xa1, 0x79, 0x94, 0x94, 0x45, 0x1a,
0x93, 0xd6, 0xb5, 0x6b, 0x28, 0xdf, 0xd2, 0x98, 0xf0, 0x31, 0xb8, 0x39, 0x8f, 0xb5, 0xa4, 0xdd,
0x50, 0x7d, 0x2a, 0xe4, 0x86, 0xc7, 0xbe, 0x67, 0x90, 0x1b, 0x1e, 0xb3, 0x6b, 0xf0, 0xbf, 0x90,
0x9c, 0xf1, 0x79, 0x55, 0xa7, 0x1d, 0x48, 0x5b, 0xa7, 0x8e, 0x01, 0x96, 0x51, 0x46, 0x89, 0x54,
0xdd, 0xb2, 0x8b, 0xd1, 0x33, 0xc8, 0x94, 0x67, 0x6b, 0xbb, 0xc4, 0x42, 0x38, 0x6c, 0xc9, 0x63,
0x87, 0x58, 0x6f, 0xa1, 0xb3, 0x69, 0x0b, 0xdf, 0xc0, 0xd0, 0xc6, 0xfc, 0x94, 0x26, 0x92, 0x12,
0x59, 0x08, 0xaf, 0xa8, 0x70, 0x6a, 0x2a, 0x26, 0xf0, 0xf4, 0x7f, 0x86, 0x95, 0xe0, 0x43, 0xf7,
0xca, 0x40, 0x9a, 0x32, 0x08, 0x8b, 0x27, 0xe3, 0x80, 0x53, 0x9a, 0x93, 0xa4, 0x87, 0x1d, 0x4e,
0x63, 0xc7, 0xdc, 0xc6, 0x8e, 0xb1, 0x21, 0xec, 0xd7, 0x52, 0x19, 0x6d, 0x93, 0xbf, 0x2e, 0x0c,
0xce, 0x29, 0xfa, 0x45, 0x14, 0x2b, 0xe9, 0x19, 0x46, 0x70, 0xd0, 0x76, 0x83, 0xc8, 0x6c, 0xcf,
0xee, 0xb9, 0xf8, 0xe0, 0xe5, 0xbd, 0x3e, 0x26, 0x23, 0xdb, 0xc2, 0x19, 0xf4, 0x2b, 0xe7, 0x86,
0x87, 0x05, 0xab, 0x71, 0xb6, 0x41, 0xd0, 0x66, 0x2a, 0xe3, 0x7c, 0x87, 0x27, 0x8d, 0xb9, 0xe3,
0x73, 0x4b, 0x59, 0xb7, 0x79, 0xc1, 0x78, 0xbd, 0x43, 0x19, 0xf9, 0x0c, 0xf6, 0xea, 0xb3, 0xc4,
0x51, 0x9d, 0x55, 0x5f, 0x8a, 0xe0, 0x78, 0x8d, 0xb5, 0x5a, 0x72, 0xa5, 0xfb, 0x65, 0xc9, 0xcd,
0xe1, 0x97, 0x25, 0xb7, 0x0c, 0x8b, 0x6d, 0x5d, 0x6e, 0xeb, 0x1f, 0xf0, 0xdb, 0x7f, 0x01, 0x00,
0x00, 0xff, 0xff, 0x6f, 0xb3, 0x14, 0x9b, 0x8f, 0x05, 0x00, 0x00,
}