From 160a0faa5fc6233fdc5a4caa4a7a3d1591f460d0 Mon Sep 17 00:00:00 2001 From: Bill Province Date: Thu, 9 Nov 2023 11:44:55 -0800 Subject: [PATCH] feat(indexing): Adopting GenericOpts and templated VectorIndex. (#59) Description: Pulls in changes from vector-indexer that allow us to specify configuration options when creating a VectorIndex. This will allow us (for example) to specify the metric type for the vector index (euclidian vs dotproduct vs cosine) separate from the technology for the index type (hnsw vs vamana vs kdtree vs hypertree). Note that at the moment, the process still retains everything using float64 arrays, even though we want to switch to float32. We will take this in two steps to keep the relative sizes of the changes a bit more reasonable. Closes: Hyp-14 --- go.mod | 28 +- go.sum | 56 +- posting/index.go | 253 ++++++--- posting/index_test.go | 9 +- protos/pb.proto | 14 + protos/pb/pb.pb.go | 1252 +++++++++++++++++++++++++++++------------ query/common_test.go | 2 + schema/parse.go | 272 +++++++-- schema/parse_test.go | 6 +- schema/schema.go | 41 +- schema/state.go | 35 +- tok/index_factory.go | 143 +++++ tok/tok.go | 113 ++-- worker/mutation.go | 4 +- worker/task.go | 82 +-- worker/tokens.go | 24 +- 16 files changed, 1683 insertions(+), 651 deletions(-) create mode 100644 tok/index_factory.go diff --git a/go.mod b/go.mod index c9d884df488..78b56588bd7 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/dgraph-io/graphql-transport-ws v0.0.0-20210511143556-2cef522f1f15 github.com/dgraph-io/ristretto v0.1.1 github.com/dgraph-io/simdjson-go v0.3.0 - github.com/dgraph-io/vector-indexer v0.1.12 + github.com/dgraph-io/vector-indexer v1.0.0 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 @@ -26,8 +26,8 @@ require ( github.com/docker/docker v1.13.1 github.com/docker/go-connections v0.4.0 github.com/dustin/go-humanize v1.0.0 - github.com/getsentry/sentry-go v0.24.0 - github.com/go-sql-driver/mysql v0.0.0-20190330032241-c0f6b444ad8f + github.com/getsentry/sentry-go v0.25.0 + github.com/go-sql-driver/mysql v1.7.1 github.com/gogo/protobuf v1.3.2 github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 github.com/golang/glog v1.0.0 @@ -35,13 +35,13 @@ require ( github.com/golang/snappy v0.0.4 github.com/google/codesearch v1.0.0 github.com/google/go-cmp v0.5.9 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/gorilla/websocket v1.4.2 github.com/graph-gophers/graphql-go v1.3.0 github.com/hashicorp/vault/api v1.0.4 github.com/minio/minio-go/v6 v6.0.55 github.com/mitchellh/panicwrap v1.0.0 - github.com/paulmach/go.geojson v0.0.0-20170327170536-40612a87147b + github.com/paulmach/go.geojson v1.5.0 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.2.1 github.com/prometheus/client_golang v1.14.0 @@ -56,13 +56,13 @@ require ( go.etcd.io/etcd/raft/v3 v3.5.9 go.opencensus.io v0.22.5 go.uber.org/zap v1.16.0 - golang.org/x/crypto v0.13.0 - golang.org/x/net v0.15.0 - golang.org/x/sync v0.3.0 - golang.org/x/sys v0.12.0 - golang.org/x/term v0.12.0 + golang.org/x/crypto v0.14.0 + golang.org/x/net v0.16.0 + golang.org/x/sync v0.4.0 + golang.org/x/sys v0.13.0 + golang.org/x/term v0.13.0 golang.org/x/text v0.13.0 - golang.org/x/tools v0.13.0 + golang.org/x/tools v0.14.0 google.golang.org/grpc v1.53.0 gopkg.in/square/go-jose.v2 v2.3.1 gopkg.in/yaml.v2 v2.4.0 @@ -82,6 +82,7 @@ require ( github.com/blevesearch/snowballstem v0.9.0 // indirect github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chewxy/math32 v1.10.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.3.3 // indirect @@ -129,11 +130,10 @@ require ( github.com/xdg/stringprep v1.0.0 // indirect go.uber.org/atomic v1.6.0 // indirect go.uber.org/multierr v1.5.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.12.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/mod v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/api v0.30.0 // indirect - google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/grpc/examples v0.0.0-20230208210314-e9d9bd0436ee // indirect google.golang.org/protobuf v1.29.1 // indirect diff --git a/go.sum b/go.sum index 208054da32f..eaff69686c8 100644 --- a/go.sum +++ b/go.sum @@ -107,6 +107,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chewxy/math32 v1.10.1 h1:LFpeY0SLJXeaiej/eIp2L40VYfscTvKh/FSEZ68uMkU= +github.com/chewxy/math32 v1.10.1/go.mod h1:dOB2rcuFrCn6UHrze36WSLVPKtzPMRAQvBvUwkSsLqs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -142,8 +144,8 @@ github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWa github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgraph-io/simdjson-go v0.3.0 h1:h71LO7vR4LHMPUhuoGN8bqGm1VNfGOlAG8BI6iDUKw0= github.com/dgraph-io/simdjson-go v0.3.0/go.mod h1:Otpysdjaxj9OGaJusn4pgQV7OFh2bELuHANq0I78uvY= -github.com/dgraph-io/vector-indexer v0.1.12 h1:Om85iSzoBR7AZB8sJ0jVKXm99h89HjQy+/gf+bShf4k= -github.com/dgraph-io/vector-indexer v0.1.12/go.mod h1:excC+hR3vdBfSPdAOcrHK2Ld4UVhOGn6V68fwwA3NLo= +github.com/dgraph-io/vector-indexer v1.0.0 h1:4M8soMImxKnAxNt27mW9xXRnLp7UT2PySgT17dskGII= +github.com/dgraph-io/vector-indexer v1.0.0/go.mod h1:pixbnSNh/ifb4PamkeoVQWAB0hIVrNzSeLeYOdp3auw= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= @@ -186,8 +188,8 @@ github.com/frankban/quicktest v1.10.2 h1:19ARM85nVi4xH7xPXuc5eM/udya5ieh7b/Sv+d8 github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/getsentry/sentry-go v0.24.0 h1:02b7qEmJ56EHGe9KFgjArjU/vG/aywm7Efgu+iPc01Y= -github.com/getsentry/sentry-go v0.24.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= +github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -203,8 +205,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-sql-driver/mysql v0.0.0-20190330032241-c0f6b444ad8f h1:yooNaEJy76Nvbcy/J0moVJfoNK4fDmSAO31V5iBM47c= -github.com/go-sql-driver/mysql v0.0.0-20190330032241-c0f6b444ad8f/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -283,8 +285,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -444,8 +446,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/paulmach/go.geojson v0.0.0-20170327170536-40612a87147b h1:rY7xFF9ktAzkr2OXol6GU9lrEw5PAMd5VV/5/T0A+FU= -github.com/paulmach/go.geojson v0.0.0-20170327170536-40612a87147b/go.mod h1:YaKx1hKpWF+T2oj2lFJPsW/t1Q5e1jQI61eoQSTwpIs= +github.com/paulmach/go.geojson v1.5.0 h1:7mhpMK89SQdHFcEGomT7/LuJhwhEgfmpWYVlVmLEdQw= +github.com/paulmach/go.geojson v1.5.0/go.mod h1:DgdUy2rRVDDVgKqrjMe2vZAHMfhDTrjVKt3LmHIXGbU= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= @@ -609,8 +611,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -624,8 +626,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -648,8 +650,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -690,8 +692,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -709,8 +711,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -762,12 +764,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -837,8 +839,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -874,8 +876,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= diff --git a/posting/index.go b/posting/index.go index d4a8b0031eb..4922bca202c 100644 --- a/posting/index.go +++ b/posting/index.go @@ -43,16 +43,16 @@ import ( "github.com/dgraph-io/dgraph/x" "github.com/dgraph-io/ristretto/z" "github.com/dgraph-io/vector-indexer/hnsw" - "github.com/dgraph-io/vector-indexer/manager" ) var emptyCountParams countParams type indexMutationInfo struct { - tokenizers []tok.Tokenizer - edge *pb.DirectedEdge // Represents the original uid -> value edge. - val types.Val - op pb.DirectedEdge_Op + tokenizers []tok.Tokenizer + factorySpecs []*tok.FactoryCreateSpec + edge *pb.DirectedEdge // Represents the original uid -> value edge. + val types.Val + op pb.DirectedEdge_Op } // indexTokens return tokens, without the predicate prefix and @@ -94,6 +94,14 @@ func (txn *Txn) addIndexMutations(ctx context.Context, info *indexMutationInfo) info.tokenizers = schema.State().Tokenizer(ctx, info.edge.Attr) } + if info.factorySpecs == nil { + specs, err := schema.State().FactoryCreateSpec(ctx, info.edge.Attr) + if err != nil { + return nil, err + } + info.factorySpecs = specs + } + attr := info.edge.Attr uid := info.edge.Entity if uid == 0 { @@ -110,18 +118,15 @@ func (txn *Txn) addIndexMutations(ctx context.Context, info *indexMutationInfo) return []*pb.DirectedEdge{}, err } - if info.tokenizers == nil { - if len(data) > 0 && data[0].Tid == types.VFloatID { - info.tokenizers = schema.State().Tokenizer(ctx, hnsw.HnswEuclidian) - } else { - info.tokenizers = schema.State().Tokenizer(ctx, info.edge.Attr) - } - } - if info.op == pb.DirectedEdge_DEL && len(data) > 0 && data[0].Tid == types.VFloatID { // TODO look into better alternatives - // if a delete & dealing with vfloats, add this to dead node in persistent store + // The issue here is that we will create dead nodes in the Vector Index + // assuming an HNSW index type. What we should do instead is invoke + // index.Remove(). However, we currently do + // not support this in VectorIndex code!! + // if a delete & dealing with vfloats, add this to dead node in persistent store. + // What we should do instead is invoke the factory.Remove(key) operation. deadAttr := hnsw.ConcatStrings(info.edge.Attr, hnsw.VecDead) deadKey := x.DataKey(deadAttr, 1) pl, err := txn.Get(deadKey) @@ -154,12 +159,17 @@ func (txn *Txn) addIndexMutations(ctx context.Context, info *indexMutationInfo) } } + // TODO: As stated earlier, we need to validate that it is okay to assume + // that we care about just data[0]. + // Similarly, the current assumption is that we have at most one + // Vector Index, but this assumption may break later. if info.op == pb.DirectedEdge_SET && - len(data) > 0 && data[0].Tid == types.VFloatID { + len(data) > 0 && data[0].Tid == types.VFloatID && + len(info.factorySpecs) > 0 { // retrieve vector from inUuid save as inVec inVec := types.BytesAsFloatArray(data[0].Value.([]byte)) tc := hnsw.NewTxnCache(NewViTxn(txn), txn.StartTs) - indexer, err := manager.NewIndexManager().Create(attr, manager.KnownFlavors[info.tokenizers[0].Name()], 3, nil) + indexer, err := info.factorySpecs[0].CreateIndex(attr) if err != nil { return []*pb.DirectedEdge{}, err } @@ -370,11 +380,16 @@ func (l *List) handleDeleteAll(ctx context.Context, edge *pb.DirectedEdge, txn * Tid: types.TypeID(p.ValType), Value: p.Value, } - _, err := txn.addIndexMutations(ctx, &indexMutationInfo{ - tokenizers: schema.State().Tokenizer(ctx, edge.Attr), - edge: edge, - val: val, - op: pb.DirectedEdge_DEL, + factorySpecs, err := schema.State().FactoryCreateSpec(ctx, edge.Attr) + if err != nil { + return err + } + _, err = txn.addIndexMutations(ctx, &indexMutationInfo{ + tokenizers: schema.State().Tokenizer(ctx, edge.Attr), + factorySpecs: factorySpecs, + edge: edge, + val: val, + op: pb.DirectedEdge_DEL, }) return err default: @@ -887,10 +902,16 @@ func (rb *IndexRebuild) GetQuerySchema() *pb.SchemaUpdate { // DropIndexes drops the indexes that need to be rebuilt. func (rb *IndexRebuild) DropIndexes(ctx context.Context) error { - prefixes, err := prefixesForTokIndexes(ctx, rb) + rebuildInfo := rb.needsTokIndexRebuild() + prefixes, err := rebuildInfo.prefixesForTokIndexes() if err != nil { return err } + vectorIndexPrefixes, err := rebuildInfo.prefixesForVectorIndexes() + if err != nil { + return nil + } + prefixes = append(prefixes, vectorIndexPrefixes...) prefixes = append(prefixes, prefixesToDropReverseEdges(ctx, rb)...) prefixes = append(prefixes, prefixesToDropCountIndex(ctx, rb)...) prefixes = append(prefixes, prefixesToDropVectorIndexEdges(ctx, rb)...) @@ -923,12 +944,15 @@ func (rb *IndexRebuild) BuildIndexes(ctx context.Context) error { } type indexRebuildInfo struct { - op indexOp - tokenizersToDelete []string - tokenizersToRebuild []string + op indexOp + attr string + tokenizersToDelete []string + tokenizersToRebuild []string + vectorIndexesToDelete []*pb.VectorSpec + vectorIndexesToRebuild []*pb.VectorSpec } -func (rb *IndexRebuild) needsTokIndexRebuild() indexRebuildInfo { +func (rb *IndexRebuild) needsTokIndexRebuild() *indexRebuildInfo { x.AssertTruef(rb.CurrentSchema != nil, "Current schema cannot be nil.") // If the old schema is nil, we can treat it as an empty schema. Copy it @@ -944,8 +968,9 @@ func (rb *IndexRebuild) needsTokIndexRebuild() indexRebuildInfo { // Index does not need to be rebuilt or deleted if the scheme directive // did not require an index before and now. if !currIndex && !prevIndex { - return indexRebuildInfo{ - op: indexNoop, + return &indexRebuildInfo{ + op: indexNoop, + attr: rb.Attr, } } @@ -954,19 +979,24 @@ func (rb *IndexRebuild) needsTokIndexRebuild() indexRebuildInfo { // prevIndex since the previous if statement guarantees both values are // different. if !currIndex { - return indexRebuildInfo{ - op: indexDelete, - tokenizersToDelete: old.Tokenizer, + return &indexRebuildInfo{ + op: indexDelete, + attr: rb.Attr, + tokenizersToDelete: old.Tokenizer, + vectorIndexesToDelete: old.VectorSpecs, } } // All tokenizers in the index need to be deleted and rebuilt if the value // types have changed. if currIndex && rb.CurrentSchema.ValueType != old.ValueType { - return indexRebuildInfo{ - op: indexRebuild, - tokenizersToDelete: old.Tokenizer, - tokenizersToRebuild: rb.CurrentSchema.Tokenizer, + return &indexRebuildInfo{ + op: indexRebuild, + attr: rb.Attr, + tokenizersToDelete: old.Tokenizer, + tokenizersToRebuild: rb.CurrentSchema.Tokenizer, + vectorIndexesToDelete: old.VectorSpecs, + vectorIndexesToRebuild: rb.CurrentSchema.VectorSpecs, } } @@ -982,63 +1012,129 @@ func (rb *IndexRebuild) needsTokIndexRebuild() indexRebuildInfo { newTokenizers, deletedTokenizers := x.Diff(currTokens, prevTokens) - // If the tokenizers are the same, nothing needs to be done. - if len(newTokenizers) == 0 && len(deletedTokenizers) == 0 { - return indexRebuildInfo{ - op: indexNoop, + prevFactoryNames := make(map[string]struct{}) + prevFactories := make(map[string]*pb.VectorSpec) + for _, t := range old.VectorSpecs { + prevFactoryNames[t.Name] = struct{}{} + prevFactories[t.Name] = t + } + currFactoryNames := make(map[string]struct{}) + currFactories := make(map[string]*pb.VectorSpec) + for _, t := range rb.CurrentSchema.VectorSpecs { + currFactoryNames[t.Name] = struct{}{} + currFactories[t.Name] = t + } + + newFactoryNames, deletedFactoryNames := x.Diff(currFactoryNames, prevFactoryNames) + + // If the tokenizers and factories are the same, nothing needs to be done. + if len(newTokenizers) == 0 && len(deletedTokenizers) == 0 && + len(newFactoryNames) == 0 && len(deletedFactoryNames) == 0 { + return &indexRebuildInfo{ + op: indexNoop, + attr: rb.Attr, } } + newFactories := []*pb.VectorSpec{} + for _, name := range newFactoryNames { + newFactories = append(newFactories, currFactories[name]) + } + deletedFactories := []*pb.VectorSpec{} + for _, name := range deletedFactoryNames { + deletedFactories = append(deletedFactories, prevFactories[name]) + } - return indexRebuildInfo{ - op: indexRebuild, - tokenizersToDelete: deletedTokenizers, - tokenizersToRebuild: newTokenizers, + return &indexRebuildInfo{ + op: indexRebuild, + attr: rb.Attr, + tokenizersToDelete: deletedTokenizers, + tokenizersToRebuild: newTokenizers, + vectorIndexesToDelete: deletedFactories, + vectorIndexesToRebuild: newFactories, } } -func prefixesForTokIndexes(ctx context.Context, rb *IndexRebuild) ([][]byte, error) { - rebuildInfo := rb.needsTokIndexRebuild() - prefixes := [][]byte{} +func (rb *indexRebuildInfo) appendTokenizerPrefixesToDelete( + tokenizer string, + priorPrefixes [][]byte) ([][]byte, error) { + retVal := priorPrefixes + prefixesNonLang, err := prefixesToDeleteTokensFor(rb.attr, tokenizer, false) + if err != nil { + return nil, err + } + retVal = append(retVal, prefixesNonLang...) + if tokenizer != "exact" { + return retVal, nil + } + prefixesWithLang, err := prefixesToDeleteTokensFor(rb.attr, tokenizer, true) + if err != nil { + return nil, err + } + return append(retVal, prefixesWithLang...), nil +} - if rebuildInfo.op == indexNoop { +// TODO: Kill this function. Rather than calculating prefixes -- like we do +// +// for tokenizers -- we should instead invoke the Remove(indexName) +// operation of the VectorIndexFactory, and have it do all the deletion. +// At the moment however, the Remove operation does not interact with +// Dgraph transactions, so this is not yet possible. +func (rb *indexRebuildInfo) prefixesForVectorIndexes() ([][]byte, error) { + prefixes := [][]byte{} + var err error + if rb.op == indexNoop { return prefixes, nil } - glog.Infof("Computing prefix index for attr %s and tokenizers %s", rb.Attr, - rebuildInfo.tokenizersToDelete) - for _, tokenizer := range rebuildInfo.tokenizersToDelete { - prefixesNonLang, err := prefixesToDeleteTokensFor(rb.Attr, tokenizer, false) + for _, vectorSpec := range rb.vectorIndexesToDelete { + glog.Infof("Computing prefix index for attr %s and index factory %s", + rb.attr, vectorSpec.Name) + // The mechanism currently is the same for tokenizers and + // vector factories. + prefixes, err = rb.appendTokenizerPrefixesToDelete(vectorSpec.Name, prefixes) if err != nil { return nil, err } - prefixes = append(prefixes, prefixesNonLang...) - if tokenizer != "exact" { - continue - } - prefixesWithLang, err := prefixesToDeleteTokensFor(rb.Attr, tokenizer, true) + } + + for _, vectorSpec := range rb.vectorIndexesToRebuild { + glog.Infof("Computing prefix index for attr %s and index factory %s", + rb.attr, vectorSpec.Name) + // The mechanism currently is the same for tokenizers and + // vector factories. + prefixes, err = rb.appendTokenizerPrefixesToDelete(vectorSpec.Name, prefixes) if err != nil { return nil, err } - prefixes = append(prefixes, prefixesWithLang...) } - glog.Infof("Deleting index for attr %s and tokenizers %s", rb.Attr, - rebuildInfo.tokenizersToRebuild) - // Before rebuilding, the existing index needs to be deleted. - for _, tokenizer := range rebuildInfo.tokenizersToRebuild { - prefixesNonLang, err := prefixesToDeleteTokensFor(rb.Attr, tokenizer, false) + return prefixes, nil +} + +func (rb *indexRebuildInfo) prefixesForTokIndexes() ([][]byte, error) { + prefixes := [][]byte{} + var err error + if rb.op == indexNoop { + return prefixes, nil + } + + glog.Infof("Computing prefix index for attr %s and tokenizers %s", rb.attr, + rb.tokenizersToDelete) + for _, tokenizer := range rb.tokenizersToDelete { + prefixes, err = rb.appendTokenizerPrefixesToDelete(tokenizer, prefixes) if err != nil { return nil, err } - prefixes = append(prefixes, prefixesNonLang...) - if tokenizer != "exact" { - continue - } - prefixesWithLang, err := prefixesToDeleteTokensFor(rb.Attr, tokenizer, true) + } + + glog.Infof("Deleting index for attr %s and tokenizers %s", rb.attr, + rb.tokenizersToRebuild) + // Before rebuilding, the existing index needs to be deleted. + for _, tokenizer := range rb.tokenizersToRebuild { + prefixes, err = rb.appendTokenizerPrefixesToDelete(tokenizer, prefixes) if err != nil { return nil, err } - prefixes = append(prefixes, prefixesWithLang...) } return prefixes, nil @@ -1053,7 +1149,7 @@ func rebuildTokIndex(ctx context.Context, rb *IndexRebuild) error { } // Exit early if there are no tokenizers to rebuild. - if len(rebuildInfo.tokenizersToRebuild) == 0 { + if len(rebuildInfo.tokenizersToRebuild) == 0 && len(rebuildInfo.vectorIndexesToRebuild) == 0 { return nil } @@ -1064,6 +1160,16 @@ func rebuildTokIndex(ctx context.Context, rb *IndexRebuild) error { return err } + var factorySpecs []*tok.FactoryCreateSpec + if len(rebuildInfo.vectorIndexesToRebuild) > 0 { + factorySpec, err := tok.GetFactoryCreateSpecFromSpec( + rebuildInfo.vectorIndexesToRebuild[0]) + if err != nil { + return err + } + factorySpecs = []*tok.FactoryCreateSpec{factorySpec} + } + pk := x.ParsedKey{Attr: rb.Attr} builder := rebuilder{attr: rb.Attr, prefix: pk.DataPrefix(), startTs: rb.StartTs} builder.fn = func(uid uint64, pl *List, txn *Txn) ([]*pb.DirectedEdge, error) { @@ -1079,10 +1185,11 @@ func rebuildTokIndex(ctx context.Context, rb *IndexRebuild) error { for { newEdges, err := txn.addIndexMutations(ctx, &indexMutationInfo{ - tokenizers: tokenizers, - edge: &edge, - val: val, - op: pb.DirectedEdge_SET, + tokenizers: tokenizers, + factorySpecs: factorySpecs, + edge: &edge, + val: val, + op: pb.DirectedEdge_SET, }) switch err { case ErrRetry: diff --git a/posting/index_test.go b/posting/index_test.go index b8098e644a7..03f2f74cc0e 100644 --- a/posting/index_test.go +++ b/posting/index_test.go @@ -267,7 +267,8 @@ func TestRebuildTokIndex(t *testing.T) { OldSchema: nil, CurrentSchema: ¤tSchema, } - prefixes, err := prefixesForTokIndexes(context.Background(), &rb) + rebuildInfo := rb.needsTokIndexRebuild() + prefixes, err := rebuildInfo.prefixesForTokIndexes() require.NoError(t, err) require.NoError(t, pstore.DropPrefix(prefixes...)) require.NoError(t, rebuildTokIndex(context.Background(), &rb)) @@ -320,7 +321,8 @@ func TestRebuildTokIndexWithDeletion(t *testing.T) { OldSchema: nil, CurrentSchema: ¤tSchema, } - prefixes, err := prefixesForTokIndexes(context.Background(), &rb) + rebuildInfo := rb.needsTokIndexRebuild() + prefixes, err := rebuildInfo.prefixesForTokIndexes() require.NoError(t, err) require.NoError(t, pstore.DropPrefix(prefixes...)) require.NoError(t, rebuildTokIndex(context.Background(), &rb)) @@ -334,7 +336,8 @@ func TestRebuildTokIndexWithDeletion(t *testing.T) { OldSchema: ¤tSchema, CurrentSchema: &newSchema, } - prefixes, err = prefixesForTokIndexes(context.Background(), &rb) + rebuildInfo = rb.needsTokIndexRebuild() + prefixes, err = rebuildInfo.prefixesForTokIndexes() require.NoError(t, err) require.NoError(t, pstore.DropPrefix(prefixes...)) require.NoError(t, rebuildTokIndex(context.Background(), &rb)) diff --git a/protos/pb.proto b/protos/pb.proto index 68a3155485f..aa0c2827501 100644 --- a/protos/pb.proto +++ b/protos/pb.proto @@ -517,6 +517,20 @@ message SchemaUpdate { // Deleted field: reserved 7; reserved "explicit"; + + repeated VectorSpec vector_specs = 15; +} + +message VectorSpec { + // This names the kind of Vector Index, e.g., + // hnsw, lsh, hypertree, ... + string name = 1; + repeated OptionPair options = 2; +} + +message OptionPair { + string key = 1; + string value = 2; } message TypeUpdate { diff --git a/protos/pb/pb.pb.go b/protos/pb/pb.pb.go index 2a1246fc151..6f2e0d62053 100644 --- a/protos/pb/pb.pb.go +++ b/protos/pb/pb.pb.go @@ -264,7 +264,7 @@ func (x NumLeaseType) String() string { } func (NumLeaseType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{54, 0} + return fileDescriptor_f80abaa17e25ccc8, []int{56, 0} } type DropOperation_DropOp int32 @@ -295,7 +295,7 @@ func (x DropOperation_DropOp) String() string { } func (DropOperation_DropOp) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{63, 0} + return fileDescriptor_f80abaa17e25ccc8, []int{65, 0} } type BackupKey_KeyType int32 @@ -338,7 +338,7 @@ func (x BackupKey_KeyType) String() string { } func (BackupKey_KeyType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{66, 0} + return fileDescriptor_f80abaa17e25ccc8, []int{68, 0} } type List struct { @@ -3598,8 +3598,9 @@ type SchemaUpdate struct { NonNullableList bool `protobuf:"varint,11,opt,name=non_nullable_list,json=nonNullableList,proto3" json:"non_nullable_list,omitempty"` // If value_type is OBJECT, then this represents an object type with a // custom name. This field stores said name. - ObjectTypeName string `protobuf:"bytes,12,opt,name=object_type_name,json=objectTypeName,proto3" json:"object_type_name,omitempty"` - NoConflict bool `protobuf:"varint,13,opt,name=no_conflict,json=noConflict,proto3" json:"no_conflict,omitempty"` + ObjectTypeName string `protobuf:"bytes,12,opt,name=object_type_name,json=objectTypeName,proto3" json:"object_type_name,omitempty"` + NoConflict bool `protobuf:"varint,13,opt,name=no_conflict,json=noConflict,proto3" json:"no_conflict,omitempty"` + VectorSpecs []*VectorSpec `protobuf:"bytes,15,rep,name=vector_specs,json=vectorSpecs,proto3" json:"vector_specs,omitempty"` } func (m *SchemaUpdate) Reset() { *m = SchemaUpdate{} } @@ -3726,6 +3727,120 @@ func (m *SchemaUpdate) GetNoConflict() bool { return false } +func (m *SchemaUpdate) GetVectorSpecs() []*VectorSpec { + if m != nil { + return m.VectorSpecs + } + return nil +} + +type VectorSpec struct { + // This names the kind of Vector Index, e.g., + // + // hnsw, lsh, hypertree, ... + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Options []*OptionPair `protobuf:"bytes,2,rep,name=options,proto3" json:"options,omitempty"` +} + +func (m *VectorSpec) Reset() { *m = VectorSpec{} } +func (m *VectorSpec) String() string { return proto.CompactTextString(m) } +func (*VectorSpec) ProtoMessage() {} +func (*VectorSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_f80abaa17e25ccc8, []int{42} +} +func (m *VectorSpec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VectorSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VectorSpec.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VectorSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_VectorSpec.Merge(m, src) +} +func (m *VectorSpec) XXX_Size() int { + return m.Size() +} +func (m *VectorSpec) XXX_DiscardUnknown() { + xxx_messageInfo_VectorSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_VectorSpec proto.InternalMessageInfo + +func (m *VectorSpec) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *VectorSpec) GetOptions() []*OptionPair { + if m != nil { + return m.Options + } + return nil +} + +type OptionPair struct { + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *OptionPair) Reset() { *m = OptionPair{} } +func (m *OptionPair) String() string { return proto.CompactTextString(m) } +func (*OptionPair) ProtoMessage() {} +func (*OptionPair) Descriptor() ([]byte, []int) { + return fileDescriptor_f80abaa17e25ccc8, []int{43} +} +func (m *OptionPair) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *OptionPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_OptionPair.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *OptionPair) XXX_Merge(src proto.Message) { + xxx_messageInfo_OptionPair.Merge(m, src) +} +func (m *OptionPair) XXX_Size() int { + return m.Size() +} +func (m *OptionPair) XXX_DiscardUnknown() { + xxx_messageInfo_OptionPair.DiscardUnknown(m) +} + +var xxx_messageInfo_OptionPair proto.InternalMessageInfo + +func (m *OptionPair) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *OptionPair) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + type TypeUpdate struct { TypeName string `protobuf:"bytes,1,opt,name=type_name,json=typeName,proto3" json:"type_name,omitempty"` Fields []*SchemaUpdate `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty"` @@ -3735,7 +3850,7 @@ func (m *TypeUpdate) Reset() { *m = TypeUpdate{} } func (m *TypeUpdate) String() string { return proto.CompactTextString(m) } func (*TypeUpdate) ProtoMessage() {} func (*TypeUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{42} + return fileDescriptor_f80abaa17e25ccc8, []int{44} } func (m *TypeUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3786,7 +3901,7 @@ func (m *MapHeader) Reset() { *m = MapHeader{} } func (m *MapHeader) String() string { return proto.CompactTextString(m) } func (*MapHeader) ProtoMessage() {} func (*MapHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{43} + return fileDescriptor_f80abaa17e25ccc8, []int{45} } func (m *MapHeader) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3834,7 +3949,7 @@ func (m *MovePredicatePayload) Reset() { *m = MovePredicatePayload{} } func (m *MovePredicatePayload) String() string { return proto.CompactTextString(m) } func (*MovePredicatePayload) ProtoMessage() {} func (*MovePredicatePayload) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{44} + return fileDescriptor_f80abaa17e25ccc8, []int{46} } func (m *MovePredicatePayload) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3907,7 +4022,7 @@ func (m *TxnStatus) Reset() { *m = TxnStatus{} } func (m *TxnStatus) String() string { return proto.CompactTextString(m) } func (*TxnStatus) ProtoMessage() {} func (*TxnStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{45} + return fileDescriptor_f80abaa17e25ccc8, []int{47} } func (m *TxnStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -3960,7 +4075,7 @@ func (m *OracleDelta) Reset() { *m = OracleDelta{} } func (m *OracleDelta) String() string { return proto.CompactTextString(m) } func (*OracleDelta) ProtoMessage() {} func (*OracleDelta) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{46} + return fileDescriptor_f80abaa17e25ccc8, []int{48} } func (m *OracleDelta) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4018,7 +4133,7 @@ func (m *TxnTimestamps) Reset() { *m = TxnTimestamps{} } func (m *TxnTimestamps) String() string { return proto.CompactTextString(m) } func (*TxnTimestamps) ProtoMessage() {} func (*TxnTimestamps) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{47} + return fileDescriptor_f80abaa17e25ccc8, []int{49} } func (m *TxnTimestamps) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4062,7 +4177,7 @@ func (m *PeerResponse) Reset() { *m = PeerResponse{} } func (m *PeerResponse) String() string { return proto.CompactTextString(m) } func (*PeerResponse) ProtoMessage() {} func (*PeerResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{48} + return fileDescriptor_f80abaa17e25ccc8, []int{50} } func (m *PeerResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4107,7 +4222,7 @@ func (m *RaftBatch) Reset() { *m = RaftBatch{} } func (m *RaftBatch) String() string { return proto.CompactTextString(m) } func (*RaftBatch) ProtoMessage() {} func (*RaftBatch) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{49} + return fileDescriptor_f80abaa17e25ccc8, []int{51} } func (m *RaftBatch) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4158,7 +4273,7 @@ func (m *TabletResponse) Reset() { *m = TabletResponse{} } func (m *TabletResponse) String() string { return proto.CompactTextString(m) } func (*TabletResponse) ProtoMessage() {} func (*TabletResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{50} + return fileDescriptor_f80abaa17e25ccc8, []int{52} } func (m *TabletResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4203,7 +4318,7 @@ func (m *TabletRequest) Reset() { *m = TabletRequest{} } func (m *TabletRequest) String() string { return proto.CompactTextString(m) } func (*TabletRequest) ProtoMessage() {} func (*TabletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{51} + return fileDescriptor_f80abaa17e25ccc8, []int{53} } func (m *TabletRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4255,7 +4370,7 @@ func (m *SubscriptionRequest) Reset() { *m = SubscriptionRequest{} } func (m *SubscriptionRequest) String() string { return proto.CompactTextString(m) } func (*SubscriptionRequest) ProtoMessage() {} func (*SubscriptionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{52} + return fileDescriptor_f80abaa17e25ccc8, []int{54} } func (m *SubscriptionRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4306,7 +4421,7 @@ func (m *SubscriptionResponse) Reset() { *m = SubscriptionResponse{} } func (m *SubscriptionResponse) String() string { return proto.CompactTextString(m) } func (*SubscriptionResponse) ProtoMessage() {} func (*SubscriptionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{53} + return fileDescriptor_f80abaa17e25ccc8, []int{55} } func (m *SubscriptionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4356,7 +4471,7 @@ func (m *Num) Reset() { *m = Num{} } func (m *Num) String() string { return proto.CompactTextString(m) } func (*Num) ProtoMessage() {} func (*Num) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{54} + return fileDescriptor_f80abaa17e25ccc8, []int{56} } func (m *Num) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4431,7 +4546,7 @@ func (m *AssignedIds) Reset() { *m = AssignedIds{} } func (m *AssignedIds) String() string { return proto.CompactTextString(m) } func (*AssignedIds) ProtoMessage() {} func (*AssignedIds) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{55} + return fileDescriptor_f80abaa17e25ccc8, []int{57} } func (m *AssignedIds) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4490,7 +4605,7 @@ func (m *RemoveNodeRequest) Reset() { *m = RemoveNodeRequest{} } func (m *RemoveNodeRequest) String() string { return proto.CompactTextString(m) } func (*RemoveNodeRequest) ProtoMessage() {} func (*RemoveNodeRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{56} + return fileDescriptor_f80abaa17e25ccc8, []int{58} } func (m *RemoveNodeRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4543,7 +4658,7 @@ func (m *MoveTabletRequest) Reset() { *m = MoveTabletRequest{} } func (m *MoveTabletRequest) String() string { return proto.CompactTextString(m) } func (*MoveTabletRequest) ProtoMessage() {} func (*MoveTabletRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{57} + return fileDescriptor_f80abaa17e25ccc8, []int{59} } func (m *MoveTabletRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4601,7 +4716,7 @@ func (m *ApplyLicenseRequest) Reset() { *m = ApplyLicenseRequest{} } func (m *ApplyLicenseRequest) String() string { return proto.CompactTextString(m) } func (*ApplyLicenseRequest) ProtoMessage() {} func (*ApplyLicenseRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{58} + return fileDescriptor_f80abaa17e25ccc8, []int{60} } func (m *ApplyLicenseRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4646,7 +4761,7 @@ func (m *SnapshotMeta) Reset() { *m = SnapshotMeta{} } func (m *SnapshotMeta) String() string { return proto.CompactTextString(m) } func (*SnapshotMeta) ProtoMessage() {} func (*SnapshotMeta) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{59} + return fileDescriptor_f80abaa17e25ccc8, []int{61} } func (m *SnapshotMeta) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4700,7 +4815,7 @@ func (m *Status) Reset() { *m = Status{} } func (m *Status) String() string { return proto.CompactTextString(m) } func (*Status) ProtoMessage() {} func (*Status) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{60} + return fileDescriptor_f80abaa17e25ccc8, []int{62} } func (m *Status) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4769,7 +4884,7 @@ func (m *BackupRequest) Reset() { *m = BackupRequest{} } func (m *BackupRequest) String() string { return proto.CompactTextString(m) } func (*BackupRequest) ProtoMessage() {} func (*BackupRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{61} + return fileDescriptor_f80abaa17e25ccc8, []int{63} } func (m *BackupRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4883,7 +4998,7 @@ func (m *BackupResponse) Reset() { *m = BackupResponse{} } func (m *BackupResponse) String() string { return proto.CompactTextString(m) } func (*BackupResponse) ProtoMessage() {} func (*BackupResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{62} + return fileDescriptor_f80abaa17e25ccc8, []int{64} } func (m *BackupResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4930,7 +5045,7 @@ func (m *DropOperation) Reset() { *m = DropOperation{} } func (m *DropOperation) String() string { return proto.CompactTextString(m) } func (*DropOperation) ProtoMessage() {} func (*DropOperation) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{63} + return fileDescriptor_f80abaa17e25ccc8, []int{65} } func (m *DropOperation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4991,7 +5106,7 @@ func (m *ExportRequest) Reset() { *m = ExportRequest{} } func (m *ExportRequest) String() string { return proto.CompactTextString(m) } func (*ExportRequest) ProtoMessage() {} func (*ExportRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{64} + return fileDescriptor_f80abaa17e25ccc8, []int{66} } func (m *ExportRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5101,7 +5216,7 @@ func (m *ExportResponse) Reset() { *m = ExportResponse{} } func (m *ExportResponse) String() string { return proto.CompactTextString(m) } func (*ExportResponse) ProtoMessage() {} func (*ExportResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{65} + return fileDescriptor_f80abaa17e25ccc8, []int{67} } func (m *ExportResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5166,7 +5281,7 @@ func (m *BackupKey) Reset() { *m = BackupKey{} } func (m *BackupKey) String() string { return proto.CompactTextString(m) } func (*BackupKey) ProtoMessage() {} func (*BackupKey) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{66} + return fileDescriptor_f80abaa17e25ccc8, []int{68} } func (m *BackupKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5257,7 +5372,7 @@ func (m *BackupPostingList) Reset() { *m = BackupPostingList{} } func (m *BackupPostingList) String() string { return proto.CompactTextString(m) } func (*BackupPostingList) ProtoMessage() {} func (*BackupPostingList) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{67} + return fileDescriptor_f80abaa17e25ccc8, []int{69} } func (m *BackupPostingList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5332,7 +5447,7 @@ func (m *UpdateGraphQLSchemaRequest) Reset() { *m = UpdateGraphQLSchemaR func (m *UpdateGraphQLSchemaRequest) String() string { return proto.CompactTextString(m) } func (*UpdateGraphQLSchemaRequest) ProtoMessage() {} func (*UpdateGraphQLSchemaRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{68} + return fileDescriptor_f80abaa17e25ccc8, []int{70} } func (m *UpdateGraphQLSchemaRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5397,7 +5512,7 @@ func (m *UpdateGraphQLSchemaResponse) Reset() { *m = UpdateGraphQLSchema func (m *UpdateGraphQLSchemaResponse) String() string { return proto.CompactTextString(m) } func (*UpdateGraphQLSchemaResponse) ProtoMessage() {} func (*UpdateGraphQLSchemaResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{69} + return fileDescriptor_f80abaa17e25ccc8, []int{71} } func (m *UpdateGraphQLSchemaResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5444,7 +5559,7 @@ func (m *BulkMeta) Reset() { *m = BulkMeta{} } func (m *BulkMeta) String() string { return proto.CompactTextString(m) } func (*BulkMeta) ProtoMessage() {} func (*BulkMeta) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{70} + return fileDescriptor_f80abaa17e25ccc8, []int{72} } func (m *BulkMeta) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5503,7 +5618,7 @@ func (m *DeleteNsRequest) Reset() { *m = DeleteNsRequest{} } func (m *DeleteNsRequest) String() string { return proto.CompactTextString(m) } func (*DeleteNsRequest) ProtoMessage() {} func (*DeleteNsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{71} + return fileDescriptor_f80abaa17e25ccc8, []int{73} } func (m *DeleteNsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5554,7 +5669,7 @@ func (m *TaskStatusRequest) Reset() { *m = TaskStatusRequest{} } func (m *TaskStatusRequest) String() string { return proto.CompactTextString(m) } func (*TaskStatusRequest) ProtoMessage() {} func (*TaskStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{72} + return fileDescriptor_f80abaa17e25ccc8, []int{74} } func (m *TaskStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5598,7 +5713,7 @@ func (m *TaskStatusResponse) Reset() { *m = TaskStatusResponse{} } func (m *TaskStatusResponse) String() string { return proto.CompactTextString(m) } func (*TaskStatusResponse) ProtoMessage() {} func (*TaskStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_f80abaa17e25ccc8, []int{73} + return fileDescriptor_f80abaa17e25ccc8, []int{75} } func (m *TaskStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5693,6 +5808,8 @@ func init() { proto.RegisterType((*SchemaNode)(nil), "pb.SchemaNode") proto.RegisterType((*SchemaResult)(nil), "pb.SchemaResult") proto.RegisterType((*SchemaUpdate)(nil), "pb.SchemaUpdate") + proto.RegisterType((*VectorSpec)(nil), "pb.VectorSpec") + proto.RegisterType((*OptionPair)(nil), "pb.OptionPair") proto.RegisterType((*TypeUpdate)(nil), "pb.TypeUpdate") proto.RegisterType((*MapHeader)(nil), "pb.MapHeader") proto.RegisterType((*MovePredicatePayload)(nil), "pb.MovePredicatePayload") @@ -5732,353 +5849,357 @@ func init() { func init() { proto.RegisterFile("pb.proto", fileDescriptor_f80abaa17e25ccc8) } var fileDescriptor_f80abaa17e25ccc8 = []byte{ - // 5528 bytes of a gzipped FileDescriptorProto + // 5589 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x7b, 0x4b, 0x6c, 0x1c, 0x57, - 0x76, 0x28, 0xfb, 0xdf, 0x75, 0xfa, 0xa3, 0xe6, 0x95, 0x2d, 0xb7, 0x5b, 0xb6, 0xa4, 0x29, 0x59, - 0x36, 0x2d, 0x59, 0x94, 0x44, 0x7b, 0xde, 0x1b, 0x7b, 0x30, 0x78, 0x8f, 0x9f, 0xa6, 0x4c, 0x8b, - 0xbf, 0x29, 0xb6, 0x34, 0x1f, 0xe0, 0xbd, 0x46, 0xb1, 0xea, 0x92, 0xac, 0x61, 0x75, 0x55, 0x4d, - 0x55, 0x35, 0x87, 0xf4, 0x2e, 0xab, 0x59, 0x24, 0x8b, 0x41, 0xb2, 0x4c, 0x90, 0x45, 0xb6, 0xc9, - 0x2a, 0x48, 0x90, 0x20, 0x40, 0x76, 0x41, 0x10, 0x64, 0x35, 0xcb, 0x04, 0x49, 0x8c, 0xc0, 0x93, - 0x95, 0x16, 0x01, 0x92, 0x6d, 0x36, 0xc1, 0x39, 0xe7, 0xd6, 0xaf, 0xd9, 0xfa, 0x78, 0x82, 0x2c, - 0xb2, 0xea, 0x7b, 0xce, 0xfd, 0x9f, 0x7b, 0xfe, 0xa7, 0x1a, 0x9a, 0xc1, 0xe1, 0x72, 0x10, 0xfa, - 0xb1, 0x2f, 0xca, 0xc1, 0xe1, 0x40, 0x33, 0x03, 0x87, 0xc1, 0xc1, 0xdd, 0x63, 0x27, 0x3e, 0x99, - 0x1e, 0x2e, 0x5b, 0xfe, 0xe4, 0x81, 0x7d, 0x1c, 0x9a, 0xc1, 0xc9, 0x7d, 0xc7, 0x7f, 0x70, 0x68, - 0xda, 0xc7, 0x32, 0x7c, 0x70, 0xf6, 0xc9, 0x83, 0xe0, 0xf0, 0x41, 0x32, 0x75, 0x70, 0x3f, 0x37, - 0xf6, 0xd8, 0x3f, 0xf6, 0x1f, 0x10, 0xfa, 0x70, 0x7a, 0x44, 0x10, 0x01, 0xd4, 0xe2, 0xe1, 0xfa, - 0x00, 0xaa, 0xdb, 0x4e, 0x14, 0x0b, 0x01, 0xd5, 0xa9, 0x63, 0x47, 0xfd, 0xd2, 0xad, 0xca, 0x52, - 0xdd, 0xa0, 0xb6, 0xbe, 0x03, 0xda, 0xc8, 0x8c, 0x4e, 0x9f, 0x99, 0xee, 0x54, 0x8a, 0x1e, 0x54, - 0xce, 0x4c, 0xb7, 0x5f, 0xba, 0x55, 0x5a, 0x6a, 0x1b, 0xd8, 0x14, 0xcb, 0xd0, 0x3c, 0x33, 0xdd, - 0x71, 0x7c, 0x11, 0xc8, 0x7e, 0xf9, 0x56, 0x69, 0xa9, 0xbb, 0x72, 0x75, 0x39, 0x38, 0x5c, 0xde, - 0xf7, 0xa3, 0xd8, 0xf1, 0x8e, 0x97, 0x9f, 0x99, 0xee, 0xe8, 0x22, 0x90, 0x46, 0xe3, 0x8c, 0x1b, - 0xfa, 0x1e, 0xb4, 0x0e, 0x42, 0x6b, 0x73, 0xea, 0x59, 0xb1, 0xe3, 0x7b, 0xb8, 0xa3, 0x67, 0x4e, - 0x24, 0xad, 0xa8, 0x19, 0xd4, 0x46, 0x9c, 0x19, 0x1e, 0x47, 0xfd, 0xca, 0xad, 0x0a, 0xe2, 0xb0, - 0x2d, 0xfa, 0xd0, 0x70, 0xa2, 0x75, 0x7f, 0xea, 0xc5, 0xfd, 0xea, 0xad, 0xd2, 0x52, 0xd3, 0x48, - 0x40, 0xfd, 0xcf, 0x2a, 0x50, 0xfb, 0xfe, 0x54, 0x86, 0x17, 0x34, 0x2f, 0x8e, 0xc3, 0x64, 0x2d, - 0x6c, 0x8b, 0x37, 0xa0, 0xe6, 0x9a, 0xde, 0x71, 0xd4, 0x2f, 0xd3, 0x62, 0x0c, 0x88, 0xeb, 0xa0, - 0x99, 0x47, 0xb1, 0x0c, 0xc7, 0x53, 0xc7, 0xee, 0x57, 0x6e, 0x95, 0x96, 0xea, 0x46, 0x93, 0x10, - 0x4f, 0x1d, 0x5b, 0xbc, 0x0d, 0x4d, 0xdb, 0x1f, 0x5b, 0xf9, 0xbd, 0x6c, 0x9f, 0xf6, 0x12, 0xb7, - 0xa1, 0x39, 0x75, 0xec, 0xb1, 0xeb, 0x44, 0x71, 0xbf, 0x76, 0xab, 0xb4, 0xd4, 0x5a, 0x69, 0xe2, - 0x65, 0x91, 0x76, 0x46, 0x63, 0xea, 0xd8, 0x44, 0xc4, 0xbb, 0xd0, 0x8c, 0x42, 0x6b, 0x7c, 0x34, - 0xf5, 0xac, 0x7e, 0x9d, 0x06, 0x5d, 0xc1, 0x41, 0xb9, 0x5b, 0x1b, 0x8d, 0x88, 0x01, 0xbc, 0x56, - 0x28, 0xcf, 0x64, 0x18, 0xc9, 0x7e, 0x83, 0xb7, 0x52, 0xa0, 0x78, 0x08, 0xad, 0x23, 0xd3, 0x92, - 0xf1, 0x38, 0x30, 0x43, 0x73, 0xd2, 0x6f, 0x66, 0x0b, 0x6d, 0x22, 0x7a, 0x1f, 0xb1, 0x91, 0x01, - 0x47, 0x29, 0x20, 0x3e, 0x86, 0x0e, 0x41, 0xd1, 0xf8, 0xc8, 0x71, 0x63, 0x19, 0xf6, 0x35, 0x9a, - 0xd3, 0xa5, 0x39, 0x84, 0x19, 0x85, 0x52, 0x1a, 0x6d, 0x1e, 0xc4, 0x18, 0xf1, 0x2e, 0x80, 0x3c, - 0x0f, 0x4c, 0xcf, 0x1e, 0x9b, 0xae, 0xdb, 0x07, 0x3a, 0x83, 0xc6, 0x98, 0x55, 0xd7, 0x15, 0x6f, - 0xe1, 0xf9, 0x4c, 0x7b, 0x1c, 0x47, 0xfd, 0xce, 0xad, 0xd2, 0x52, 0xd5, 0xa8, 0x23, 0x38, 0x8a, - 0x90, 0xae, 0x96, 0x69, 0x9d, 0xc8, 0x7e, 0xf7, 0x56, 0x69, 0xa9, 0x66, 0x30, 0x80, 0xd8, 0x23, - 0x27, 0x8c, 0xe2, 0xfe, 0x15, 0xc6, 0x12, 0x20, 0xae, 0x41, 0xdd, 0x3f, 0x3a, 0x8a, 0x64, 0xdc, - 0xef, 0x11, 0x5a, 0x41, 0xfa, 0x0a, 0x68, 0xc4, 0x55, 0x44, 0xb5, 0x3b, 0x50, 0x3f, 0x43, 0x80, - 0x99, 0xaf, 0xb5, 0xd2, 0xc1, 0x63, 0xa7, 0x8c, 0x67, 0xa8, 0x4e, 0xfd, 0x06, 0x34, 0xb7, 0x4d, - 0xef, 0x38, 0xe1, 0x56, 0x7c, 0x4e, 0x9a, 0xa0, 0x19, 0xd4, 0xd6, 0x7f, 0xaf, 0x02, 0x75, 0x43, - 0x46, 0x53, 0x37, 0x16, 0x1f, 0x00, 0xe0, 0x63, 0x4d, 0xcc, 0x38, 0x74, 0xce, 0xd5, 0xaa, 0xd9, - 0x73, 0x69, 0x53, 0xc7, 0xde, 0xa1, 0x2e, 0xf1, 0x10, 0xda, 0xb4, 0x7a, 0x32, 0xb4, 0x9c, 0x1d, - 0x20, 0x3d, 0x9f, 0xd1, 0xa2, 0x21, 0x6a, 0xc6, 0x35, 0xa8, 0x13, 0x7f, 0x30, 0x8f, 0x76, 0x0c, - 0x05, 0x89, 0x3b, 0xd0, 0x75, 0xbc, 0x18, 0xdf, 0xcf, 0x8a, 0xc7, 0xb6, 0x8c, 0x12, 0x06, 0xea, - 0xa4, 0xd8, 0x0d, 0x19, 0xc5, 0xe2, 0x11, 0xf0, 0x23, 0x24, 0x1b, 0xd6, 0x68, 0xc3, 0x6e, 0xfa, - 0xb8, 0x11, 0xef, 0x48, 0x63, 0xd4, 0x8e, 0xf7, 0xa1, 0x85, 0xf7, 0x4b, 0x66, 0xd4, 0x69, 0x46, - 0x9b, 0x6e, 0xa3, 0xc8, 0x61, 0x00, 0x0e, 0x50, 0xc3, 0x91, 0x34, 0xc8, 0xa4, 0xcc, 0x54, 0xd4, - 0x16, 0xab, 0xd0, 0x91, 0xe7, 0x71, 0x68, 0x8e, 0x27, 0x32, 0x0e, 0x1d, 0x2b, 0xea, 0x37, 0x69, - 0x91, 0x77, 0x70, 0x11, 0x26, 0xd9, 0xf2, 0x10, 0xfb, 0x77, 0xb8, 0x7b, 0xe8, 0xc5, 0xe1, 0x85, - 0xd1, 0x96, 0x39, 0xd4, 0xe0, 0xff, 0xc0, 0xe2, 0xa5, 0x21, 0xa8, 0x13, 0x4e, 0xe5, 0x85, 0x92, - 0x3a, 0x6c, 0x22, 0x1b, 0x10, 0xb5, 0x48, 0x21, 0x54, 0x0d, 0x06, 0x3e, 0x2b, 0x7f, 0xa7, 0xa4, - 0x0f, 0xa1, 0xb6, 0x17, 0xda, 0x32, 0x9c, 0x2b, 0xab, 0x02, 0xaa, 0xb6, 0x8c, 0x2c, 0x9a, 0xd5, - 0x34, 0xa8, 0x9d, 0xc9, 0x6f, 0x25, 0x27, 0xbf, 0xfa, 0xef, 0x97, 0xa0, 0x75, 0xe0, 0x87, 0xf1, - 0x8e, 0x8c, 0x22, 0xf3, 0x58, 0x8a, 0x9b, 0x50, 0xf3, 0x71, 0x59, 0xf5, 0xca, 0x1a, 0x5e, 0x89, - 0xf6, 0x31, 0x18, 0x3f, 0xc3, 0x0b, 0xe5, 0x17, 0xf3, 0x02, 0xf2, 0x35, 0x49, 0x7e, 0x45, 0xf1, - 0x35, 0xc9, 0x7d, 0xc6, 0xc1, 0xd5, 0x3c, 0x07, 0xbf, 0x50, 0x3c, 0xf4, 0x6f, 0x03, 0xe0, 0xf9, - 0xbe, 0x21, 0x27, 0xea, 0x3f, 0x2f, 0x41, 0xcb, 0x30, 0x8f, 0xe2, 0x75, 0xdf, 0x8b, 0xe5, 0x79, - 0x2c, 0xba, 0x50, 0x76, 0x6c, 0xa2, 0x51, 0xdd, 0x28, 0x3b, 0x36, 0x9e, 0xee, 0x38, 0xf4, 0xa7, - 0x01, 0x91, 0xa8, 0x63, 0x30, 0x40, 0xb4, 0xb4, 0xed, 0x90, 0x8e, 0x8c, 0xb4, 0xb4, 0xed, 0x50, - 0xdc, 0x84, 0x56, 0xe4, 0x99, 0x41, 0x74, 0xe2, 0xc7, 0x78, 0xba, 0x2a, 0x9d, 0x0e, 0x12, 0xd4, - 0x28, 0x42, 0xc1, 0x77, 0xa2, 0xb1, 0x2b, 0xcd, 0xd0, 0x93, 0x21, 0x29, 0xb3, 0xa6, 0xa1, 0x39, - 0xd1, 0x36, 0x23, 0xf4, 0x9f, 0x57, 0xa0, 0xbe, 0x23, 0x27, 0x87, 0x32, 0xbc, 0x74, 0x88, 0x87, - 0xd0, 0xa4, 0x7d, 0xc7, 0x8e, 0xcd, 0xe7, 0x58, 0x7b, 0xf3, 0xf9, 0x57, 0x37, 0x17, 0x09, 0xb7, - 0x65, 0x7f, 0xe4, 0x4f, 0x9c, 0x58, 0x4e, 0x82, 0xf8, 0xc2, 0x68, 0x28, 0xd4, 0xdc, 0x03, 0x5e, - 0x83, 0xba, 0x2b, 0x4d, 0x7c, 0x33, 0x16, 0x11, 0x05, 0x89, 0xfb, 0xd0, 0x30, 0x27, 0x63, 0x5b, - 0x9a, 0x36, 0x1f, 0x6a, 0xed, 0x8d, 0xe7, 0x5f, 0xdd, 0xec, 0x99, 0x93, 0x0d, 0x69, 0xe6, 0xd7, - 0xae, 0x33, 0x46, 0x7c, 0x8a, 0x72, 0x11, 0xc5, 0xe3, 0x69, 0x60, 0x9b, 0xb1, 0x24, 0x7d, 0x5b, - 0x5d, 0xeb, 0x3f, 0xff, 0xea, 0xe6, 0x1b, 0x88, 0x7e, 0x4a, 0xd8, 0xdc, 0x34, 0xc8, 0xb0, 0xa8, - 0x7b, 0x93, 0xeb, 0x2b, 0xdd, 0xab, 0x40, 0xb1, 0x05, 0x8b, 0x96, 0x3b, 0x8d, 0xd0, 0x40, 0x38, - 0xde, 0x91, 0x3f, 0xf6, 0x3d, 0xf7, 0x82, 0x1e, 0xb8, 0xb9, 0xf6, 0xee, 0xf3, 0xaf, 0x6e, 0xbe, - 0xad, 0x3a, 0xb7, 0xbc, 0x23, 0x7f, 0xcf, 0x73, 0x2f, 0x72, 0xeb, 0x5f, 0x99, 0xe9, 0x12, 0xff, - 0x17, 0xba, 0x47, 0x7e, 0x68, 0xc9, 0x71, 0x4a, 0xb2, 0x2e, 0xad, 0x33, 0x78, 0xfe, 0xd5, 0xcd, - 0x6b, 0xd4, 0xf3, 0xf8, 0x12, 0xdd, 0xda, 0x79, 0xbc, 0xfe, 0x4f, 0x65, 0xa8, 0x51, 0x5b, 0x3c, - 0x84, 0xc6, 0x84, 0x9e, 0x24, 0xd1, 0x91, 0xd7, 0x90, 0x87, 0xa8, 0x6f, 0x99, 0xdf, 0x4a, 0x09, - 0x6d, 0x32, 0x0c, 0x67, 0xc4, 0xe6, 0xa1, 0x2b, 0xe3, 0x48, 0xf1, 0x7c, 0x6e, 0xc6, 0x88, 0x3b, - 0xd4, 0x0c, 0x35, 0x6c, 0x96, 0x6f, 0x2a, 0x97, 0xf8, 0x66, 0x00, 0x4d, 0xeb, 0x44, 0x5a, 0xa7, - 0xd1, 0x74, 0xa2, 0xb8, 0x2a, 0x85, 0xc5, 0x6d, 0xe8, 0x50, 0x3b, 0xf0, 0x1d, 0x8f, 0xa6, 0xd7, - 0x68, 0x40, 0x3b, 0x43, 0x8e, 0xa2, 0xc1, 0x26, 0xb4, 0xf3, 0x87, 0xcd, 0xab, 0x8f, 0x2a, 0xab, - 0x8f, 0x5b, 0x79, 0xf5, 0xd1, 0x5a, 0x01, 0x3c, 0x33, 0x4f, 0xc9, 0xa9, 0x12, 0x5c, 0x27, 0x7f, - 0x85, 0x39, 0x6a, 0x68, 0xde, 0x3a, 0x3c, 0x25, 0xaf, 0x92, 0x7c, 0x68, 0x6c, 0x3b, 0x96, 0xf4, - 0x22, 0x72, 0x3c, 0xa6, 0x91, 0x4c, 0x95, 0x12, 0xb6, 0xf1, 0xbe, 0x13, 0xf3, 0x7c, 0xd7, 0xb7, - 0x65, 0xa4, 0xd4, 0x59, 0x0a, 0x63, 0x9f, 0x3c, 0x0f, 0x9c, 0xf0, 0x62, 0xc4, 0x94, 0xaa, 0x18, - 0x29, 0x8c, 0xdc, 0x25, 0x3d, 0xdc, 0xcc, 0x4e, 0x9c, 0x08, 0x05, 0xea, 0x7f, 0x54, 0x85, 0xf6, - 0x8f, 0x65, 0xe8, 0xef, 0x87, 0x7e, 0xe0, 0x47, 0xa6, 0x2b, 0x56, 0x8b, 0x34, 0xe7, 0xb7, 0xbd, - 0x85, 0xa7, 0xcd, 0x0f, 0x5b, 0x3e, 0x48, 0x1f, 0x81, 0xdf, 0x2c, 0xff, 0x2a, 0x3a, 0xd4, 0xf9, - 0xcd, 0xe7, 0xd0, 0x4c, 0xf5, 0xe0, 0x18, 0x7e, 0x65, 0x3a, 0x6b, 0x91, 0x1e, 0xaa, 0x07, 0xa5, - 0x72, 0x62, 0x9e, 0x3f, 0xdd, 0xda, 0x50, 0x6f, 0xab, 0x20, 0x45, 0x85, 0xd1, 0xb9, 0x37, 0x4a, - 0x1e, 0x35, 0x85, 0xf1, 0xa6, 0x48, 0x91, 0x68, 0x6b, 0xa3, 0xdf, 0xa6, 0xae, 0x04, 0x14, 0xef, - 0x80, 0x36, 0x31, 0xcf, 0x51, 0xa1, 0x6d, 0xd9, 0x2c, 0x9a, 0x46, 0x86, 0x10, 0xdf, 0x82, 0x4a, - 0x7c, 0xee, 0x91, 0xec, 0xa1, 0x67, 0x83, 0x8e, 0xee, 0xe8, 0xdc, 0x53, 0xaa, 0xcf, 0xc0, 0x3e, - 0x7c, 0x53, 0xcb, 0xb1, 0xc9, 0x91, 0xd1, 0x0c, 0x6c, 0x8a, 0x3b, 0xd0, 0x70, 0xf9, 0xb5, 0xc8, - 0x59, 0x69, 0xad, 0xb4, 0x58, 0x8f, 0x12, 0xca, 0x48, 0xfa, 0xc4, 0x47, 0xd0, 0x4c, 0xa8, 0xd3, - 0x6f, 0xd1, 0xb8, 0x5e, 0x42, 0xcf, 0x84, 0x8c, 0x46, 0x3a, 0x42, 0x3c, 0x04, 0xcd, 0x96, 0xae, - 0x8c, 0xe5, 0xd8, 0x63, 0x45, 0xde, 0x62, 0x27, 0x76, 0x83, 0x90, 0xbb, 0x91, 0x21, 0x7f, 0x3a, - 0x95, 0x51, 0x6c, 0x34, 0x6d, 0x85, 0x10, 0xef, 0x65, 0x82, 0xd5, 0xa5, 0xe7, 0xca, 0x13, 0x33, - 0xe9, 0x1a, 0x7c, 0x0f, 0xae, 0xcc, 0x3c, 0x5a, 0x9e, 0x4b, 0x3b, 0xaf, 0x30, 0x96, 0x5f, 0x54, - 0x9b, 0xcd, 0x9e, 0xa6, 0xff, 0x5b, 0x05, 0xae, 0x28, 0x81, 0x39, 0x71, 0x82, 0x83, 0x58, 0xa9, - 0x2e, 0x32, 0x4c, 0x8a, 0x57, 0xab, 0x46, 0x02, 0x8a, 0xff, 0x0d, 0x75, 0xd2, 0x34, 0x89, 0xc0, - 0xdf, 0xcc, 0x18, 0x21, 0x9d, 0xce, 0x0a, 0x40, 0x71, 0x91, 0x1a, 0x2e, 0x3e, 0x81, 0xda, 0x97, - 0x32, 0xf4, 0xd9, 0xd0, 0xb6, 0x56, 0x6e, 0xcc, 0x9b, 0x87, 0xe4, 0x53, 0xd3, 0x78, 0xf0, 0x7f, - 0x95, 0x5f, 0xe0, 0x9b, 0xf0, 0xcb, 0x7b, 0x68, 0x6c, 0x27, 0xfe, 0x99, 0xb4, 0xfb, 0x8d, 0x8c, - 0xe6, 0x8a, 0xc9, 0x93, 0xae, 0x84, 0x65, 0x9a, 0x73, 0x59, 0x46, 0x7b, 0x31, 0xcb, 0x0c, 0x36, - 0xa0, 0x95, 0xa3, 0xcb, 0x9c, 0x87, 0xba, 0x59, 0x54, 0x27, 0x5a, 0xaa, 0x4a, 0xf3, 0x5a, 0x69, - 0x03, 0x20, 0xa3, 0xd2, 0xaf, 0xab, 0xdb, 0xf4, 0xdf, 0x28, 0xc1, 0x95, 0x75, 0xdf, 0xf3, 0x24, - 0x85, 0x0b, 0xfc, 0xe6, 0x99, 0x88, 0x97, 0x5e, 0x28, 0xe2, 0x1f, 0x42, 0x2d, 0xc2, 0xc1, 0x6a, - 0xf5, 0xab, 0x73, 0x1e, 0xd1, 0xe0, 0x11, 0xa8, 0xe8, 0x27, 0xe6, 0xf9, 0x38, 0x90, 0x9e, 0xed, - 0x78, 0xc7, 0x89, 0xa2, 0x9f, 0x98, 0xe7, 0xfb, 0x8c, 0xd1, 0xff, 0xbc, 0x0c, 0xf0, 0xb9, 0x34, - 0xdd, 0xf8, 0x04, 0x8d, 0x19, 0xbe, 0xa8, 0xe3, 0x45, 0xb1, 0xe9, 0x59, 0x49, 0xb0, 0x96, 0xc2, - 0xf8, 0xa2, 0x68, 0xd3, 0x65, 0xc4, 0x2a, 0x52, 0x33, 0x12, 0x10, 0xf9, 0x03, 0xb7, 0x9b, 0x46, - 0xca, 0xf6, 0x2b, 0x28, 0x73, 0x64, 0xaa, 0x84, 0x56, 0x8e, 0x4c, 0x1f, 0x1a, 0x18, 0xfc, 0x38, - 0xbe, 0x47, 0x4c, 0xa3, 0x19, 0x09, 0x88, 0xeb, 0x4c, 0x83, 0xd8, 0x99, 0xb0, 0x85, 0xaf, 0x18, - 0x0a, 0xc2, 0x53, 0xa1, 0x45, 0x1f, 0x5a, 0x27, 0x3e, 0x29, 0x92, 0x8a, 0x91, 0xc2, 0xb8, 0x9a, - 0xef, 0x1d, 0xfb, 0x78, 0xbb, 0x26, 0x39, 0x8f, 0x09, 0xc8, 0x77, 0xb1, 0xe5, 0x39, 0x76, 0x69, - 0xd4, 0x95, 0xc2, 0x48, 0x17, 0x29, 0xc7, 0x47, 0xd2, 0x8c, 0xa7, 0xa1, 0x8c, 0xfa, 0x40, 0xdd, - 0x20, 0xe5, 0xa6, 0xc2, 0x88, 0x6f, 0x41, 0x1b, 0x09, 0x67, 0x46, 0x91, 0x73, 0xec, 0x49, 0x9b, - 0xd4, 0x4b, 0xd5, 0x40, 0x62, 0xae, 0x2a, 0x94, 0xfe, 0x97, 0x65, 0xa8, 0xb3, 0x2e, 0x28, 0x38, - 0x4b, 0xa5, 0xd7, 0x72, 0x96, 0xde, 0x01, 0x2d, 0x08, 0xa5, 0xed, 0x58, 0xc9, 0x3b, 0x6a, 0x46, - 0x86, 0xa0, 0x08, 0x0b, 0xbd, 0x03, 0xa2, 0x67, 0xd3, 0x60, 0x40, 0xe8, 0xd0, 0xf1, 0xbd, 0xb1, - 0xed, 0x44, 0xa7, 0xe3, 0xc3, 0x8b, 0x58, 0x46, 0x8a, 0x16, 0x2d, 0xdf, 0xdb, 0x70, 0xa2, 0xd3, - 0x35, 0x44, 0x21, 0x09, 0x59, 0x46, 0x48, 0x36, 0x9a, 0x86, 0x82, 0xc4, 0xc7, 0xa0, 0x91, 0x0f, - 0x4b, 0x4e, 0x8e, 0x46, 0xce, 0xc9, 0xb5, 0xe7, 0x5f, 0xdd, 0x14, 0x88, 0x9c, 0xf1, 0x6e, 0x9a, - 0x09, 0x0e, 0xbd, 0x34, 0x9c, 0x8c, 0xe6, 0x8a, 0x64, 0x98, 0xbd, 0x34, 0x44, 0x8d, 0xa2, 0xbc, - 0x97, 0xc6, 0x18, 0x71, 0x1f, 0xc4, 0xd4, 0xb3, 0xfc, 0x49, 0x80, 0x4c, 0x21, 0x6d, 0x75, 0xc8, - 0x16, 0x1d, 0x72, 0x31, 0xdf, 0x43, 0x47, 0xd5, 0xff, 0xb1, 0x0c, 0xed, 0x0d, 0x27, 0x94, 0x56, - 0x2c, 0xed, 0xa1, 0x7d, 0x2c, 0xf1, 0xec, 0xd2, 0x8b, 0x9d, 0xf8, 0x42, 0xb9, 0xa1, 0x0a, 0x4a, - 0xa3, 0x88, 0x72, 0x31, 0xe2, 0x67, 0x09, 0xab, 0x50, 0x92, 0x82, 0x01, 0xb1, 0x02, 0xc0, 0x31, - 0x1e, 0x25, 0x2a, 0xaa, 0x2f, 0x4e, 0x54, 0x68, 0x34, 0x0c, 0x9b, 0xe2, 0x6d, 0x4a, 0x6d, 0x4c, - 0x25, 0xbe, 0x5d, 0x8d, 0xf6, 0x6d, 0x10, 0xcc, 0x1e, 0x2d, 0x85, 0x9e, 0x0d, 0xde, 0x18, 0xdb, - 0xe2, 0x36, 0x94, 0xfd, 0x80, 0x88, 0xab, 0x96, 0xce, 0x5f, 0x61, 0x79, 0x2f, 0x30, 0xca, 0x7e, - 0x80, 0x52, 0xcc, 0xf1, 0x37, 0x31, 0x1e, 0x4a, 0x31, 0xda, 0x3d, 0x8a, 0xfa, 0x0c, 0xd5, 0x23, - 0x74, 0x68, 0x9b, 0xae, 0xeb, 0xff, 0x4c, 0xda, 0xfb, 0xa1, 0xb4, 0x13, 0x1e, 0x2c, 0xe0, 0x90, - 0x4b, 0x3c, 0x73, 0x22, 0xa3, 0xc0, 0xb4, 0xa4, 0x62, 0xc1, 0x0c, 0xa1, 0x5f, 0x83, 0xf2, 0x5e, - 0x20, 0x1a, 0x50, 0x39, 0x18, 0x8e, 0x7a, 0x0b, 0xd8, 0xd8, 0x18, 0x6e, 0xf7, 0xd0, 0xa2, 0xd4, - 0x7b, 0x0d, 0xfd, 0xeb, 0x32, 0x68, 0x3b, 0xd3, 0xd8, 0x44, 0xdd, 0x12, 0xe1, 0x2d, 0x8b, 0x1c, - 0x9a, 0xb1, 0xe2, 0xdb, 0xd0, 0x8c, 0x62, 0x33, 0x24, 0xaf, 0x84, 0xad, 0x53, 0x83, 0xe0, 0x51, - 0x24, 0xde, 0x87, 0x9a, 0xb4, 0x8f, 0x65, 0x62, 0x2e, 0x7a, 0xb3, 0xf7, 0x35, 0xb8, 0x5b, 0x2c, - 0x41, 0x3d, 0xb2, 0x4e, 0xe4, 0xc4, 0xec, 0x57, 0xb3, 0x81, 0x07, 0x84, 0x61, 0x37, 0xdc, 0x50, - 0xfd, 0xe2, 0x3d, 0xa8, 0xe1, 0xdb, 0x44, 0x2a, 0xb6, 0xa5, 0x68, 0x18, 0x9f, 0x41, 0x0d, 0xe3, - 0x4e, 0x64, 0x3c, 0x3b, 0xf4, 0x83, 0xb1, 0x1f, 0x10, 0xed, 0xbb, 0x2b, 0x6f, 0x90, 0x8e, 0x4b, - 0x6e, 0xb3, 0xbc, 0x11, 0xfa, 0xc1, 0x5e, 0x60, 0xd4, 0x6d, 0xfa, 0xc5, 0x28, 0x87, 0x86, 0x33, - 0x47, 0xb0, 0x51, 0xd0, 0x10, 0xc3, 0xe9, 0xac, 0x25, 0x68, 0x4e, 0x64, 0x6c, 0xda, 0x66, 0x6c, - 0x2a, 0xdb, 0xd0, 0x66, 0x95, 0xc9, 0x38, 0x23, 0xed, 0xd5, 0x1f, 0x40, 0x9d, 0x97, 0x16, 0x4d, - 0xa8, 0xee, 0xee, 0xed, 0x0e, 0x99, 0xac, 0xab, 0xdb, 0xdb, 0xbd, 0x12, 0xa2, 0x36, 0x56, 0x47, - 0xab, 0xbd, 0x32, 0xb6, 0x46, 0x3f, 0xda, 0x1f, 0xf6, 0x2a, 0xfa, 0xdf, 0x96, 0xa0, 0x99, 0xac, - 0x23, 0x3e, 0x03, 0x40, 0x11, 0x1e, 0x9f, 0x38, 0x5e, 0xea, 0xe0, 0x5d, 0xcf, 0xef, 0xb4, 0x8c, - 0xaf, 0xfa, 0x39, 0xf6, 0xb2, 0x79, 0x25, 0x89, 0x27, 0x78, 0x70, 0x00, 0xdd, 0x62, 0xe7, 0x1c, - 0x4f, 0xf7, 0x5e, 0xde, 0xaa, 0x74, 0x57, 0xde, 0x2c, 0x2c, 0x8d, 0x33, 0x89, 0xb5, 0x73, 0x06, - 0xe6, 0x3e, 0x34, 0x13, 0xb4, 0x68, 0x41, 0x63, 0x63, 0xb8, 0xb9, 0xfa, 0x74, 0x1b, 0x59, 0x05, - 0xa0, 0x7e, 0xb0, 0xb5, 0xfb, 0x78, 0x7b, 0xc8, 0xd7, 0xda, 0xde, 0x3a, 0x18, 0xf5, 0xca, 0xfa, - 0xef, 0x94, 0xa0, 0x99, 0x78, 0x32, 0xe2, 0x43, 0x74, 0x3e, 0xc8, 0x49, 0x53, 0x96, 0x88, 0xb2, - 0x52, 0xb9, 0xb0, 0xd5, 0x48, 0xfa, 0x51, 0x16, 0x49, 0xb1, 0x26, 0xbe, 0x0d, 0x01, 0xf9, 0xa8, - 0xb9, 0x52, 0x48, 0x2a, 0x09, 0xa8, 0xda, 0xbe, 0x27, 0x95, 0xc3, 0x4c, 0x6d, 0xe2, 0x41, 0xc7, - 0xb3, 0x64, 0x16, 0x4e, 0x34, 0x08, 0x1e, 0x45, 0x7a, 0xcc, 0x7e, 0x74, 0x7a, 0xb0, 0x74, 0xb7, - 0x52, 0x7e, 0xb7, 0x4b, 0x41, 0x49, 0xf9, 0x72, 0x50, 0x92, 0x19, 0xce, 0xda, 0xab, 0x0c, 0xa7, - 0xfe, 0x1f, 0x55, 0xe8, 0x1a, 0x32, 0x8a, 0xfd, 0x50, 0x2a, 0xbf, 0xf0, 0x65, 0x22, 0xf4, 0x2e, - 0x40, 0xc8, 0x83, 0xb3, 0xad, 0x35, 0x85, 0xe1, 0x68, 0xca, 0xf5, 0x2d, 0xe2, 0x5d, 0x65, 0x21, - 0x53, 0x58, 0x5c, 0x07, 0xed, 0xd0, 0xb4, 0x4e, 0x79, 0x59, 0xb6, 0x93, 0x4d, 0x46, 0xf0, 0xba, - 0xa6, 0x65, 0xc9, 0x28, 0x1a, 0x23, 0x2b, 0xb0, 0xb5, 0xd4, 0x18, 0xf3, 0x44, 0x5e, 0x60, 0x77, - 0x24, 0xad, 0x50, 0xc6, 0xd4, 0x5d, 0xe7, 0x6e, 0xc6, 0x60, 0xf7, 0x6d, 0xe8, 0x44, 0x32, 0x42, - 0xcb, 0x3a, 0x8e, 0xfd, 0x53, 0xe9, 0x29, 0x3d, 0xd6, 0x56, 0xc8, 0x11, 0xe2, 0x50, 0xc5, 0x98, - 0x9e, 0xef, 0x5d, 0x4c, 0xfc, 0x69, 0xa4, 0x6c, 0x46, 0x86, 0x10, 0xcb, 0x70, 0x55, 0x7a, 0x56, - 0x78, 0x11, 0xe0, 0x59, 0x71, 0x97, 0xf1, 0x91, 0xe3, 0x4a, 0xe5, 0xaa, 0x2f, 0x66, 0x5d, 0x4f, - 0xe4, 0xc5, 0xa6, 0xe3, 0x4a, 0x3c, 0xd1, 0x99, 0x39, 0x75, 0xe3, 0x31, 0x65, 0x02, 0x80, 0x4f, - 0x44, 0x98, 0x55, 0xdb, 0x0e, 0xc5, 0x5d, 0x58, 0xe4, 0xee, 0xd0, 0x77, 0xa5, 0x63, 0xf3, 0x62, - 0x2d, 0x1a, 0x75, 0x85, 0x3a, 0x0c, 0xc2, 0xd3, 0x52, 0xcb, 0x70, 0x95, 0xc7, 0xf2, 0x85, 0x92, - 0xd1, 0x6d, 0xde, 0x9a, 0xba, 0x0e, 0x54, 0x4f, 0x71, 0xeb, 0xc0, 0x8c, 0x4f, 0xc8, 0xbf, 0x4f, - 0xb6, 0xde, 0x37, 0xe3, 0x13, 0xb4, 0xf8, 0xdc, 0x7d, 0xe4, 0x48, 0x97, 0xe3, 0x73, 0xcd, 0xe0, - 0x19, 0x9b, 0x88, 0x41, 0x8b, 0xaf, 0x06, 0xf8, 0xe1, 0xc4, 0xe4, 0xe4, 0xa6, 0x66, 0xf0, 0xa4, - 0x4d, 0x42, 0xe1, 0x16, 0xea, 0xad, 0xbc, 0xe9, 0x84, 0xd2, 0x9c, 0x55, 0x43, 0xbd, 0xde, 0xee, - 0x74, 0x22, 0x3e, 0x84, 0x9e, 0xe3, 0x59, 0xa1, 0x9c, 0x48, 0x2f, 0x36, 0xdd, 0xf1, 0x51, 0xe8, - 0x4f, 0xfa, 0x8b, 0x34, 0xe8, 0x4a, 0x0e, 0xbf, 0x19, 0xfa, 0x13, 0x95, 0x97, 0x09, 0xcc, 0x30, - 0x76, 0x4c, 0xb7, 0x2f, 0x92, 0xbc, 0xcc, 0x3e, 0x23, 0xf4, 0xe7, 0x15, 0x68, 0xa6, 0x81, 0xe3, - 0x3d, 0xd0, 0x26, 0x89, 0xe6, 0x53, 0x2e, 0x5f, 0xa7, 0xa0, 0x0e, 0x8d, 0xac, 0x5f, 0xbc, 0x0b, - 0xe5, 0xd3, 0x33, 0xa5, 0x85, 0x3b, 0xcb, 0x5c, 0x36, 0x08, 0x0e, 0x3f, 0x59, 0x7e, 0xf2, 0xcc, - 0x28, 0x9f, 0x9e, 0x7d, 0x03, 0x09, 0x10, 0x1f, 0xc0, 0x15, 0xcb, 0x95, 0xa6, 0x37, 0xce, 0xfc, - 0x14, 0xe6, 0xb0, 0x2e, 0xa1, 0xf7, 0x53, 0x67, 0xe5, 0x0e, 0xd4, 0x6c, 0xe9, 0xc6, 0x66, 0x3e, - 0x7b, 0xbd, 0x17, 0x9a, 0x96, 0x2b, 0x37, 0x10, 0x6d, 0x70, 0x2f, 0x6a, 0xe1, 0x34, 0x58, 0xcb, - 0x69, 0xe1, 0x39, 0x81, 0x5a, 0x2a, 0xe1, 0x90, 0x97, 0xf0, 0x7b, 0xb0, 0x28, 0xcf, 0x03, 0x32, - 0x3d, 0xe3, 0x34, 0x37, 0xc1, 0x36, 0xb1, 0x97, 0x74, 0xac, 0x27, 0x39, 0x8a, 0x8f, 0x50, 0xf9, - 0x90, 0xf8, 0x11, 0xc3, 0xb4, 0x56, 0x84, 0xca, 0x7f, 0xe6, 0x04, 0xda, 0x48, 0x86, 0x88, 0x0f, - 0x41, 0xb3, 0x6c, 0x6b, 0xcc, 0x94, 0xe9, 0x64, 0x67, 0x5b, 0xdf, 0x58, 0x67, 0x92, 0x34, 0x2d, - 0xdb, 0x62, 0xff, 0xbc, 0x10, 0x44, 0x76, 0x5f, 0x27, 0x88, 0xcc, 0x9b, 0xd7, 0x5e, 0xc1, 0xbc, - 0x7e, 0x51, 0x6d, 0x36, 0x7a, 0x4d, 0xfd, 0x36, 0x34, 0x93, 0x8d, 0x50, 0x69, 0x46, 0xd2, 0x53, - 0x09, 0x02, 0x52, 0x9a, 0x08, 0x8e, 0x22, 0xdd, 0x82, 0xca, 0x93, 0x67, 0x07, 0xa4, 0x3b, 0xd1, - 0x8c, 0xd5, 0xc8, 0xeb, 0xa1, 0x76, 0xaa, 0x4f, 0xcb, 0x39, 0x7d, 0x7a, 0x83, 0x4d, 0x11, 0x3d, - 0x50, 0x92, 0x55, 0xcd, 0x61, 0x90, 0xc4, 0x6c, 0x86, 0xab, 0x9c, 0x70, 0x25, 0x40, 0xff, 0xf7, - 0x0a, 0x34, 0x94, 0xa7, 0x84, 0xe6, 0x67, 0x9a, 0x26, 0x04, 0xb1, 0x59, 0x0c, 0x61, 0x53, 0x97, - 0x2b, 0x5f, 0x19, 0xaa, 0xbc, 0xba, 0x32, 0x24, 0x3e, 0x83, 0x76, 0xc0, 0x7d, 0x79, 0x27, 0xed, - 0xad, 0xfc, 0x1c, 0xf5, 0x4b, 0xf3, 0x5a, 0x41, 0x06, 0x20, 0x29, 0x29, 0x3d, 0x1e, 0x9b, 0xc7, - 0x8a, 0x02, 0x0d, 0x84, 0x47, 0xe6, 0xf1, 0x6b, 0x79, 0x5c, 0x5d, 0x72, 0xdd, 0xda, 0xa4, 0xba, - 0xd1, 0x4b, 0xcb, 0xbf, 0x4c, 0xa7, 0xe8, 0xf8, 0x5c, 0x07, 0xcd, 0xf2, 0x27, 0x13, 0x87, 0xfa, - 0xba, 0x2a, 0x01, 0x46, 0x88, 0x51, 0xa4, 0xff, 0x76, 0x09, 0x1a, 0xea, 0x5e, 0x97, 0xcc, 0xea, - 0xda, 0xd6, 0xee, 0xaa, 0xf1, 0xa3, 0x5e, 0x09, 0xdd, 0x86, 0xad, 0xdd, 0x51, 0xaf, 0x2c, 0x34, - 0xa8, 0x6d, 0x6e, 0xef, 0xad, 0x8e, 0x7a, 0x15, 0x34, 0xb5, 0x6b, 0x7b, 0x7b, 0xdb, 0xbd, 0xaa, - 0x68, 0x43, 0x73, 0x63, 0x75, 0x34, 0x1c, 0x6d, 0xed, 0x0c, 0x7b, 0x35, 0x1c, 0xfb, 0x78, 0xb8, - 0xd7, 0xab, 0x63, 0xe3, 0xe9, 0xd6, 0x46, 0xaf, 0x81, 0xfd, 0xfb, 0xab, 0x07, 0x07, 0x3f, 0xd8, - 0x33, 0x36, 0x7a, 0x4d, 0x32, 0xd7, 0x23, 0x63, 0x6b, 0xf7, 0x71, 0x4f, 0xc3, 0xf6, 0xde, 0xda, - 0x17, 0xc3, 0xf5, 0x51, 0x0f, 0xb0, 0xfd, 0x8c, 0xd7, 0x6e, 0xeb, 0x8f, 0xa0, 0x95, 0xa3, 0x1b, - 0xae, 0x64, 0x0c, 0x37, 0x7b, 0x0b, 0xb8, 0xfd, 0xb3, 0xd5, 0xed, 0xa7, 0x68, 0xe9, 0xbb, 0x00, - 0xd4, 0x1c, 0x6f, 0xaf, 0xee, 0x3e, 0xee, 0x95, 0x95, 0x9f, 0xf8, 0x7d, 0x68, 0x3e, 0x75, 0xec, - 0x35, 0xd7, 0xb7, 0x4e, 0x91, 0x95, 0x0e, 0xcd, 0x48, 0x2a, 0xde, 0xa3, 0x36, 0x7a, 0xe5, 0x24, + 0x76, 0x28, 0xfb, 0xdf, 0x75, 0xfa, 0xc3, 0xe6, 0x95, 0x2d, 0xb7, 0x5b, 0xb6, 0xa4, 0x29, 0x59, + 0x36, 0x2d, 0x59, 0x94, 0x44, 0x7b, 0xde, 0x1b, 0x7b, 0x30, 0x78, 0x8f, 0x14, 0x9b, 0x32, 0x2d, + 0xfe, 0xa6, 0xd8, 0xd2, 0x7c, 0x80, 0xf7, 0x1a, 0xc5, 0xaa, 0x4b, 0xb2, 0x86, 0xd5, 0x55, 0x35, + 0x55, 0xd5, 0x1c, 0xd2, 0xbb, 0xac, 0x66, 0x93, 0xc5, 0x20, 0x59, 0x26, 0xc8, 0x22, 0xdb, 0x64, + 0x15, 0x24, 0x48, 0x10, 0x20, 0x59, 0x05, 0x41, 0x90, 0xd5, 0x2c, 0x13, 0x24, 0x31, 0x02, 0x4f, + 0x56, 0x5a, 0x04, 0x48, 0xb6, 0xd9, 0x04, 0xe7, 0x9c, 0x5b, 0xbf, 0x66, 0xeb, 0xe3, 0x09, 0xb2, + 0xc8, 0xaa, 0xef, 0x39, 0xf7, 0x7f, 0xee, 0xf9, 0x9f, 0x6a, 0x68, 0x06, 0x87, 0x2b, 0x41, 0xe8, + 0xc7, 0xbe, 0x28, 0x07, 0x87, 0x03, 0xcd, 0x0c, 0x1c, 0x06, 0x07, 0x77, 0x8e, 0x9d, 0xf8, 0x64, + 0x7a, 0xb8, 0x62, 0xf9, 0x93, 0xfb, 0xf6, 0x71, 0x68, 0x06, 0x27, 0xf7, 0x1c, 0xff, 0xfe, 0xa1, + 0x69, 0x1f, 0xcb, 0xf0, 0xfe, 0xd9, 0x27, 0xf7, 0x83, 0xc3, 0xfb, 0xc9, 0xd4, 0xc1, 0xbd, 0xdc, + 0xd8, 0x63, 0xff, 0xd8, 0xbf, 0x4f, 0xe8, 0xc3, 0xe9, 0x11, 0x41, 0x04, 0x50, 0x8b, 0x87, 0xeb, + 0x03, 0xa8, 0x6e, 0x3b, 0x51, 0x2c, 0x04, 0x54, 0xa7, 0x8e, 0x1d, 0xf5, 0x4b, 0x37, 0x2b, 0xcb, + 0x75, 0x83, 0xda, 0xfa, 0x0e, 0x68, 0x23, 0x33, 0x3a, 0x7d, 0x66, 0xba, 0x53, 0x29, 0x7a, 0x50, + 0x39, 0x33, 0xdd, 0x7e, 0xe9, 0x66, 0x69, 0xb9, 0x6d, 0x60, 0x53, 0xac, 0x40, 0xf3, 0xcc, 0x74, + 0xc7, 0xf1, 0x45, 0x20, 0xfb, 0xe5, 0x9b, 0xa5, 0xe5, 0xee, 0xea, 0x95, 0x95, 0xe0, 0x70, 0x65, + 0xdf, 0x8f, 0x62, 0xc7, 0x3b, 0x5e, 0x79, 0x66, 0xba, 0xa3, 0x8b, 0x40, 0x1a, 0x8d, 0x33, 0x6e, + 0xe8, 0x7b, 0xd0, 0x3a, 0x08, 0xad, 0xcd, 0xa9, 0x67, 0xc5, 0x8e, 0xef, 0xe1, 0x8e, 0x9e, 0x39, + 0x91, 0xb4, 0xa2, 0x66, 0x50, 0x1b, 0x71, 0x66, 0x78, 0x1c, 0xf5, 0x2b, 0x37, 0x2b, 0x88, 0xc3, + 0xb6, 0xe8, 0x43, 0xc3, 0x89, 0x1e, 0xf9, 0x53, 0x2f, 0xee, 0x57, 0x6f, 0x96, 0x96, 0x9b, 0x46, + 0x02, 0xea, 0x7f, 0x5a, 0x81, 0xda, 0xf7, 0xa7, 0x32, 0xbc, 0xa0, 0x79, 0x71, 0x1c, 0x26, 0x6b, + 0x61, 0x5b, 0xbc, 0x01, 0x35, 0xd7, 0xf4, 0x8e, 0xa3, 0x7e, 0x99, 0x16, 0x63, 0x40, 0x5c, 0x03, + 0xcd, 0x3c, 0x8a, 0x65, 0x38, 0x9e, 0x3a, 0x76, 0xbf, 0x72, 0xb3, 0xb4, 0x5c, 0x37, 0x9a, 0x84, + 0x78, 0xea, 0xd8, 0xe2, 0x6d, 0x68, 0xda, 0xfe, 0xd8, 0xca, 0xef, 0x65, 0xfb, 0xb4, 0x97, 0xb8, + 0x05, 0xcd, 0xa9, 0x63, 0x8f, 0x5d, 0x27, 0x8a, 0xfb, 0xb5, 0x9b, 0xa5, 0xe5, 0xd6, 0x6a, 0x13, + 0x2f, 0x8b, 0xb4, 0x33, 0x1a, 0x53, 0xc7, 0x26, 0x22, 0xde, 0x81, 0x66, 0x14, 0x5a, 0xe3, 0xa3, + 0xa9, 0x67, 0xf5, 0xeb, 0x34, 0x68, 0x11, 0x07, 0xe5, 0x6e, 0x6d, 0x34, 0x22, 0x06, 0xf0, 0x5a, + 0xa1, 0x3c, 0x93, 0x61, 0x24, 0xfb, 0x0d, 0xde, 0x4a, 0x81, 0xe2, 0x01, 0xb4, 0x8e, 0x4c, 0x4b, + 0xc6, 0xe3, 0xc0, 0x0c, 0xcd, 0x49, 0xbf, 0x99, 0x2d, 0xb4, 0x89, 0xe8, 0x7d, 0xc4, 0x46, 0x06, + 0x1c, 0xa5, 0x80, 0xf8, 0x18, 0x3a, 0x04, 0x45, 0xe3, 0x23, 0xc7, 0x8d, 0x65, 0xd8, 0xd7, 0x68, + 0x4e, 0x97, 0xe6, 0x10, 0x66, 0x14, 0x4a, 0x69, 0xb4, 0x79, 0x10, 0x63, 0xc4, 0xbb, 0x00, 0xf2, + 0x3c, 0x30, 0x3d, 0x7b, 0x6c, 0xba, 0x6e, 0x1f, 0xe8, 0x0c, 0x1a, 0x63, 0xd6, 0x5c, 0x57, 0xbc, + 0x85, 0xe7, 0x33, 0xed, 0x71, 0x1c, 0xf5, 0x3b, 0x37, 0x4b, 0xcb, 0x55, 0xa3, 0x8e, 0xe0, 0x28, + 0x42, 0xba, 0x5a, 0xa6, 0x75, 0x22, 0xfb, 0xdd, 0x9b, 0xa5, 0xe5, 0x9a, 0xc1, 0x00, 0x62, 0x8f, + 0x9c, 0x30, 0x8a, 0xfb, 0x8b, 0x8c, 0x25, 0x40, 0x5c, 0x85, 0xba, 0x7f, 0x74, 0x14, 0xc9, 0xb8, + 0xdf, 0x23, 0xb4, 0x82, 0xf4, 0x55, 0xd0, 0x88, 0xab, 0x88, 0x6a, 0xb7, 0xa1, 0x7e, 0x86, 0x00, + 0x33, 0x5f, 0x6b, 0xb5, 0x83, 0xc7, 0x4e, 0x19, 0xcf, 0x50, 0x9d, 0xfa, 0x75, 0x68, 0x6e, 0x9b, + 0xde, 0x71, 0xc2, 0xad, 0xf8, 0x9c, 0x34, 0x41, 0x33, 0xa8, 0xad, 0xff, 0x6e, 0x05, 0xea, 0x86, + 0x8c, 0xa6, 0x6e, 0x2c, 0x3e, 0x00, 0xc0, 0xc7, 0x9a, 0x98, 0x71, 0xe8, 0x9c, 0xab, 0x55, 0xb3, + 0xe7, 0xd2, 0xa6, 0x8e, 0xbd, 0x43, 0x5d, 0xe2, 0x01, 0xb4, 0x69, 0xf5, 0x64, 0x68, 0x39, 0x3b, + 0x40, 0x7a, 0x3e, 0xa3, 0x45, 0x43, 0xd4, 0x8c, 0xab, 0x50, 0x27, 0xfe, 0x60, 0x1e, 0xed, 0x18, + 0x0a, 0x12, 0xb7, 0xa1, 0xeb, 0x78, 0x31, 0xbe, 0x9f, 0x15, 0x8f, 0x6d, 0x19, 0x25, 0x0c, 0xd4, + 0x49, 0xb1, 0x1b, 0x32, 0x8a, 0xc5, 0x43, 0xe0, 0x47, 0x48, 0x36, 0xac, 0xd1, 0x86, 0xdd, 0xf4, + 0x71, 0x23, 0xde, 0x91, 0xc6, 0xa8, 0x1d, 0xef, 0x41, 0x0b, 0xef, 0x97, 0xcc, 0xa8, 0xd3, 0x8c, + 0x36, 0xdd, 0x46, 0x91, 0xc3, 0x00, 0x1c, 0xa0, 0x86, 0x23, 0x69, 0x90, 0x49, 0x99, 0xa9, 0xa8, + 0x2d, 0xd6, 0xa0, 0x23, 0xcf, 0xe3, 0xd0, 0x1c, 0x4f, 0x64, 0x1c, 0x3a, 0x56, 0xd4, 0x6f, 0xd2, + 0x22, 0xef, 0xe0, 0x22, 0x4c, 0xb2, 0x95, 0x21, 0xf6, 0xef, 0x70, 0xf7, 0xd0, 0x8b, 0xc3, 0x0b, + 0xa3, 0x2d, 0x73, 0xa8, 0xc1, 0xff, 0x81, 0xa5, 0x4b, 0x43, 0x50, 0x27, 0x9c, 0xca, 0x0b, 0x25, + 0x75, 0xd8, 0x44, 0x36, 0x20, 0x6a, 0x91, 0x42, 0xa8, 0x1a, 0x0c, 0x7c, 0x56, 0xfe, 0x4e, 0x49, + 0x1f, 0x42, 0x6d, 0x2f, 0xb4, 0x65, 0x38, 0x57, 0x56, 0x05, 0x54, 0x6d, 0x19, 0x59, 0x34, 0xab, + 0x69, 0x50, 0x3b, 0x93, 0xdf, 0x4a, 0x4e, 0x7e, 0xf5, 0xdf, 0x2b, 0x41, 0xeb, 0xc0, 0x0f, 0xe3, + 0x1d, 0x19, 0x45, 0xe6, 0xb1, 0x14, 0x37, 0xa0, 0xe6, 0xe3, 0xb2, 0xea, 0x95, 0x35, 0xbc, 0x12, + 0xed, 0x63, 0x30, 0x7e, 0x86, 0x17, 0xca, 0x2f, 0xe6, 0x05, 0xe4, 0x6b, 0x92, 0xfc, 0x8a, 0xe2, + 0x6b, 0x92, 0xfb, 0x8c, 0x83, 0xab, 0x79, 0x0e, 0x7e, 0xa1, 0x78, 0xe8, 0xdf, 0x06, 0xc0, 0xf3, + 0x7d, 0x43, 0x4e, 0xd4, 0x7f, 0x5e, 0x82, 0x96, 0x61, 0x1e, 0xc5, 0x8f, 0x7c, 0x2f, 0x96, 0xe7, + 0xb1, 0xe8, 0x42, 0xd9, 0xb1, 0x89, 0x46, 0x75, 0xa3, 0xec, 0xd8, 0x78, 0xba, 0xe3, 0xd0, 0x9f, + 0x06, 0x44, 0xa2, 0x8e, 0xc1, 0x00, 0xd1, 0xd2, 0xb6, 0x43, 0x3a, 0x32, 0xd2, 0xd2, 0xb6, 0x43, + 0x71, 0x03, 0x5a, 0x91, 0x67, 0x06, 0xd1, 0x89, 0x1f, 0xe3, 0xe9, 0xaa, 0x74, 0x3a, 0x48, 0x50, + 0xa3, 0x08, 0x05, 0xdf, 0x89, 0xc6, 0xae, 0x34, 0x43, 0x4f, 0x86, 0xa4, 0xcc, 0x9a, 0x86, 0xe6, + 0x44, 0xdb, 0x8c, 0xd0, 0x7f, 0x5e, 0x81, 0xfa, 0x8e, 0x9c, 0x1c, 0xca, 0xf0, 0xd2, 0x21, 0x1e, + 0x40, 0x93, 0xf6, 0x1d, 0x3b, 0x36, 0x9f, 0x63, 0xfd, 0xcd, 0xe7, 0x5f, 0xdd, 0x58, 0x22, 0xdc, + 0x96, 0xfd, 0x91, 0x3f, 0x71, 0x62, 0x39, 0x09, 0xe2, 0x0b, 0xa3, 0xa1, 0x50, 0x73, 0x0f, 0x78, + 0x15, 0xea, 0xae, 0x34, 0xf1, 0xcd, 0x58, 0x44, 0x14, 0x24, 0xee, 0x41, 0xc3, 0x9c, 0x8c, 0x6d, + 0x69, 0xda, 0x7c, 0xa8, 0xf5, 0x37, 0x9e, 0x7f, 0x75, 0xa3, 0x67, 0x4e, 0x36, 0xa4, 0x99, 0x5f, + 0xbb, 0xce, 0x18, 0xf1, 0x29, 0xca, 0x45, 0x14, 0x8f, 0xa7, 0x81, 0x6d, 0xc6, 0x92, 0xf4, 0x6d, + 0x75, 0xbd, 0xff, 0xfc, 0xab, 0x1b, 0x6f, 0x20, 0xfa, 0x29, 0x61, 0x73, 0xd3, 0x20, 0xc3, 0xa2, + 0xee, 0x4d, 0xae, 0xaf, 0x74, 0xaf, 0x02, 0xc5, 0x16, 0x2c, 0x59, 0xee, 0x34, 0x42, 0x03, 0xe1, + 0x78, 0x47, 0xfe, 0xd8, 0xf7, 0xdc, 0x0b, 0x7a, 0xe0, 0xe6, 0xfa, 0xbb, 0xcf, 0xbf, 0xba, 0xf1, + 0xb6, 0xea, 0xdc, 0xf2, 0x8e, 0xfc, 0x3d, 0xcf, 0xbd, 0xc8, 0xad, 0xbf, 0x38, 0xd3, 0x25, 0xfe, + 0x2f, 0x74, 0x8f, 0xfc, 0xd0, 0x92, 0xe3, 0x94, 0x64, 0x5d, 0x5a, 0x67, 0xf0, 0xfc, 0xab, 0x1b, + 0x57, 0xa9, 0xe7, 0xf1, 0x25, 0xba, 0xb5, 0xf3, 0x78, 0xfd, 0x9f, 0xca, 0x50, 0xa3, 0xb6, 0x78, + 0x00, 0x8d, 0x09, 0x3d, 0x49, 0xa2, 0x23, 0xaf, 0x22, 0x0f, 0x51, 0xdf, 0x0a, 0xbf, 0x95, 0x12, + 0xda, 0x64, 0x18, 0xce, 0x88, 0xcd, 0x43, 0x57, 0xc6, 0x91, 0xe2, 0xf9, 0xdc, 0x8c, 0x11, 0x77, + 0xa8, 0x19, 0x6a, 0xd8, 0x2c, 0xdf, 0x54, 0x2e, 0xf1, 0xcd, 0x00, 0x9a, 0xd6, 0x89, 0xb4, 0x4e, + 0xa3, 0xe9, 0x44, 0x71, 0x55, 0x0a, 0x8b, 0x5b, 0xd0, 0xa1, 0x76, 0xe0, 0x3b, 0x1e, 0x4d, 0xaf, + 0xd1, 0x80, 0x76, 0x86, 0x1c, 0x45, 0x83, 0x4d, 0x68, 0xe7, 0x0f, 0x9b, 0x57, 0x1f, 0x55, 0x56, + 0x1f, 0x37, 0xf3, 0xea, 0xa3, 0xb5, 0x0a, 0x78, 0x66, 0x9e, 0x92, 0x53, 0x25, 0xb8, 0x4e, 0xfe, + 0x0a, 0x73, 0xd4, 0xd0, 0xbc, 0x75, 0x78, 0x4a, 0x5e, 0x25, 0xf9, 0xd0, 0xd8, 0x76, 0x2c, 0xe9, + 0x45, 0xe4, 0x78, 0x4c, 0x23, 0x99, 0x2a, 0x25, 0x6c, 0xe3, 0x7d, 0x27, 0xe6, 0xf9, 0xae, 0x6f, + 0xcb, 0x48, 0xa9, 0xb3, 0x14, 0xc6, 0x3e, 0x79, 0x1e, 0x38, 0xe1, 0xc5, 0x88, 0x29, 0x55, 0x31, + 0x52, 0x18, 0xb9, 0x4b, 0x7a, 0xb8, 0x99, 0x9d, 0x38, 0x11, 0x0a, 0xd4, 0xff, 0xb0, 0x0a, 0xed, + 0x1f, 0xcb, 0xd0, 0xdf, 0x0f, 0xfd, 0xc0, 0x8f, 0x4c, 0x57, 0xac, 0x15, 0x69, 0xce, 0x6f, 0x7b, + 0x13, 0x4f, 0x9b, 0x1f, 0xb6, 0x72, 0x90, 0x3e, 0x02, 0xbf, 0x59, 0xfe, 0x55, 0x74, 0xa8, 0xf3, + 0x9b, 0xcf, 0xa1, 0x99, 0xea, 0xc1, 0x31, 0xfc, 0xca, 0x74, 0xd6, 0x22, 0x3d, 0x54, 0x0f, 0x4a, + 0xe5, 0xc4, 0x3c, 0x7f, 0xba, 0xb5, 0xa1, 0xde, 0x56, 0x41, 0x8a, 0x0a, 0xa3, 0x73, 0x6f, 0x94, + 0x3c, 0x6a, 0x0a, 0xe3, 0x4d, 0x91, 0x22, 0xd1, 0xd6, 0x46, 0xbf, 0x4d, 0x5d, 0x09, 0x28, 0xde, + 0x01, 0x6d, 0x62, 0x9e, 0xa3, 0x42, 0xdb, 0xb2, 0x59, 0x34, 0x8d, 0x0c, 0x21, 0xbe, 0x05, 0x95, + 0xf8, 0xdc, 0x23, 0xd9, 0x43, 0xcf, 0x06, 0x1d, 0xdd, 0xd1, 0xb9, 0xa7, 0x54, 0x9f, 0x81, 0x7d, + 0xf8, 0xa6, 0x96, 0x63, 0x93, 0x23, 0xa3, 0x19, 0xd8, 0x14, 0xb7, 0xa1, 0xe1, 0xf2, 0x6b, 0x91, + 0xb3, 0xd2, 0x5a, 0x6d, 0xb1, 0x1e, 0x25, 0x94, 0x91, 0xf4, 0x89, 0x8f, 0xa0, 0x99, 0x50, 0xa7, + 0xdf, 0xa2, 0x71, 0xbd, 0x84, 0x9e, 0x09, 0x19, 0x8d, 0x74, 0x84, 0x78, 0x00, 0x9a, 0x2d, 0x5d, + 0x19, 0xcb, 0xb1, 0xc7, 0x8a, 0xbc, 0xc5, 0x4e, 0xec, 0x06, 0x21, 0x77, 0x23, 0x43, 0xfe, 0x74, + 0x2a, 0xa3, 0xd8, 0x68, 0xda, 0x0a, 0x21, 0xde, 0xcb, 0x04, 0xab, 0x4b, 0xcf, 0x95, 0x27, 0x66, + 0xd2, 0x35, 0xf8, 0x1e, 0x2c, 0xce, 0x3c, 0x5a, 0x9e, 0x4b, 0x3b, 0xaf, 0x30, 0x96, 0x5f, 0x54, + 0x9b, 0xcd, 0x9e, 0xa6, 0xff, 0x5b, 0x05, 0x16, 0x95, 0xc0, 0x9c, 0x38, 0xc1, 0x41, 0xac, 0x54, + 0x17, 0x19, 0x26, 0xc5, 0xab, 0x55, 0x23, 0x01, 0xc5, 0xff, 0x86, 0x3a, 0x69, 0x9a, 0x44, 0xe0, + 0x6f, 0x64, 0x8c, 0x90, 0x4e, 0x67, 0x05, 0xa0, 0xb8, 0x48, 0x0d, 0x17, 0x9f, 0x40, 0xed, 0x4b, + 0x19, 0xfa, 0x6c, 0x68, 0x5b, 0xab, 0xd7, 0xe7, 0xcd, 0x43, 0xf2, 0xa9, 0x69, 0x3c, 0xf8, 0xbf, + 0xca, 0x2f, 0xf0, 0x4d, 0xf8, 0xe5, 0x3d, 0x34, 0xb6, 0x13, 0xff, 0x4c, 0xda, 0xfd, 0x46, 0x46, + 0x73, 0xc5, 0xe4, 0x49, 0x57, 0xc2, 0x32, 0xcd, 0xb9, 0x2c, 0xa3, 0xbd, 0x98, 0x65, 0x06, 0x1b, + 0xd0, 0xca, 0xd1, 0x65, 0xce, 0x43, 0xdd, 0x28, 0xaa, 0x13, 0x2d, 0x55, 0xa5, 0x79, 0xad, 0xb4, + 0x01, 0x90, 0x51, 0xe9, 0xd7, 0xd5, 0x6d, 0xfa, 0x6f, 0x94, 0x60, 0xf1, 0x91, 0xef, 0x79, 0x92, + 0xc2, 0x05, 0x7e, 0xf3, 0x4c, 0xc4, 0x4b, 0x2f, 0x14, 0xf1, 0x0f, 0xa1, 0x16, 0xe1, 0x60, 0xb5, + 0xfa, 0x95, 0x39, 0x8f, 0x68, 0xf0, 0x08, 0x54, 0xf4, 0x13, 0xf3, 0x7c, 0x1c, 0x48, 0xcf, 0x76, + 0xbc, 0xe3, 0x44, 0xd1, 0x4f, 0xcc, 0xf3, 0x7d, 0xc6, 0xe8, 0x7f, 0x56, 0x06, 0xf8, 0x5c, 0x9a, + 0x6e, 0x7c, 0x82, 0xc6, 0x0c, 0x5f, 0xd4, 0xf1, 0xa2, 0xd8, 0xf4, 0xac, 0x24, 0x58, 0x4b, 0x61, + 0x7c, 0x51, 0xb4, 0xe9, 0x32, 0x62, 0x15, 0xa9, 0x19, 0x09, 0x88, 0xfc, 0x81, 0xdb, 0x4d, 0x23, + 0x65, 0xfb, 0x15, 0x94, 0x39, 0x32, 0x55, 0x42, 0x2b, 0x47, 0xa6, 0x0f, 0x0d, 0x0c, 0x7e, 0x1c, + 0xdf, 0x23, 0xa6, 0xd1, 0x8c, 0x04, 0xc4, 0x75, 0xa6, 0x41, 0xec, 0x4c, 0xd8, 0xc2, 0x57, 0x0c, + 0x05, 0xe1, 0xa9, 0xd0, 0xa2, 0x0f, 0xad, 0x13, 0x9f, 0x14, 0x49, 0xc5, 0x48, 0x61, 0x5c, 0xcd, + 0xf7, 0x8e, 0x7d, 0xbc, 0x5d, 0x93, 0x9c, 0xc7, 0x04, 0xe4, 0xbb, 0xd8, 0xf2, 0x1c, 0xbb, 0x34, + 0xea, 0x4a, 0x61, 0xa4, 0x8b, 0x94, 0xe3, 0x23, 0x69, 0xc6, 0xd3, 0x50, 0x46, 0x7d, 0xa0, 0x6e, + 0x90, 0x72, 0x53, 0x61, 0xc4, 0xb7, 0xa0, 0x8d, 0x84, 0x33, 0xa3, 0xc8, 0x39, 0xf6, 0xa4, 0x4d, + 0xea, 0xa5, 0x6a, 0x20, 0x31, 0xd7, 0x14, 0x4a, 0xff, 0x8b, 0x32, 0xd4, 0x59, 0x17, 0x14, 0x9c, + 0xa5, 0xd2, 0x6b, 0x39, 0x4b, 0xef, 0x80, 0x16, 0x84, 0xd2, 0x76, 0xac, 0xe4, 0x1d, 0x35, 0x23, + 0x43, 0x50, 0x84, 0x85, 0xde, 0x01, 0xd1, 0xb3, 0x69, 0x30, 0x20, 0x74, 0xe8, 0xf8, 0xde, 0xd8, + 0x76, 0xa2, 0xd3, 0xf1, 0xe1, 0x45, 0x2c, 0x23, 0x45, 0x8b, 0x96, 0xef, 0x6d, 0x38, 0xd1, 0xe9, + 0x3a, 0xa2, 0x90, 0x84, 0x2c, 0x23, 0x24, 0x1b, 0x4d, 0x43, 0x41, 0xe2, 0x63, 0xd0, 0xc8, 0x87, + 0x25, 0x27, 0x47, 0x23, 0xe7, 0xe4, 0xea, 0xf3, 0xaf, 0x6e, 0x08, 0x44, 0xce, 0x78, 0x37, 0xcd, + 0x04, 0x87, 0x5e, 0x1a, 0x4e, 0x46, 0x73, 0x45, 0x32, 0xcc, 0x5e, 0x1a, 0xa2, 0x46, 0x51, 0xde, + 0x4b, 0x63, 0x8c, 0xb8, 0x07, 0x62, 0xea, 0x59, 0xfe, 0x24, 0x40, 0xa6, 0x90, 0xb6, 0x3a, 0x64, + 0x8b, 0x0e, 0xb9, 0x94, 0xef, 0xa1, 0xa3, 0xea, 0xff, 0x58, 0x86, 0xf6, 0x86, 0x13, 0x4a, 0x2b, + 0x96, 0xf6, 0xd0, 0x3e, 0x96, 0x78, 0x76, 0xe9, 0xc5, 0x4e, 0x7c, 0xa1, 0xdc, 0x50, 0x05, 0xa5, + 0x51, 0x44, 0xb9, 0x18, 0xf1, 0xb3, 0x84, 0x55, 0x28, 0x49, 0xc1, 0x80, 0x58, 0x05, 0xe0, 0x18, + 0x8f, 0x12, 0x15, 0xd5, 0x17, 0x27, 0x2a, 0x34, 0x1a, 0x86, 0x4d, 0xf1, 0x36, 0xa5, 0x36, 0xa6, + 0x12, 0xdf, 0xae, 0x46, 0xfb, 0x36, 0x08, 0x66, 0x8f, 0x96, 0x42, 0xcf, 0x06, 0x6f, 0x8c, 0x6d, + 0x71, 0x0b, 0xca, 0x7e, 0x40, 0xc4, 0x55, 0x4b, 0xe7, 0xaf, 0xb0, 0xb2, 0x17, 0x18, 0x65, 0x3f, + 0x40, 0x29, 0xe6, 0xf8, 0x9b, 0x18, 0x0f, 0xa5, 0x18, 0xed, 0x1e, 0x45, 0x7d, 0x86, 0xea, 0x11, + 0x3a, 0xb4, 0x4d, 0xd7, 0xf5, 0x7f, 0x26, 0xed, 0xfd, 0x50, 0xda, 0x09, 0x0f, 0x16, 0x70, 0xc8, + 0x25, 0x9e, 0x39, 0x91, 0x51, 0x60, 0x5a, 0x52, 0xb1, 0x60, 0x86, 0xd0, 0xaf, 0x42, 0x79, 0x2f, + 0x10, 0x0d, 0xa8, 0x1c, 0x0c, 0x47, 0xbd, 0x05, 0x6c, 0x6c, 0x0c, 0xb7, 0x7b, 0x68, 0x51, 0xea, + 0xbd, 0x86, 0xfe, 0x75, 0x19, 0xb4, 0x9d, 0x69, 0x6c, 0xa2, 0x6e, 0x89, 0xf0, 0x96, 0x45, 0x0e, + 0xcd, 0x58, 0xf1, 0x6d, 0x68, 0x46, 0xb1, 0x19, 0x92, 0x57, 0xc2, 0xd6, 0xa9, 0x41, 0xf0, 0x28, + 0x12, 0xef, 0x43, 0x4d, 0xda, 0xc7, 0x32, 0x31, 0x17, 0xbd, 0xd9, 0xfb, 0x1a, 0xdc, 0x2d, 0x96, + 0xa1, 0x1e, 0x59, 0x27, 0x72, 0x62, 0xf6, 0xab, 0xd9, 0xc0, 0x03, 0xc2, 0xb0, 0x1b, 0x6e, 0xa8, + 0x7e, 0xf1, 0x1e, 0xd4, 0xf0, 0x6d, 0x22, 0x15, 0xdb, 0x52, 0x34, 0x8c, 0xcf, 0xa0, 0x86, 0x71, + 0x27, 0x32, 0x9e, 0x1d, 0xfa, 0xc1, 0xd8, 0x0f, 0x88, 0xf6, 0xdd, 0xd5, 0x37, 0x48, 0xc7, 0x25, + 0xb7, 0x59, 0xd9, 0x08, 0xfd, 0x60, 0x2f, 0x30, 0xea, 0x36, 0xfd, 0x62, 0x94, 0x43, 0xc3, 0x99, + 0x23, 0xd8, 0x28, 0x68, 0x88, 0xe1, 0x74, 0xd6, 0x32, 0x34, 0x27, 0x32, 0x36, 0x6d, 0x33, 0x36, + 0x95, 0x6d, 0x68, 0xb3, 0xca, 0x64, 0x9c, 0x91, 0xf6, 0xea, 0xf7, 0xa1, 0xce, 0x4b, 0x8b, 0x26, + 0x54, 0x77, 0xf7, 0x76, 0x87, 0x4c, 0xd6, 0xb5, 0xed, 0xed, 0x5e, 0x09, 0x51, 0x1b, 0x6b, 0xa3, + 0xb5, 0x5e, 0x19, 0x5b, 0xa3, 0x1f, 0xed, 0x0f, 0x7b, 0x15, 0xfd, 0x6f, 0x4b, 0xd0, 0x4c, 0xd6, + 0x11, 0x9f, 0x01, 0xa0, 0x08, 0x8f, 0x4f, 0x1c, 0x2f, 0x75, 0xf0, 0xae, 0xe5, 0x77, 0x5a, 0xc1, + 0x57, 0xfd, 0x1c, 0x7b, 0xd9, 0xbc, 0x92, 0xc4, 0x13, 0x3c, 0x38, 0x80, 0x6e, 0xb1, 0x73, 0x8e, + 0xa7, 0x7b, 0x37, 0x6f, 0x55, 0xba, 0xab, 0x6f, 0x16, 0x96, 0xc6, 0x99, 0xc4, 0xda, 0x39, 0x03, + 0x73, 0x0f, 0x9a, 0x09, 0x5a, 0xb4, 0xa0, 0xb1, 0x31, 0xdc, 0x5c, 0x7b, 0xba, 0x8d, 0xac, 0x02, + 0x50, 0x3f, 0xd8, 0xda, 0x7d, 0xbc, 0x3d, 0xe4, 0x6b, 0x6d, 0x6f, 0x1d, 0x8c, 0x7a, 0x65, 0xfd, + 0xb7, 0x4b, 0xd0, 0x4c, 0x3c, 0x19, 0xf1, 0x21, 0x3a, 0x1f, 0xe4, 0xa4, 0x29, 0x4b, 0x44, 0x59, + 0xa9, 0x5c, 0xd8, 0x6a, 0x24, 0xfd, 0x28, 0x8b, 0xa4, 0x58, 0x13, 0xdf, 0x86, 0x80, 0x7c, 0xd4, + 0x5c, 0x29, 0x24, 0x95, 0x04, 0x54, 0x6d, 0xdf, 0x93, 0xca, 0x61, 0xa6, 0x36, 0xf1, 0xa0, 0xe3, + 0x59, 0x32, 0x0b, 0x27, 0x1a, 0x04, 0x8f, 0x22, 0x3d, 0x66, 0x3f, 0x3a, 0x3d, 0x58, 0xba, 0x5b, + 0x29, 0xbf, 0xdb, 0xa5, 0xa0, 0xa4, 0x7c, 0x39, 0x28, 0xc9, 0x0c, 0x67, 0xed, 0x55, 0x86, 0x53, + 0xff, 0x8f, 0x2a, 0x74, 0x0d, 0x19, 0xc5, 0x7e, 0x28, 0x95, 0x5f, 0xf8, 0x32, 0x11, 0x7a, 0x17, + 0x20, 0xe4, 0xc1, 0xd9, 0xd6, 0x9a, 0xc2, 0x70, 0x34, 0xe5, 0xfa, 0x16, 0xf1, 0xae, 0xb2, 0x90, + 0x29, 0x2c, 0xae, 0x81, 0x76, 0x68, 0x5a, 0xa7, 0xbc, 0x2c, 0xdb, 0xc9, 0x26, 0x23, 0x78, 0x5d, + 0xd3, 0xb2, 0x64, 0x14, 0x8d, 0x91, 0x15, 0xd8, 0x5a, 0x6a, 0x8c, 0x79, 0x22, 0x2f, 0xb0, 0x3b, + 0x92, 0x56, 0x28, 0x63, 0xea, 0xae, 0x73, 0x37, 0x63, 0xb0, 0xfb, 0x16, 0x74, 0x22, 0x19, 0xa1, + 0x65, 0x1d, 0xc7, 0xfe, 0xa9, 0xf4, 0x94, 0x1e, 0x6b, 0x2b, 0xe4, 0x08, 0x71, 0xa8, 0x62, 0x4c, + 0xcf, 0xf7, 0x2e, 0x26, 0xfe, 0x34, 0x52, 0x36, 0x23, 0x43, 0x88, 0x15, 0xb8, 0x22, 0x3d, 0x2b, + 0xbc, 0x08, 0xf0, 0xac, 0xb8, 0xcb, 0xf8, 0xc8, 0x71, 0xa5, 0x72, 0xd5, 0x97, 0xb2, 0xae, 0x27, + 0xf2, 0x62, 0xd3, 0x71, 0x25, 0x9e, 0xe8, 0xcc, 0x9c, 0xba, 0xf1, 0x98, 0x32, 0x01, 0xc0, 0x27, + 0x22, 0xcc, 0x9a, 0x6d, 0x87, 0xe2, 0x0e, 0x2c, 0x71, 0x77, 0xe8, 0xbb, 0xd2, 0xb1, 0x79, 0xb1, + 0x16, 0x8d, 0x5a, 0xa4, 0x0e, 0x83, 0xf0, 0xb4, 0xd4, 0x0a, 0x5c, 0xe1, 0xb1, 0x7c, 0xa1, 0x64, + 0x74, 0x9b, 0xb7, 0xa6, 0xae, 0x03, 0xd5, 0x53, 0xdc, 0x3a, 0x30, 0xe3, 0x13, 0xf2, 0xef, 0x93, + 0xad, 0xf7, 0xcd, 0xf8, 0x04, 0x2d, 0x3e, 0x77, 0x1f, 0x39, 0xd2, 0xe5, 0xf8, 0x5c, 0x33, 0x78, + 0xc6, 0x26, 0x62, 0xd0, 0xe2, 0xab, 0x01, 0x7e, 0x38, 0x31, 0x39, 0xb9, 0xa9, 0x19, 0x3c, 0x69, + 0x93, 0x50, 0xb8, 0x85, 0x7a, 0x2b, 0x6f, 0x3a, 0xa1, 0x34, 0x67, 0xd5, 0x50, 0xaf, 0xb7, 0x3b, + 0x9d, 0x88, 0x0f, 0xa1, 0xe7, 0x78, 0x56, 0x28, 0x27, 0xd2, 0x8b, 0x4d, 0x77, 0x7c, 0x14, 0xfa, + 0x93, 0xfe, 0x12, 0x0d, 0x5a, 0xcc, 0xe1, 0x37, 0x43, 0x7f, 0xa2, 0xf2, 0x32, 0x81, 0x19, 0xc6, + 0x8e, 0xe9, 0xf6, 0x45, 0x92, 0x97, 0xd9, 0x67, 0x84, 0xfe, 0xbc, 0x02, 0xcd, 0x34, 0x70, 0xbc, + 0x0b, 0xda, 0x24, 0xd1, 0x7c, 0xca, 0xe5, 0xeb, 0x14, 0xd4, 0xa1, 0x91, 0xf5, 0x8b, 0x77, 0xa1, + 0x7c, 0x7a, 0xa6, 0xb4, 0x70, 0x67, 0x85, 0xcb, 0x06, 0xc1, 0xe1, 0x27, 0x2b, 0x4f, 0x9e, 0x19, + 0xe5, 0xd3, 0xb3, 0x6f, 0x20, 0x01, 0xe2, 0x03, 0x58, 0xb4, 0x5c, 0x69, 0x7a, 0xe3, 0xcc, 0x4f, + 0x61, 0x0e, 0xeb, 0x12, 0x7a, 0x3f, 0x75, 0x56, 0x6e, 0x43, 0xcd, 0x96, 0x6e, 0x6c, 0xe6, 0xb3, + 0xd7, 0x7b, 0xa1, 0x69, 0xb9, 0x72, 0x03, 0xd1, 0x06, 0xf7, 0xa2, 0x16, 0x4e, 0x83, 0xb5, 0x9c, + 0x16, 0x9e, 0x13, 0xa8, 0xa5, 0x12, 0x0e, 0x79, 0x09, 0xbf, 0x0b, 0x4b, 0xf2, 0x3c, 0x20, 0xd3, + 0x33, 0x4e, 0x73, 0x13, 0x6c, 0x13, 0x7b, 0x49, 0xc7, 0xa3, 0x24, 0x47, 0xf1, 0x11, 0x2a, 0x1f, + 0x12, 0x3f, 0x62, 0x98, 0xd6, 0xaa, 0x50, 0xf9, 0xcf, 0x9c, 0x40, 0x1b, 0xc9, 0x10, 0xf1, 0x21, + 0x68, 0x96, 0x6d, 0x8d, 0x99, 0x32, 0x9d, 0xec, 0x6c, 0x8f, 0x36, 0x1e, 0x31, 0x49, 0x9a, 0x96, + 0x6d, 0xb1, 0x7f, 0x5e, 0x08, 0x22, 0xbb, 0xaf, 0x13, 0x44, 0xe6, 0xcd, 0x6b, 0xaf, 0x60, 0x5e, + 0xbf, 0xa8, 0x36, 0x1b, 0xbd, 0xa6, 0x7e, 0x0b, 0x9a, 0xc9, 0x46, 0xa8, 0x34, 0x23, 0xe9, 0xa9, + 0x04, 0x01, 0x29, 0x4d, 0x04, 0x47, 0x91, 0x6e, 0x41, 0xe5, 0xc9, 0xb3, 0x03, 0xd2, 0x9d, 0x68, + 0xc6, 0x6a, 0xe4, 0xf5, 0x50, 0x3b, 0xd5, 0xa7, 0xe5, 0x9c, 0x3e, 0xbd, 0xce, 0xa6, 0x88, 0x1e, + 0x28, 0xc9, 0xaa, 0xe6, 0x30, 0x48, 0x62, 0x36, 0xc3, 0x55, 0x4e, 0xb8, 0x12, 0xa0, 0xff, 0x7b, + 0x05, 0x1a, 0xca, 0x53, 0x42, 0xf3, 0x33, 0x4d, 0x13, 0x82, 0xd8, 0x2c, 0x86, 0xb0, 0xa9, 0xcb, + 0x95, 0xaf, 0x0c, 0x55, 0x5e, 0x5d, 0x19, 0x12, 0x9f, 0x41, 0x3b, 0xe0, 0xbe, 0xbc, 0x93, 0xf6, + 0x56, 0x7e, 0x8e, 0xfa, 0xa5, 0x79, 0xad, 0x20, 0x03, 0x90, 0x94, 0x94, 0x1e, 0x8f, 0xcd, 0x63, + 0x45, 0x81, 0x06, 0xc2, 0x23, 0xf3, 0xf8, 0xb5, 0x3c, 0xae, 0x2e, 0xb9, 0x6e, 0x6d, 0x52, 0xdd, + 0xe8, 0xa5, 0xe5, 0x5f, 0xa6, 0x53, 0x74, 0x7c, 0xae, 0x81, 0x66, 0xf9, 0x93, 0x89, 0x43, 0x7d, + 0x5d, 0x95, 0x00, 0x23, 0xc4, 0x28, 0xd2, 0x7f, 0xab, 0x04, 0x0d, 0x75, 0xaf, 0x4b, 0x66, 0x75, + 0x7d, 0x6b, 0x77, 0xcd, 0xf8, 0x51, 0xaf, 0x84, 0x6e, 0xc3, 0xd6, 0xee, 0xa8, 0x57, 0x16, 0x1a, + 0xd4, 0x36, 0xb7, 0xf7, 0xd6, 0x46, 0xbd, 0x0a, 0x9a, 0xda, 0xf5, 0xbd, 0xbd, 0xed, 0x5e, 0x55, + 0xb4, 0xa1, 0xb9, 0xb1, 0x36, 0x1a, 0x8e, 0xb6, 0x76, 0x86, 0xbd, 0x1a, 0x8e, 0x7d, 0x3c, 0xdc, + 0xeb, 0xd5, 0xb1, 0xf1, 0x74, 0x6b, 0xa3, 0xd7, 0xc0, 0xfe, 0xfd, 0xb5, 0x83, 0x83, 0x1f, 0xec, + 0x19, 0x1b, 0xbd, 0x26, 0x99, 0xeb, 0x91, 0xb1, 0xb5, 0xfb, 0xb8, 0xa7, 0x61, 0x7b, 0x6f, 0xfd, + 0x8b, 0xe1, 0xa3, 0x51, 0x0f, 0xb0, 0xfd, 0x8c, 0xd7, 0x6e, 0xeb, 0x0f, 0xa1, 0x95, 0xa3, 0x1b, + 0xae, 0x64, 0x0c, 0x37, 0x7b, 0x0b, 0xb8, 0xfd, 0xb3, 0xb5, 0xed, 0xa7, 0x68, 0xe9, 0xbb, 0x00, + 0xd4, 0x1c, 0x6f, 0xaf, 0xed, 0x3e, 0xee, 0x95, 0x95, 0x9f, 0xf8, 0x7d, 0x68, 0x3e, 0x75, 0xec, + 0x75, 0xd7, 0xb7, 0x4e, 0x91, 0x95, 0x0e, 0xcd, 0x48, 0x2a, 0xde, 0xa3, 0x36, 0x7a, 0xe5, 0x24, 0xc0, 0x91, 0x7a, 0x77, 0x05, 0x21, 0xf5, 0xbc, 0xe9, 0x64, 0x4c, 0x95, 0xc4, 0x0a, 0x9b, 0x43, 0x6f, 0x3a, 0x79, 0xea, 0xd8, 0x91, 0x7e, 0x0a, 0x8d, 0xa7, 0x8e, 0xbd, 0x6f, 0x5a, 0xa7, 0xa4, 0x32, 0x71, 0xe9, 0x71, 0xe4, 0x7c, 0x29, 0x95, 0xd9, 0xd4, 0x08, 0x73, 0xe0, 0x7c, 0x29, 0xc5, 0x7b, 0x50, 0x27, 0x20, 0x49, 0x64, 0x90, 0xd8, 0x25, 0xc7, 0x31, 0x54, 0x1f, 0x15, 0xf2, 0x5c, - 0xd7, 0xb7, 0xc6, 0xa1, 0x3c, 0xea, 0xbf, 0xc5, 0xaf, 0x41, 0x08, 0x43, 0x1e, 0xe9, 0xbf, 0x55, - 0x4a, 0x6f, 0x4e, 0xf5, 0xa2, 0x9b, 0x50, 0x0d, 0x4c, 0xeb, 0x54, 0x79, 0x2d, 0x2d, 0xb5, 0x20, + 0xd7, 0xb7, 0xc6, 0xa1, 0x3c, 0xea, 0xbf, 0xc5, 0xaf, 0x41, 0x08, 0x43, 0x1e, 0xe9, 0xbf, 0x59, + 0x4a, 0x6f, 0x4e, 0xf5, 0xa2, 0x1b, 0x50, 0x0d, 0x4c, 0xeb, 0x54, 0x79, 0x2d, 0x2d, 0xb5, 0x20, 0x1e, 0xc6, 0xa0, 0x0e, 0xf1, 0x01, 0x34, 0x15, 0x53, 0x25, 0xbb, 0xb6, 0x72, 0xdc, 0x67, 0xa4, 0x9d, 0x45, 0x26, 0xa8, 0x14, 0x99, 0x80, 0x62, 0xde, 0xc0, 0x75, 0x62, 0x16, 0x21, 0x14, 0x54, 0x82, 0xf4, 0x4f, 0x00, 0xb2, 0xd2, 0xdd, 0xfc, 0xaa, 0x89, 0xe9, 0x3a, 0x66, 0x12, 0x43, 0x33, 0xa0, 0xef, 0x42, 0x2b, 0x57, 0xf0, 0x43, 0xda, 0x9a, 0xae, 0x8b, 0xf6, 0x96, 0xf5, 0x40, 0xd3, 0x68, 0x98, 0xae, 0xfb, 0x44, 0x5e, 0x44, 0xe8, 0x40, 0x73, 0xad, 0xb0, 0x3c, 0x53, 0x4e, 0xa2, 0xa9, 0x06, 0x77, 0xea, 0x1f, 0x41, 0x7d, 0x33, 0x09, 0x33, 0x12, 0xc1, 0x28, 0xbd, 0x48, 0x30, - 0xf4, 0x4f, 0xd5, 0x99, 0xa9, 0x22, 0x25, 0xee, 0xa9, 0x9a, 0x64, 0xc4, 0x15, 0xd0, 0x52, 0x96, + 0xf4, 0x4f, 0xd5, 0x99, 0xa9, 0x22, 0x25, 0xee, 0xaa, 0x9a, 0x64, 0xc4, 0x15, 0xd0, 0x52, 0x96, 0x85, 0xe1, 0x41, 0xaa, 0x1c, 0x49, 0x83, 0xf5, 0x0d, 0x68, 0xbe, 0xb4, 0xca, 0xab, 0x08, 0x50, 0xce, 0x08, 0x30, 0xa7, 0xee, 0xab, 0xff, 0x04, 0x20, 0xab, 0x5d, 0x2a, 0x39, 0xe5, 0x55, 0x50, - 0x4e, 0xef, 0x42, 0xd3, 0x3a, 0x71, 0x5c, 0x3b, 0x94, 0x5e, 0xe1, 0xd6, 0x59, 0xb5, 0x33, 0xed, - 0x17, 0xb7, 0xa0, 0x4a, 0x25, 0xd9, 0x4a, 0xa6, 0xc5, 0xd3, 0x7a, 0x2c, 0xf5, 0xe8, 0xe7, 0xd0, - 0xe1, 0xc8, 0xe4, 0x35, 0xfc, 0xba, 0xa2, 0x1a, 0x2d, 0x5f, 0x52, 0xa3, 0xd7, 0xa0, 0x4e, 0xee, - 0x44, 0x72, 0x1b, 0x05, 0xbd, 0x40, 0xbd, 0xfe, 0x6e, 0x19, 0x80, 0xb7, 0xde, 0xf5, 0x6d, 0x59, + 0x4e, 0xef, 0x40, 0xd3, 0x3a, 0x71, 0x5c, 0x3b, 0x94, 0x5e, 0xe1, 0xd6, 0x59, 0xb5, 0x33, 0xed, + 0x17, 0x37, 0xa1, 0x4a, 0x25, 0xd9, 0x4a, 0xa6, 0xc5, 0xd3, 0x7a, 0x2c, 0xf5, 0xe8, 0xe7, 0xd0, + 0xe1, 0xc8, 0xe4, 0x35, 0xfc, 0xba, 0xa2, 0x1a, 0x2d, 0x5f, 0x52, 0xa3, 0x57, 0xa1, 0x4e, 0xee, + 0x44, 0x72, 0x1b, 0x05, 0xbd, 0x40, 0xbd, 0xfe, 0x4e, 0x19, 0x80, 0xb7, 0xde, 0xf5, 0x6d, 0x59, 0x4c, 0x01, 0x94, 0x66, 0x53, 0x00, 0x02, 0xaa, 0x69, 0xb5, 0x5d, 0x33, 0xa8, 0x9d, 0x19, 0x46, 0x95, 0x16, 0x60, 0xc3, 0xf8, 0x0e, 0x68, 0xe4, 0xde, 0x39, 0x5f, 0x52, 0x99, 0x05, 0x37, 0xcc, 0x10, 0xf9, 0xda, 0x73, 0xad, 0x58, 0x7b, 0x4e, 0x8b, 0x60, 0x75, 0x5e, 0x8d, 0x8b, 0x60, 0xf3, 0x6a, 0x8a, 0x94, 0x97, 0x89, 0x64, 0x18, 0x27, 0x49, 0x05, 0x86, 0xd2, 0xf8, 0x58, 0x53, 0x63, 0x4d, 0xce, 0xac, 0x78, 0xfe, 0xd8, 0xf2, 0xbd, 0x23, 0xd7, 0xb1, 0x62, 0x55, 0x6b, 0x06, 0xcf, - 0x5f, 0x57, 0x18, 0x5a, 0xcc, 0x73, 0x7e, 0x3a, 0x65, 0xc7, 0x0f, 0x17, 0x23, 0x48, 0xff, 0x0c, - 0xda, 0xc9, 0xbb, 0x50, 0x39, 0xed, 0x6e, 0x1a, 0x53, 0x96, 0xb2, 0x37, 0xcf, 0xc8, 0xb7, 0x56, - 0xee, 0x97, 0x92, 0xa8, 0x52, 0xff, 0xcd, 0x6a, 0x32, 0x59, 0x55, 0x7d, 0x5e, 0x4e, 0xdb, 0x62, - 0x9a, 0xa0, 0xfc, 0x5a, 0x69, 0x82, 0xef, 0x80, 0x66, 0x53, 0xe4, 0xeb, 0x9c, 0x25, 0x86, 0x6e, - 0x30, 0x1b, 0xe5, 0xaa, 0xd8, 0xd8, 0x39, 0x93, 0x46, 0x36, 0xf8, 0x15, 0xef, 0x93, 0xbe, 0x42, - 0x6d, 0xde, 0x2b, 0xd4, 0x7f, 0xcd, 0x57, 0xc8, 0x88, 0xdc, 0xcd, 0x13, 0x19, 0x9d, 0x5c, 0xcf, - 0xf7, 0xc6, 0xde, 0xd4, 0x75, 0xcd, 0x43, 0x57, 0xaa, 0xe7, 0x69, 0x79, 0xbe, 0xb7, 0xab, 0x50, - 0xe8, 0xa3, 0xe7, 0x87, 0xb0, 0x12, 0xe0, 0xa7, 0xba, 0x92, 0x1b, 0x47, 0xaa, 0x62, 0x09, 0x7a, + 0x7f, 0xa4, 0x30, 0xb4, 0x98, 0xe7, 0xfc, 0x74, 0xca, 0x8e, 0x1f, 0x2e, 0x46, 0x90, 0xfe, 0x19, + 0xb4, 0x93, 0x77, 0xa1, 0x72, 0xda, 0x9d, 0x34, 0xa6, 0x2c, 0x65, 0x6f, 0x9e, 0x91, 0x6f, 0xbd, + 0xdc, 0x2f, 0x25, 0x51, 0xa5, 0xfe, 0x97, 0xd5, 0x64, 0xb2, 0xaa, 0xfa, 0xbc, 0x9c, 0xb6, 0xc5, + 0x34, 0x41, 0xf9, 0xb5, 0xd2, 0x04, 0xdf, 0x01, 0xcd, 0xa6, 0xc8, 0xd7, 0x39, 0x4b, 0x0c, 0xdd, + 0x60, 0x36, 0xca, 0x55, 0xb1, 0xb1, 0x73, 0x26, 0x8d, 0x6c, 0xf0, 0x2b, 0xde, 0x27, 0x7d, 0x85, + 0xda, 0xbc, 0x57, 0xa8, 0xff, 0x9a, 0xaf, 0x90, 0x11, 0xb9, 0x9b, 0x27, 0x32, 0x3a, 0xb9, 0x9e, + 0xef, 0x8d, 0xbd, 0xa9, 0xeb, 0x9a, 0x87, 0xae, 0x54, 0xcf, 0xd3, 0xf2, 0x7c, 0x6f, 0x57, 0xa1, + 0xd0, 0x47, 0xcf, 0x0f, 0x61, 0x25, 0xc0, 0x4f, 0xb5, 0x98, 0x1b, 0x47, 0xaa, 0x62, 0x19, 0x7a, 0xfe, 0xe1, 0x4f, 0xa4, 0x15, 0x13, 0x25, 0xc7, 0x24, 0xfd, 0xec, 0xa0, 0x77, 0x19, 0x8f, 0xa4, - 0xdb, 0x45, 0x3d, 0x30, 0xc3, 0x16, 0x9d, 0x59, 0xb6, 0xd0, 0x3f, 0x05, 0x2d, 0xa5, 0x5e, 0x2e, - 0xfa, 0xd6, 0xa0, 0xb6, 0xb5, 0xbb, 0x31, 0xfc, 0x61, 0xaf, 0x84, 0xa6, 0xd6, 0x18, 0x3e, 0x1b, - 0x1a, 0x07, 0xc3, 0x5e, 0x19, 0x4d, 0xdf, 0xc6, 0x70, 0x7b, 0x38, 0x1a, 0xf6, 0x2a, 0xec, 0x46, - 0x51, 0x51, 0xc6, 0x75, 0x2c, 0x27, 0xd6, 0x0f, 0x00, 0xb2, 0x94, 0x02, 0x6a, 0xf1, 0xec, 0x70, - 0x2a, 0xa7, 0x19, 0x27, 0xc7, 0x5a, 0x4a, 0x05, 0xb8, 0xfc, 0xa2, 0xc4, 0x05, 0xf7, 0xeb, 0x2b, - 0xa0, 0xed, 0x98, 0xc1, 0xe7, 0x5c, 0xbe, 0xbc, 0x03, 0x5d, 0xf2, 0xdd, 0x93, 0xa8, 0x88, 0x95, - 0x6b, 0xdb, 0xe8, 0xa4, 0x58, 0xd4, 0xd5, 0xfa, 0x1f, 0x97, 0xe0, 0x8d, 0x1d, 0xff, 0x4c, 0xa6, - 0xbe, 0xf2, 0xbe, 0x79, 0xe1, 0xfa, 0xa6, 0xfd, 0x0a, 0xf6, 0xc4, 0xb0, 0xce, 0x9f, 0x52, 0x39, - 0x31, 0x29, 0xbe, 0x1a, 0x1a, 0x63, 0x1e, 0xab, 0x2f, 0x57, 0x64, 0x14, 0x53, 0xa7, 0x32, 0xbc, - 0x08, 0x63, 0xd7, 0x9b, 0x50, 0x8f, 0xcf, 0xbd, 0xac, 0x14, 0x5c, 0x8b, 0x29, 0x17, 0x3f, 0xd7, - 0x75, 0xae, 0xcd, 0x77, 0x9d, 0xf5, 0x75, 0xd0, 0x46, 0xe7, 0x94, 0x8d, 0x9e, 0x16, 0x9d, 0xd7, - 0xd2, 0x4b, 0x5c, 0xa4, 0xf2, 0x8c, 0x8b, 0xf4, 0x2f, 0x25, 0x68, 0xe5, 0x62, 0x00, 0xf1, 0x2d, - 0xa8, 0xc6, 0xe7, 0x5e, 0xf1, 0xab, 0x8f, 0x64, 0x13, 0x83, 0xba, 0x2e, 0x65, 0x5c, 0xcb, 0x97, - 0x32, 0xae, 0x62, 0x1b, 0xae, 0xb0, 0xa6, 0x4e, 0x2e, 0x91, 0x24, 0xa6, 0x6e, 0xcf, 0xc4, 0x1c, - 0x9c, 0xb1, 0x4f, 0xae, 0xa4, 0xb2, 0x2d, 0xdd, 0xe3, 0x02, 0x72, 0xb0, 0x0a, 0x57, 0xe7, 0x0c, - 0xfb, 0x26, 0xb5, 0x1b, 0xfd, 0x26, 0x74, 0x46, 0xe7, 0xde, 0xc8, 0x99, 0xc8, 0x28, 0x36, 0x27, - 0x01, 0xb9, 0x98, 0xca, 0xd2, 0x56, 0x8d, 0x72, 0x1c, 0xe9, 0xef, 0x43, 0x7b, 0x5f, 0xca, 0xd0, - 0x90, 0x51, 0xe0, 0x7b, 0xec, 0x4c, 0xa9, 0x4c, 0x39, 0x9b, 0x75, 0x05, 0xe9, 0xff, 0x1f, 0x34, - 0xc3, 0x3c, 0x8a, 0xd7, 0xcc, 0xd8, 0x3a, 0xf9, 0x26, 0xa9, 0x97, 0xf7, 0xa1, 0x11, 0x30, 0x4f, - 0xa9, 0xc8, 0xb0, 0x4d, 0xe6, 0x5d, 0xf1, 0x99, 0x91, 0x74, 0xea, 0xff, 0x0b, 0xba, 0xaa, 0x6c, - 0x95, 0x9c, 0x24, 0x57, 0xdb, 0x2a, 0xbd, 0xb0, 0xb6, 0xa5, 0x1f, 0x43, 0x27, 0x99, 0xc7, 0xc6, - 0xf2, 0xb5, 0xa6, 0x7d, 0xf3, 0x8f, 0x07, 0xf4, 0xff, 0x07, 0x57, 0x0f, 0xa6, 0x87, 0x91, 0x15, - 0x3a, 0x94, 0x4f, 0x48, 0xb6, 0x1b, 0x40, 0x33, 0x08, 0xe5, 0x91, 0x73, 0x2e, 0x13, 0x11, 0x4b, - 0x61, 0x71, 0x17, 0x1a, 0x13, 0xa4, 0x97, 0xcc, 0x84, 0x37, 0x8b, 0x77, 0x77, 0xb0, 0xc7, 0x48, - 0x06, 0xe8, 0xdf, 0x85, 0x37, 0x8a, 0xcb, 0x2b, 0x2a, 0xdc, 0x86, 0xca, 0xe9, 0x59, 0xa4, 0xc8, - 0xbc, 0x58, 0x88, 0x97, 0xe9, 0xab, 0x0d, 0xec, 0xd5, 0xff, 0xa2, 0x04, 0x15, 0x8c, 0xef, 0x73, - 0x9f, 0xc5, 0x55, 0xf9, 0xb3, 0xb8, 0xeb, 0xf9, 0xac, 0x3a, 0xc7, 0x5f, 0x59, 0xf6, 0xfc, 0x1d, - 0xd0, 0x8e, 0xfc, 0xf0, 0x67, 0x66, 0x68, 0x4b, 0x5b, 0x59, 0xec, 0x0c, 0x41, 0xae, 0xf6, 0x74, - 0x12, 0x28, 0xb5, 0x4f, 0x6d, 0x71, 0x47, 0xd9, 0x7c, 0x8e, 0x89, 0x16, 0x91, 0xb2, 0xbb, 0xd3, - 0xc9, 0xb2, 0x2b, 0xcd, 0x88, 0x8c, 0x10, 0xbb, 0x01, 0xfa, 0x3d, 0xd0, 0x52, 0x14, 0x2a, 0xc8, - 0xdd, 0x83, 0xf1, 0xd6, 0x06, 0x67, 0x2a, 0x31, 0x7a, 0x28, 0xa1, 0x72, 0x1c, 0xfd, 0x70, 0x77, - 0x3c, 0x3a, 0xe8, 0x95, 0xf5, 0x1f, 0x43, 0x2b, 0x91, 0x9f, 0x2d, 0x9b, 0xca, 0x72, 0x24, 0xc0, - 0x5b, 0x76, 0x41, 0x9e, 0xb7, 0x28, 0xbc, 0x93, 0x9e, 0xbd, 0x95, 0x08, 0x1e, 0x03, 0xc5, 0x1b, - 0xaa, 0x1a, 0x5f, 0x72, 0x43, 0x7d, 0x08, 0x8b, 0x06, 0x95, 0x17, 0xd0, 0x20, 0x27, 0x4f, 0x76, - 0x0d, 0xea, 0x9e, 0x6f, 0xcb, 0x74, 0x03, 0x05, 0xe1, 0xce, 0xea, 0xb1, 0x95, 0x4a, 0x4b, 0xdf, - 0x5e, 0xc2, 0x22, 0x6a, 0xc9, 0x22, 0xa3, 0x15, 0x52, 0xdf, 0xa5, 0x99, 0xd4, 0x37, 0x6e, 0xa2, - 0xaa, 0xdc, 0xec, 0x1f, 0x25, 0x95, 0xed, 0x01, 0x34, 0xed, 0x28, 0x26, 0xb1, 0x56, 0xba, 0x31, - 0x85, 0xf5, 0x07, 0x70, 0x75, 0x35, 0x08, 0xdc, 0x8b, 0xa4, 0x26, 0xa8, 0x36, 0xea, 0x67, 0x85, - 0xc3, 0x92, 0x8a, 0x29, 0x19, 0xd4, 0x37, 0xa1, 0x9d, 0x64, 0x27, 0x76, 0x64, 0x6c, 0x92, 0xc6, - 0x73, 0x9d, 0x42, 0x78, 0xde, 0x64, 0xc4, 0xa8, 0x98, 0x60, 0x9f, 0xb9, 0xdf, 0x32, 0xd4, 0x95, - 0x3a, 0x15, 0x50, 0xb5, 0x7c, 0x9b, 0x37, 0xaa, 0x19, 0xd4, 0x46, 0xae, 0x9a, 0x44, 0xc7, 0x89, - 0x87, 0x3c, 0x89, 0x8e, 0xf5, 0xbf, 0x2f, 0x43, 0x67, 0x8d, 0xb2, 0x4a, 0xc9, 0x19, 0x73, 0xb9, - 0xd4, 0x52, 0x21, 0x97, 0x9a, 0xcf, 0x9b, 0x96, 0x0b, 0x79, 0xd3, 0xc2, 0x81, 0x2a, 0x45, 0xb7, - 0xf6, 0x2d, 0x68, 0x4c, 0x3d, 0xe7, 0x3c, 0xb1, 0x13, 0x1a, 0xb9, 0x07, 0xe7, 0xa3, 0x48, 0xdc, - 0x82, 0x16, 0x9a, 0x12, 0xc7, 0xe3, 0x5c, 0x25, 0x27, 0x1c, 0xf3, 0xa8, 0x99, 0x8c, 0x64, 0xfd, - 0xe5, 0x19, 0xc9, 0xc6, 0x2b, 0x33, 0x92, 0xcd, 0x57, 0x65, 0x24, 0xb5, 0xd9, 0x8c, 0x64, 0xd1, - 0x25, 0x87, 0x4b, 0x2e, 0xf9, 0xbb, 0x00, 0xfc, 0x29, 0xce, 0xd1, 0xd4, 0x75, 0x95, 0xdf, 0xa2, - 0x11, 0x66, 0x73, 0xea, 0xba, 0xfa, 0x36, 0x74, 0x13, 0xd2, 0x2a, 0x15, 0xf0, 0x19, 0x5c, 0x51, - 0xb5, 0x06, 0x19, 0xaa, 0x24, 0x1b, 0x6b, 0x36, 0x92, 0x3f, 0x2e, 0x07, 0xa8, 0x1e, 0xa3, 0x6b, - 0xe7, 0xc1, 0x48, 0xff, 0x45, 0x09, 0x3a, 0x85, 0x11, 0xe2, 0x51, 0x56, 0xb9, 0x28, 0x91, 0x14, - 0xf7, 0x2f, 0xad, 0xf2, 0xf2, 0xea, 0x45, 0x79, 0xa6, 0x7a, 0xa1, 0xdf, 0x4f, 0x6b, 0x12, 0xaa, - 0x12, 0xb1, 0x90, 0x56, 0x22, 0x28, 0x79, 0xbf, 0x3a, 0x1a, 0x19, 0xbd, 0xb2, 0xa8, 0x43, 0x79, - 0xf7, 0xa0, 0x57, 0xd1, 0xff, 0xb4, 0x0c, 0x9d, 0xe1, 0x79, 0x40, 0x9f, 0xa5, 0xbd, 0x32, 0xbe, - 0xc9, 0xf1, 0x55, 0xb9, 0xc0, 0x57, 0x39, 0x0e, 0xa9, 0xa8, 0x52, 0x2c, 0x73, 0x08, 0x46, 0x3c, - 0x9c, 0x1f, 0x55, 0x9c, 0xc3, 0xd0, 0xff, 0x04, 0xce, 0x29, 0x68, 0x14, 0x98, 0x2d, 0xa6, 0x6d, - 0x43, 0x37, 0x21, 0x9b, 0x62, 0x8c, 0xd7, 0x12, 0x56, 0xfe, 0x18, 0xd6, 0x4d, 0x93, 0x6c, 0x0c, - 0xe8, 0x7f, 0x58, 0x06, 0x8d, 0xf9, 0x0c, 0x0f, 0xff, 0xa1, 0xd2, 0xeb, 0xa5, 0xac, 0x6e, 0x93, - 0x76, 0x2e, 0x3f, 0x91, 0x17, 0x99, 0x6e, 0x9f, 0x5b, 0xeb, 0x54, 0xa9, 0x38, 0xce, 0x40, 0x50, - 0x2a, 0xee, 0x3a, 0x68, 0xec, 0x96, 0x4d, 0x55, 0xd1, 0xa0, 0x6a, 0xb0, 0x9f, 0xf6, 0xd4, 0x21, - 0xcb, 0x12, 0xcb, 0x70, 0xa2, 0xde, 0x80, 0xda, 0xc5, 0x58, 0xaf, 0x93, 0x44, 0x19, 0x05, 0x8a, - 0x34, 0x66, 0x29, 0x72, 0x02, 0x0d, 0x75, 0x36, 0x74, 0xbd, 0x9f, 0xee, 0x3e, 0xd9, 0xdd, 0xfb, - 0xc1, 0x6e, 0x81, 0xfb, 0x52, 0xe7, 0xbc, 0x9c, 0x77, 0xce, 0x2b, 0x88, 0x5f, 0xdf, 0x7b, 0xba, - 0x3b, 0xea, 0x55, 0x45, 0x07, 0x34, 0x6a, 0x8e, 0x8d, 0xe1, 0xb3, 0x5e, 0x8d, 0x32, 0x59, 0xeb, - 0x9f, 0x0f, 0x77, 0x56, 0x7b, 0xf5, 0xb4, 0x8a, 0xd6, 0xd0, 0xff, 0xa0, 0x04, 0x8b, 0x4c, 0x90, - 0x7c, 0x22, 0x27, 0xff, 0x99, 0x7a, 0x95, 0x3f, 0x53, 0xff, 0xef, 0xcd, 0xdd, 0xe0, 0xa4, 0xa9, - 0x93, 0xd4, 0xad, 0x39, 0xc1, 0xd8, 0x9c, 0x3a, 0xaa, 0x5c, 0xfd, 0xd7, 0x25, 0x18, 0x70, 0x4c, - 0xf0, 0x38, 0x34, 0x83, 0x93, 0xef, 0x6f, 0x5f, 0xca, 0x22, 0xbc, 0xc8, 0x53, 0xbe, 0x03, 0x5d, - 0xfa, 0x90, 0xff, 0xa7, 0xee, 0x58, 0x45, 0xb4, 0xfc, 0xba, 0x1d, 0x85, 0xe5, 0x85, 0xc4, 0xc7, - 0xd0, 0xe6, 0x0f, 0xfe, 0x29, 0xe3, 0x5e, 0xa8, 0xb9, 0x16, 0x22, 0x92, 0x16, 0x8f, 0xe2, 0x0a, - 0xf1, 0xa3, 0x74, 0x52, 0x96, 0x70, 0xb8, 0x5c, 0x56, 0x55, 0x53, 0x46, 0x94, 0x86, 0x78, 0x00, - 0xd7, 0xe7, 0xde, 0x43, 0xb1, 0x7d, 0x2e, 0xf1, 0xcb, 0xdc, 0xa6, 0xff, 0x43, 0x09, 0x9a, 0x6b, - 0x53, 0xf7, 0x94, 0x8c, 0xe0, 0xbb, 0x00, 0xd2, 0x3e, 0x96, 0xea, 0xcb, 0xf9, 0x12, 0x29, 0x07, - 0x0d, 0x31, 0xfc, 0xed, 0xfc, 0x67, 0x00, 0x7c, 0xc7, 0xf1, 0xc4, 0x0c, 0xd4, 0x13, 0x51, 0x0d, - 0x34, 0x59, 0x40, 0xdd, 0x65, 0xc7, 0x0c, 0x54, 0x0d, 0x34, 0x4a, 0xe0, 0xac, 0x36, 0x5c, 0x79, - 0x49, 0x6d, 0x78, 0xb0, 0x0b, 0xdd, 0xe2, 0x12, 0x73, 0x92, 0x6c, 0xef, 0x17, 0xbf, 0xbf, 0xb9, - 0x4c, 0xc3, 0x9c, 0x0f, 0xff, 0x05, 0x5c, 0x99, 0x49, 0xde, 0xbf, 0x4c, 0x63, 0x16, 0x44, 0xa6, - 0x3c, 0x2b, 0x32, 0x1f, 0xc1, 0xe2, 0xc8, 0x8c, 0x4e, 0x55, 0x5c, 0x93, 0x19, 0xef, 0xd8, 0x8c, - 0x4e, 0xc7, 0x29, 0x51, 0xeb, 0x08, 0x6e, 0xd9, 0xfa, 0x23, 0x10, 0xf9, 0xd1, 0x8a, 0xfe, 0x18, - 0xaf, 0xe2, 0xf0, 0x89, 0x8c, 0xcd, 0xc4, 0xcb, 0x40, 0x04, 0x12, 0x6f, 0xe5, 0xaf, 0x4a, 0x50, - 0xc5, 0x40, 0x40, 0xdc, 0x07, 0xed, 0x73, 0x69, 0x86, 0xf1, 0xa1, 0x34, 0x63, 0x51, 0x70, 0xfa, - 0x07, 0x44, 0xb7, 0xec, 0x9b, 0x1e, 0x7d, 0xe1, 0x61, 0x49, 0x2c, 0xf3, 0x17, 0xc7, 0xc9, 0x97, - 0xd4, 0x9d, 0x24, 0xa0, 0xa0, 0x80, 0x63, 0x50, 0x98, 0xaf, 0x2f, 0x2c, 0xd1, 0xf8, 0x2f, 0x7c, - 0xc7, 0x5b, 0xe7, 0xef, 0x5c, 0xc5, 0x6c, 0x00, 0x32, 0x3b, 0x43, 0xdc, 0x87, 0xfa, 0x56, 0x84, - 0x91, 0xce, 0xe5, 0xa1, 0x44, 0xfc, 0x7c, 0x10, 0xa4, 0x2f, 0xac, 0xfc, 0x49, 0x0d, 0xaa, 0x3f, - 0x96, 0xa1, 0x2f, 0x3e, 0x82, 0x86, 0xfa, 0x02, 0x4a, 0xe4, 0xbe, 0x74, 0x1a, 0x50, 0x32, 0x66, - 0xe6, 0xd3, 0x28, 0xda, 0xa5, 0xc7, 0xef, 0x97, 0x95, 0xac, 0x44, 0xf6, 0x81, 0xd6, 0xa5, 0x43, - 0x7d, 0x0a, 0xbd, 0x83, 0x38, 0x94, 0xe6, 0x24, 0x37, 0xbc, 0x48, 0xaa, 0x79, 0xf5, 0x2f, 0xa2, - 0xd7, 0x3d, 0xa8, 0x73, 0x38, 0x39, 0x33, 0x61, 0xb6, 0xb8, 0x45, 0x83, 0x3f, 0x80, 0xd6, 0xc1, - 0x89, 0x3f, 0x75, 0xed, 0x03, 0x19, 0x9e, 0x49, 0x91, 0x8b, 0x88, 0x06, 0xb9, 0xb6, 0xbe, 0x20, - 0x1e, 0x41, 0x1d, 0x5f, 0x24, 0x9c, 0x88, 0xc5, 0x5c, 0xd4, 0xc4, 0x6c, 0x32, 0x10, 0x79, 0x54, - 0x42, 0x29, 0xf1, 0x01, 0x68, 0xec, 0xbe, 0xa3, 0xf3, 0xde, 0x50, 0x11, 0x01, 0x1f, 0x23, 0xe7, - 0xd6, 0xeb, 0x0b, 0x62, 0x09, 0x20, 0x17, 0x87, 0xbe, 0x6c, 0xe4, 0xc7, 0xd0, 0x59, 0x27, 0x4d, - 0xb8, 0x17, 0xae, 0x1e, 0xfa, 0x61, 0x2c, 0x66, 0xbf, 0xca, 0x1c, 0xcc, 0x22, 0xf4, 0x05, 0x8c, - 0xe8, 0x46, 0xe1, 0x05, 0x8f, 0x5f, 0x54, 0xe1, 0x7b, 0xb6, 0xdf, 0x1c, 0xba, 0x88, 0x4f, 0x52, - 0xb9, 0x4a, 0xbd, 0xf6, 0x79, 0x95, 0x32, 0x26, 0x11, 0xcb, 0x00, 0x91, 0x08, 0xb2, 0x90, 0x42, - 0xbc, 0xc9, 0x55, 0xbb, 0x99, 0x10, 0xe3, 0xf2, 0x94, 0x2c, 0x7c, 0xe0, 0x29, 0x97, 0xc2, 0x89, - 0x99, 0x29, 0xdf, 0x86, 0x76, 0x3e, 0x14, 0x10, 0x54, 0x7e, 0x9a, 0x13, 0x1c, 0x14, 0xa7, 0xad, - 0xfc, 0x6b, 0x0d, 0xea, 0x3f, 0xf0, 0xc3, 0x53, 0x19, 0x8a, 0xbb, 0x50, 0xa7, 0xfa, 0xab, 0x92, - 0xa5, 0xb4, 0x16, 0x3b, 0x8f, 0x76, 0xef, 0x81, 0x46, 0x9c, 0x81, 0xc2, 0xce, 0xfc, 0x4a, 0xff, - 0x64, 0xe2, 0xc5, 0x39, 0xdb, 0x49, 0xcc, 0xdd, 0x65, 0x6e, 0x4d, 0xbf, 0x74, 0x28, 0xd4, 0x47, - 0x07, 0xf4, 0xa4, 0x4f, 0x9e, 0x1d, 0xa0, 0x7c, 0x3e, 0x2c, 0xa1, 0x4f, 0x71, 0xc0, 0x8f, 0x87, - 0x83, 0xb2, 0x7f, 0x49, 0xb0, 0xf8, 0x67, 0x7f, 0x4b, 0xd0, 0x17, 0xc4, 0x03, 0xa8, 0x2b, 0x13, - 0xb3, 0x98, 0x29, 0xc2, 0xe4, 0x86, 0xbd, 0x3c, 0x4a, 0x4d, 0x78, 0x04, 0x75, 0x36, 0xc7, 0x3c, - 0xa1, 0x10, 0x8b, 0x30, 0x9f, 0x16, 0x7d, 0x68, 0x7d, 0x41, 0xdc, 0x83, 0x86, 0xaa, 0xae, 0x8a, - 0x39, 0xa5, 0xd6, 0x4b, 0x2f, 0x56, 0x67, 0x5f, 0x8b, 0xd7, 0x2f, 0xb8, 0xab, 0xbc, 0x7e, 0xd1, - 0x15, 0x63, 0xd1, 0x37, 0xa4, 0x25, 0x9d, 0x5c, 0x32, 0x4d, 0x24, 0x14, 0x99, 0xa3, 0xbf, 0x3e, - 0x85, 0x4e, 0x21, 0xf1, 0x26, 0xfa, 0x09, 0x5b, 0xcc, 0xe6, 0xe2, 0x2e, 0x69, 0x8d, 0xef, 0x82, - 0xa6, 0x52, 0x05, 0x87, 0x8a, 0x31, 0xe6, 0x24, 0x26, 0x06, 0x97, 0x73, 0x05, 0xa4, 0x0a, 0x7e, - 0x08, 0x57, 0xe7, 0xd8, 0x56, 0x41, 0xdf, 0xd9, 0xbe, 0xd8, 0x79, 0x18, 0xdc, 0x7c, 0x61, 0x7f, - 0x4a, 0x80, 0x5f, 0x4f, 0x9c, 0xbe, 0x07, 0x90, 0x99, 0x18, 0x96, 0x8d, 0x4b, 0x06, 0x6a, 0x70, - 0x6d, 0x16, 0x9d, 0x6c, 0xba, 0xd6, 0xff, 0x9b, 0xaf, 0x6f, 0x94, 0x7e, 0xf9, 0xf5, 0x8d, 0xd2, - 0x3f, 0x7f, 0x7d, 0xa3, 0xf4, 0x8b, 0x5f, 0xdd, 0x58, 0xf8, 0xe5, 0xaf, 0x6e, 0x2c, 0xfc, 0xdd, - 0xaf, 0x6e, 0x2c, 0x1c, 0xd6, 0xe9, 0x2f, 0x85, 0x1f, 0xff, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x0d, 0x7d, 0xf5, 0x7b, 0xc8, 0x38, 0x00, 0x00, + 0xdb, 0x45, 0x3d, 0x30, 0xc3, 0x16, 0x9d, 0x4b, 0x6c, 0xf1, 0x10, 0xda, 0x67, 0xd2, 0x8a, 0xfd, + 0x70, 0x1c, 0x05, 0xd2, 0x8a, 0xfa, 0x8b, 0xd9, 0xa3, 0x3f, 0x23, 0xfc, 0x41, 0x20, 0x2d, 0xa3, + 0x75, 0x96, 0xb6, 0x51, 0x6d, 0x69, 0x29, 0xc1, 0x73, 0x01, 0xbb, 0x06, 0xb5, 0xad, 0xdd, 0x8d, + 0xe1, 0x0f, 0x7b, 0x25, 0xb4, 0xce, 0xc6, 0xf0, 0xd9, 0xd0, 0x38, 0x18, 0xf6, 0xca, 0x68, 0x2d, + 0x37, 0x86, 0xdb, 0xc3, 0xd1, 0xb0, 0x57, 0x61, 0xcf, 0x8b, 0xea, 0x38, 0xae, 0x63, 0x39, 0xb1, + 0xfe, 0x05, 0x40, 0xb6, 0xcb, 0x5c, 0x45, 0xb6, 0x0c, 0x0d, 0x3f, 0x48, 0x7c, 0xf0, 0xf4, 0x68, + 0x7b, 0x84, 0xda, 0x37, 0x9d, 0xd0, 0x48, 0xba, 0xd1, 0x02, 0x64, 0xe8, 0x57, 0xd5, 0xcd, 0x35, + 0xe5, 0x47, 0xe9, 0x07, 0x00, 0x59, 0x1e, 0x04, 0x4d, 0x4f, 0x46, 0x51, 0x95, 0x88, 0x8d, 0x13, + 0x5a, 0x2e, 0xa7, 0x5a, 0xa7, 0xfc, 0xa2, 0x6c, 0x0b, 0xf7, 0xeb, 0xab, 0xa0, 0xed, 0x98, 0xc1, + 0xe7, 0x5c, 0x73, 0xbd, 0x0d, 0x5d, 0x0a, 0x38, 0x92, 0x50, 0x8e, 0x2d, 0x42, 0xdb, 0xe8, 0xa4, + 0x58, 0x34, 0x30, 0xfa, 0x1f, 0x95, 0xe0, 0x8d, 0x1d, 0xff, 0x4c, 0xa6, 0x0e, 0xfe, 0xbe, 0x79, + 0xe1, 0xfa, 0xa6, 0xfd, 0x0a, 0x99, 0xc2, 0x58, 0xd4, 0x9f, 0x52, 0x0d, 0x34, 0xa9, 0x18, 0x1b, + 0x1a, 0x63, 0x1e, 0xab, 0xcf, 0x6d, 0x64, 0x14, 0x53, 0xa7, 0xf2, 0x16, 0x10, 0xc6, 0xae, 0x37, + 0xa1, 0x1e, 0x9f, 0x7b, 0x59, 0xfd, 0xba, 0x16, 0x53, 0x01, 0x61, 0xae, 0xbf, 0x5f, 0x9b, 0xef, + 0xef, 0xeb, 0x8f, 0x40, 0x1b, 0x9d, 0x53, 0x0a, 0x7d, 0x5a, 0xf4, 0xb8, 0x4b, 0x2f, 0xf1, 0xeb, + 0xca, 0x33, 0x7e, 0xdd, 0xbf, 0x94, 0xa0, 0x95, 0x0b, 0x5c, 0xc4, 0xb7, 0xa0, 0x1a, 0x9f, 0x7b, + 0xc5, 0x4f, 0x55, 0x92, 0x4d, 0x0c, 0xea, 0xba, 0x94, 0x26, 0x2e, 0x5f, 0x4a, 0x13, 0x8b, 0x6d, + 0x58, 0x64, 0xf3, 0x92, 0x5c, 0x22, 0xc9, 0xa6, 0xdd, 0x9a, 0x09, 0x94, 0xb8, 0xcc, 0x90, 0x5c, + 0x49, 0xa5, 0x88, 0xba, 0xc7, 0x05, 0xe4, 0x60, 0x0d, 0xae, 0xcc, 0x19, 0xf6, 0x4d, 0x0a, 0x4e, + 0xfa, 0x0d, 0xe8, 0x8c, 0xce, 0xbd, 0x91, 0x33, 0x91, 0x51, 0x6c, 0x4e, 0x02, 0xf2, 0x8b, 0x95, + 0x7b, 0x50, 0x35, 0xca, 0x71, 0xa4, 0xbf, 0x0f, 0xed, 0x7d, 0x29, 0x43, 0x43, 0x46, 0x81, 0xef, + 0xb1, 0x07, 0xa8, 0xd2, 0xfb, 0xec, 0x8b, 0x28, 0x48, 0xff, 0xff, 0xa0, 0x19, 0xe6, 0x51, 0xbc, + 0x6e, 0xc6, 0xd6, 0xc9, 0x37, 0xc9, 0x17, 0xbd, 0x0f, 0x8d, 0x80, 0x79, 0x4a, 0x85, 0xb3, 0x6d, + 0xf2, 0x49, 0x14, 0x9f, 0x19, 0x49, 0xa7, 0xfe, 0xbf, 0xa0, 0xab, 0x6a, 0x6d, 0xc9, 0x49, 0x72, + 0x05, 0xb9, 0xd2, 0x0b, 0x0b, 0x72, 0xfa, 0x31, 0x74, 0x92, 0x79, 0x6c, 0xe1, 0x5f, 0x6b, 0xda, + 0x37, 0xff, 0xe2, 0x41, 0xff, 0x7f, 0x70, 0xe5, 0x60, 0x7a, 0x18, 0x59, 0xa1, 0x43, 0xf2, 0x9e, + 0x6c, 0x37, 0x80, 0x66, 0x10, 0xca, 0x23, 0xe7, 0x5c, 0x26, 0x22, 0x96, 0xc2, 0xe2, 0x0e, 0x34, + 0x26, 0x48, 0x2f, 0x99, 0x09, 0x6f, 0x16, 0xa4, 0xef, 0x60, 0x8f, 0x91, 0x0c, 0xd0, 0xbf, 0x0b, + 0x6f, 0x14, 0x97, 0x57, 0x54, 0xb8, 0x05, 0x95, 0xd3, 0xb3, 0x48, 0x91, 0x79, 0xa9, 0x10, 0xe4, + 0xd3, 0xa7, 0x26, 0xd8, 0xab, 0xff, 0x79, 0x09, 0x2a, 0xbb, 0xd3, 0x49, 0xfe, 0x5b, 0xbe, 0x2a, + 0x7f, 0xcb, 0x77, 0x2d, 0x5f, 0x0a, 0xe0, 0xa0, 0x31, 0x4b, 0xf9, 0xbf, 0x03, 0xda, 0x91, 0x1f, + 0xfe, 0xcc, 0x0c, 0x6d, 0x69, 0x2b, 0x37, 0x23, 0x43, 0x50, 0x7c, 0x30, 0x9d, 0x04, 0xca, 0x56, + 0x51, 0x5b, 0xdc, 0x56, 0x8e, 0x0a, 0x07, 0x72, 0x4b, 0x48, 0xd9, 0xdd, 0xe9, 0x64, 0xc5, 0x95, + 0x66, 0x44, 0x96, 0x93, 0x7d, 0x17, 0xfd, 0x2e, 0x68, 0x29, 0x0a, 0x55, 0xf4, 0xee, 0xc1, 0x78, + 0x6b, 0x83, 0xd3, 0xab, 0x18, 0xf2, 0x94, 0x50, 0x3d, 0x8f, 0x7e, 0xb8, 0x3b, 0x1e, 0x1d, 0xf4, + 0xca, 0xfa, 0x8f, 0xa1, 0x95, 0xc8, 0xcf, 0x96, 0x4d, 0xb5, 0x44, 0x12, 0xe0, 0x2d, 0xbb, 0x20, + 0xcf, 0x5b, 0x14, 0x93, 0x4a, 0xcf, 0xde, 0x4a, 0x04, 0x8f, 0x81, 0xe2, 0x0d, 0x55, 0x61, 0x32, + 0xb9, 0xa1, 0x3e, 0x84, 0x25, 0x83, 0x6a, 0x22, 0xe8, 0x45, 0x24, 0x4f, 0x76, 0x15, 0xea, 0x9e, + 0x6f, 0xcb, 0x74, 0x03, 0x05, 0xe1, 0xce, 0xea, 0xb1, 0x95, 0x4a, 0x4b, 0xdf, 0x5e, 0xc2, 0x12, + 0x6a, 0xc9, 0x22, 0xa3, 0x15, 0xf2, 0xf5, 0xa5, 0x99, 0x7c, 0x3d, 0x6e, 0xa2, 0x4a, 0xf3, 0xac, + 0xf9, 0x93, 0x72, 0xfc, 0x00, 0x9a, 0x76, 0x14, 0x93, 0x58, 0x2b, 0xdd, 0x98, 0xc2, 0xfa, 0x7d, + 0xb8, 0xb2, 0x16, 0x04, 0xee, 0x45, 0x52, 0xc8, 0x54, 0x1b, 0xf5, 0xb3, 0x6a, 0x67, 0x49, 0x05, + 0xc2, 0x0c, 0xea, 0x9b, 0xd0, 0x4e, 0x52, 0x2a, 0x3b, 0x32, 0x36, 0x49, 0xe3, 0xb9, 0x4e, 0x21, + 0xa7, 0xd0, 0x64, 0xc4, 0xa8, 0x58, 0x15, 0x98, 0xb9, 0xdf, 0x0a, 0xd4, 0x95, 0x3a, 0x15, 0x50, + 0xb5, 0x7c, 0x9b, 0x37, 0xaa, 0x19, 0xd4, 0x46, 0xae, 0x9a, 0x44, 0xc7, 0x89, 0x5b, 0x3f, 0x89, + 0x8e, 0xf5, 0xbf, 0x2f, 0x43, 0x67, 0x9d, 0x52, 0x61, 0xc9, 0x19, 0x73, 0x09, 0xe0, 0x52, 0x21, + 0x01, 0x9c, 0x4f, 0xf6, 0x96, 0x0b, 0xc9, 0xde, 0xc2, 0x81, 0x2a, 0x45, 0x5f, 0xfc, 0x2d, 0x68, + 0x4c, 0x3d, 0xe7, 0x3c, 0xb1, 0x13, 0x1a, 0xf9, 0x34, 0xe7, 0xa3, 0x48, 0xdc, 0x84, 0x16, 0x9a, + 0x12, 0xc7, 0xe3, 0x04, 0x2b, 0x67, 0x49, 0xf3, 0xa8, 0x99, 0x34, 0x6a, 0xfd, 0xe5, 0x69, 0xd4, + 0xc6, 0x2b, 0xd3, 0xa8, 0xcd, 0x57, 0xa5, 0x51, 0xb5, 0xd9, 0x34, 0x6a, 0x31, 0x8e, 0x80, 0x4b, + 0x71, 0xc4, 0xbb, 0x00, 0xfc, 0xfd, 0xd0, 0xd1, 0xd4, 0x75, 0x95, 0xb3, 0xa5, 0x11, 0x66, 0x73, + 0xea, 0xba, 0xfa, 0x36, 0x74, 0x13, 0xd2, 0x2a, 0x15, 0xf0, 0x19, 0x2c, 0xaa, 0x02, 0x89, 0x0c, + 0x55, 0x66, 0x90, 0x35, 0x1b, 0xc9, 0x1f, 0xd7, 0x30, 0x54, 0x8f, 0xd1, 0xb5, 0xf3, 0x60, 0xa4, + 0xff, 0xa2, 0x04, 0x9d, 0xc2, 0x08, 0xf1, 0x30, 0x2b, 0xb7, 0x94, 0x48, 0x8a, 0xfb, 0x97, 0x56, + 0x79, 0x79, 0xc9, 0xa5, 0x3c, 0x53, 0x72, 0xd1, 0xef, 0xa5, 0x85, 0x14, 0x55, 0x3e, 0x59, 0x48, + 0xcb, 0x27, 0x54, 0x71, 0x58, 0x1b, 0x8d, 0x8c, 0x5e, 0x59, 0xd4, 0xa1, 0xbc, 0x7b, 0xd0, 0xab, + 0xe8, 0x7f, 0x52, 0x86, 0xce, 0xf0, 0x3c, 0xa0, 0x6f, 0xe9, 0x5e, 0x19, 0x94, 0xe5, 0xf8, 0xaa, + 0x5c, 0xe0, 0xab, 0x1c, 0x87, 0x54, 0x54, 0xfd, 0x98, 0x39, 0x04, 0xc3, 0x34, 0x4e, 0xea, 0x2a, + 0xce, 0x61, 0xe8, 0x7f, 0x02, 0xe7, 0x14, 0x34, 0x0a, 0xcc, 0x56, 0x00, 0xb7, 0xa1, 0x9b, 0x90, + 0x4d, 0x31, 0xc6, 0x6b, 0x09, 0x2b, 0x7f, 0xc1, 0xeb, 0xa6, 0x99, 0x41, 0x06, 0xf4, 0x3f, 0x28, + 0x83, 0xc6, 0x7c, 0x86, 0x87, 0xff, 0x50, 0xe9, 0xf5, 0x52, 0x56, 0x6c, 0x4a, 0x3b, 0x57, 0x9e, + 0xc8, 0x8b, 0x4c, 0xb7, 0xcf, 0x2d, 0xd0, 0xaa, 0xfc, 0x21, 0xa7, 0x4d, 0x28, 0x7f, 0x78, 0x0d, + 0x34, 0x76, 0xcb, 0xa6, 0xaa, 0xd2, 0x51, 0x35, 0xd8, 0x4f, 0x7b, 0xea, 0x90, 0x65, 0x89, 0x65, + 0x38, 0x51, 0x6f, 0x40, 0xed, 0x62, 0x80, 0xda, 0x49, 0x42, 0xa3, 0x02, 0x45, 0x1a, 0xb3, 0x14, + 0x39, 0x81, 0x86, 0x3a, 0x1b, 0x3a, 0xff, 0x4f, 0x77, 0x9f, 0xec, 0xee, 0xfd, 0x60, 0xb7, 0xc0, + 0x7d, 0x69, 0x78, 0x50, 0xce, 0x87, 0x07, 0x15, 0xc4, 0x3f, 0xda, 0x7b, 0xba, 0x3b, 0xea, 0x55, + 0x45, 0x07, 0x34, 0x6a, 0x8e, 0x8d, 0xe1, 0xb3, 0x5e, 0x8d, 0xd2, 0x6f, 0x8f, 0x3e, 0x1f, 0xee, + 0xac, 0xf5, 0xea, 0x69, 0xe9, 0xaf, 0xa1, 0xff, 0x7e, 0x09, 0x96, 0x98, 0x20, 0xf9, 0xec, 0x53, + 0xfe, 0xdb, 0xfa, 0x2a, 0x7f, 0x5b, 0xff, 0xdf, 0x9b, 0x70, 0xc2, 0x49, 0x53, 0x27, 0x29, 0xb6, + 0x73, 0x56, 0xb4, 0x39, 0x75, 0x54, 0x8d, 0xfd, 0xaf, 0x4b, 0x30, 0xe0, 0x98, 0xe0, 0x71, 0x68, + 0x06, 0x27, 0xdf, 0xdf, 0xbe, 0x94, 0xfa, 0x78, 0x91, 0xa7, 0x7c, 0x1b, 0xba, 0xf4, 0xef, 0x83, + 0x9f, 0xba, 0x63, 0x15, 0x86, 0xf3, 0xeb, 0x76, 0x14, 0x96, 0x17, 0x12, 0x1f, 0x43, 0x9b, 0xff, + 0xa5, 0x40, 0x65, 0x82, 0x42, 0xa1, 0xb8, 0x10, 0x91, 0xb4, 0x78, 0x14, 0x97, 0xb5, 0x1f, 0xa6, + 0x93, 0xb2, 0x2c, 0xc9, 0xe5, 0x5a, 0xb0, 0x9a, 0x32, 0xa2, 0xdc, 0xc9, 0x7d, 0xb8, 0x36, 0xf7, + 0x1e, 0x8a, 0xed, 0x73, 0xd9, 0x6a, 0xe6, 0x36, 0xfd, 0x1f, 0x4a, 0xd0, 0x5c, 0x9f, 0xba, 0xa7, + 0x64, 0x04, 0xdf, 0x05, 0x90, 0xf6, 0xb1, 0x54, 0x9f, 0xfb, 0x97, 0x48, 0x39, 0x68, 0x88, 0xe1, + 0x0f, 0xfe, 0x3f, 0x03, 0xe0, 0x3b, 0x8e, 0x27, 0x66, 0xa0, 0x9e, 0x88, 0x0a, 0xb7, 0xc9, 0x02, + 0xea, 0x2e, 0x3b, 0x66, 0xa0, 0x0a, 0xb7, 0x51, 0x02, 0x67, 0x05, 0xed, 0xca, 0x4b, 0x0a, 0xda, + 0x83, 0x5d, 0xe8, 0x16, 0x97, 0x98, 0x13, 0x17, 0xbe, 0x5f, 0xfc, 0x68, 0xe8, 0x32, 0x0d, 0x73, + 0x3e, 0xfc, 0x17, 0xb0, 0x38, 0x53, 0x71, 0x78, 0x99, 0xc6, 0x2c, 0x88, 0x4c, 0x79, 0x56, 0x64, + 0x3e, 0x82, 0xa5, 0x91, 0x19, 0x9d, 0xaa, 0xb8, 0x26, 0x33, 0xde, 0xb1, 0x19, 0x9d, 0x8e, 0x53, + 0xa2, 0xd6, 0x11, 0xdc, 0xb2, 0xf5, 0x87, 0x20, 0xf2, 0xa3, 0x15, 0xfd, 0x31, 0x5e, 0xc5, 0xe1, + 0x13, 0x19, 0x9b, 0x89, 0x97, 0x81, 0x08, 0x24, 0xde, 0xea, 0x5f, 0x95, 0xa0, 0x8a, 0x81, 0x80, + 0xb8, 0x07, 0xda, 0xe7, 0xd2, 0x0c, 0xe3, 0x43, 0x69, 0xc6, 0xa2, 0xe0, 0xf4, 0x0f, 0x88, 0x6e, + 0xd9, 0x87, 0x48, 0xfa, 0xc2, 0x83, 0x92, 0x58, 0xe1, 0xcf, 0xa4, 0x93, 0xcf, 0xbf, 0x3b, 0x49, + 0x40, 0x41, 0x01, 0xc7, 0xa0, 0x30, 0x5f, 0x5f, 0x58, 0xa6, 0xf1, 0x5f, 0xf8, 0x8e, 0xf7, 0x88, + 0x3f, 0xce, 0x15, 0xb3, 0x01, 0xc8, 0xec, 0x0c, 0x71, 0x0f, 0xea, 0x5b, 0x11, 0x46, 0x3a, 0x97, + 0x87, 0x12, 0xf1, 0xf3, 0x41, 0x90, 0xbe, 0xb0, 0xfa, 0xc7, 0x35, 0xa8, 0xfe, 0x58, 0x86, 0xbe, + 0xf8, 0x08, 0x1a, 0xea, 0xb3, 0x2d, 0x91, 0xfb, 0x3c, 0x6b, 0x40, 0x19, 0xa4, 0x99, 0xef, 0xb9, + 0x68, 0x97, 0x1e, 0xbf, 0x5f, 0x56, 0x67, 0x13, 0xd9, 0x57, 0x65, 0x97, 0x0e, 0xf5, 0x29, 0xf4, + 0x0e, 0xe2, 0x50, 0x9a, 0x93, 0xdc, 0xf0, 0x22, 0xa9, 0xe6, 0x15, 0xed, 0x88, 0x5e, 0x77, 0xa1, + 0xce, 0xe1, 0xe4, 0xcc, 0x84, 0xd9, 0x8a, 0x1c, 0x0d, 0xfe, 0x00, 0x5a, 0x07, 0x27, 0xfe, 0xd4, + 0xb5, 0x0f, 0x64, 0x78, 0x26, 0x45, 0x2e, 0x22, 0x1a, 0xe4, 0xda, 0xfa, 0x82, 0x78, 0x08, 0x75, + 0x7c, 0x91, 0x70, 0x22, 0x96, 0x72, 0x51, 0x13, 0xb3, 0xc9, 0x40, 0xe4, 0x51, 0x09, 0xa5, 0xc4, + 0x07, 0xa0, 0xb1, 0xfb, 0x8e, 0xce, 0x7b, 0x43, 0x45, 0x04, 0x7c, 0x8c, 0x9c, 0x5b, 0xaf, 0x2f, + 0x88, 0x65, 0x80, 0x5c, 0x1c, 0xfa, 0xb2, 0x91, 0x1f, 0x43, 0xe7, 0x11, 0x69, 0xc2, 0xbd, 0x70, + 0xed, 0xd0, 0x0f, 0x63, 0x31, 0xfb, 0x29, 0xe9, 0x60, 0x16, 0xa1, 0x2f, 0x60, 0x44, 0x37, 0x0a, + 0x2f, 0x78, 0xfc, 0x92, 0x0a, 0xdf, 0xb3, 0xfd, 0xe6, 0xd0, 0x45, 0x7c, 0x92, 0xca, 0x55, 0xea, + 0xb5, 0xcf, 0x2b, 0xef, 0x31, 0x89, 0x58, 0x06, 0x88, 0x44, 0x90, 0x85, 0x14, 0xe2, 0x4d, 0x2e, + 0x35, 0xce, 0x84, 0x18, 0x97, 0xa7, 0x64, 0xe1, 0x03, 0x4f, 0xb9, 0x14, 0x4e, 0xcc, 0x4c, 0xf9, + 0x36, 0xb4, 0xf3, 0xa1, 0x80, 0xa0, 0x9a, 0xd9, 0x9c, 0xe0, 0xa0, 0x38, 0x6d, 0xf5, 0x5f, 0x6b, + 0x50, 0xff, 0x81, 0x1f, 0x9e, 0xca, 0x50, 0xdc, 0x81, 0x3a, 0x15, 0x8d, 0x95, 0x2c, 0xa5, 0x05, + 0xe4, 0x79, 0xb4, 0x7b, 0x0f, 0x34, 0xe2, 0x0c, 0x14, 0x76, 0xe6, 0x57, 0xfa, 0xfb, 0x15, 0x2f, + 0xce, 0x29, 0x5a, 0x62, 0xee, 0x2e, 0x73, 0x6b, 0xfa, 0x79, 0x46, 0xa1, 0xa8, 0x3b, 0xa0, 0x27, + 0x7d, 0xf2, 0xec, 0x00, 0xe5, 0xf3, 0x41, 0x09, 0x7d, 0x8a, 0x03, 0x7e, 0x3c, 0x1c, 0x94, 0xfd, + 0xb5, 0x83, 0xc5, 0x3f, 0xfb, 0x2f, 0x85, 0xbe, 0x20, 0xee, 0x43, 0x5d, 0x99, 0x98, 0xa5, 0x4c, + 0x11, 0x26, 0x37, 0xec, 0xe5, 0x51, 0x6a, 0xc2, 0x43, 0xa8, 0xb3, 0x39, 0xe6, 0x09, 0x85, 0x58, + 0x84, 0xf9, 0xb4, 0xe8, 0x43, 0xeb, 0x0b, 0xe2, 0x2e, 0x34, 0x54, 0x49, 0x58, 0xcc, 0xa9, 0x0f, + 0x5f, 0x7a, 0xb1, 0x3a, 0xfb, 0x5a, 0xbc, 0x7e, 0xc1, 0x5d, 0xe5, 0xf5, 0x8b, 0xae, 0x18, 0x8b, + 0xbe, 0x21, 0x2d, 0xe9, 0xe4, 0x92, 0x69, 0x22, 0xa1, 0xc8, 0x1c, 0xfd, 0xf5, 0x29, 0x74, 0x0a, + 0x89, 0x37, 0xd1, 0x4f, 0xd8, 0x62, 0x36, 0x17, 0x77, 0x49, 0x6b, 0x7c, 0x17, 0x34, 0x95, 0x2a, + 0x38, 0x54, 0x8c, 0x31, 0x27, 0x31, 0x31, 0xb8, 0x9c, 0x2b, 0x20, 0x55, 0xf0, 0x43, 0xb8, 0x32, + 0xc7, 0xb6, 0x0a, 0xfa, 0x38, 0xf8, 0xc5, 0xce, 0xc3, 0xe0, 0xc6, 0x0b, 0xfb, 0x53, 0x02, 0xfc, + 0x7a, 0xe2, 0xf4, 0x3d, 0x80, 0xcc, 0xc4, 0xb0, 0x6c, 0x5c, 0x32, 0x50, 0x83, 0xab, 0xb3, 0xe8, + 0x64, 0xd3, 0xf5, 0xfe, 0xdf, 0x7c, 0x7d, 0xbd, 0xf4, 0xcb, 0xaf, 0xaf, 0x97, 0xfe, 0xf9, 0xeb, + 0xeb, 0xa5, 0x5f, 0xfc, 0xea, 0xfa, 0xc2, 0x2f, 0x7f, 0x75, 0x7d, 0xe1, 0xef, 0x7e, 0x75, 0x7d, + 0xe1, 0xb0, 0x4e, 0xff, 0x83, 0xfc, 0xf8, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x35, 0x86, + 0x6a, 0x7d, 0x39, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -10445,6 +10566,20 @@ func (m *SchemaUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.VectorSpecs) > 0 { + for iNdEx := len(m.VectorSpecs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.VectorSpecs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + } + } if m.Unique { i-- if m.Unique { @@ -10561,6 +10696,87 @@ func (m *SchemaUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *VectorSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VectorSpec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VectorSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Options) > 0 { + for iNdEx := len(m.Options) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Options[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintPb(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintPb(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *OptionPair) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *OptionPair) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *OptionPair) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Value) > 0 { + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintPb(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x12 + } + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintPb(dAtA, i, uint64(len(m.Key))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *TypeUpdate) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -13354,6 +13570,48 @@ func (m *SchemaUpdate) Size() (n int) { if m.Unique { n += 2 } + if len(m.VectorSpecs) > 0 { + for _, e := range m.VectorSpecs { + l = e.Size() + n += 1 + l + sovPb(uint64(l)) + } + } + return n +} + +func (m *VectorSpec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovPb(uint64(l)) + } + if len(m.Options) > 0 { + for _, e := range m.Options { + l = e.Size() + n += 1 + l + sovPb(uint64(l)) + } + } + return n +} + +func (m *OptionPair) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovPb(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovPb(uint64(l)) + } return n } @@ -22822,6 +23080,270 @@ func (m *SchemaUpdate) Unmarshal(dAtA []byte) error { } } m.Unique = bool(v != 0) + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VectorSpecs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VectorSpecs = append(m.VectorSpecs, &VectorSpec{}) + if err := m.VectorSpecs[len(m.VectorSpecs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPb(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VectorSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VectorSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VectorSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + 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 ErrInvalidLengthPb + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthPb + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthPb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Options = append(m.Options, &OptionPair{}) + if err := m.Options[len(m.Options)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipPb(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthPb + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *OptionPair) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: OptionPair: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: OptionPair: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + 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 ErrInvalidLengthPb + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPb + } + 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 ErrInvalidLengthPb + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthPb + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPb(dAtA[iNdEx:]) diff --git a/query/common_test.go b/query/common_test.go index 78c6ce64ea5..769e458d251 100644 --- a/query/common_test.go +++ b/query/common_test.go @@ -259,6 +259,7 @@ type User { gender friend alive + user_profile } type Node { @@ -344,6 +345,7 @@ tweet-c : string @index(fulltext) . tweet-d : string @index(trigram) . name2 : string @index(term) . age2 : int @index(int) . +user_profile : vfloat @index(hnsw(metric:"euclidian")) . ` func populateCluster() { diff --git a/schema/parse.go b/schema/parse.go index 29b85942a14..3bba03f6e57 100644 --- a/schema/parse.go +++ b/schema/parse.go @@ -63,12 +63,13 @@ func parseDirective(it *lex.ItemIterator, schema *pb.SchemaUpdate, t types.TypeI } schema.Directive = pb.SchemaUpdate_REVERSE case "index": - tokenizer, err := parseIndexDirective(it, schema.Predicate, t) + tokenizer, vectorSpecs, err := parseIndexDirective(it, schema.Predicate, t) if err != nil { return err } schema.Directive = pb.SchemaUpdate_INDEX schema.Tokenizer = tokenizer + schema.VectorSpecs = vectorSpecs case "count": schema.Count = true case "upsert": @@ -175,77 +176,246 @@ func parseScalarPair(it *lex.ItemIterator, predicate string, ns uint64) (*pb.Sch return schema, nil } -// parseIndexDirective works on "@index" or "@index(customtokenizer)". +// parseIndexDirective works on "@index" or "@index(customtokenizer)" +// or @index(tok1(opt1:"opt1val",opt2:"opt2val"), tok2, tok3) +// We assume that the "@index" has already been found, so we just need +// to parse the rest. +// Syntax EBNF (after '@index' has been found): +// +// Tokens ::= '(' TokenList ')' +// TokenList ::= Token [',' TokenList]* +// +// This function will specifically handle this as: +// +// Tokens ::= '(' TokenList ')' +// TokenList ::= Token [',' TokeniList] +// +// It then defers to parseTokenOrVectorSpec to parse Token. func parseIndexDirective(it *lex.ItemIterator, predicate string, - typ types.TypeID) ([]string, error) { - var tokenizers []string + typ types.TypeID) ([]string, []*pb.VectorSpec, error) { + tokenizers := []string{} + var vectorSpecs []*pb.VectorSpec var seen = make(map[string]bool) var seenSortableTok bool if typ == types.UidID || typ == types.DefaultID || typ == types.PasswordID { - return tokenizers, it.Item().Errorf("Indexing not allowed on predicate %s of type %s", - predicate, typ.Name()) + return tokenizers, vectorSpecs, + it.Item().Errorf("Indexing not allowed on predicate %s of type %s", + predicate, typ.Name()) } if !it.Next() { // Nothing to read. - return []string{}, it.Item().Errorf("Invalid ending.") + return tokenizers, vectorSpecs, it.Item().Errorf("Invalid ending.") } next := it.Item() if next.Typ != itemLeftRound { it.Prev() // Backup. - return []string{}, it.Item().Errorf("Require type of tokenizer for pred: %s for indexing.", - predicate) + return tokenizers, vectorSpecs, + it.Item().Errorf("Require type of tokenizer for pred: %s for indexing.", + predicate) } - expectArg := true - // Look for tokenizers. + // Look for tokenizers and IndexFactories (vectorSpecs). for { + tokenText, vectorSpec, sortable, err := parseTokenOrVectorSpec(it, predicate, typ) + if err != nil { + return tokenizers, vectorSpecs, err + } + if sortable && seenSortableTok { + return tokenizers, vectorSpecs, + next.Errorf("Only one index tokenizer can be sortable for %s", + predicate) + } + seenSortableTok = sortable + if tokenText != "" { + if _, found := seen[tokenText]; found { + return tokenizers, vectorSpecs, + next.Errorf("Duplicate tokenizers defined for predicate %v", + predicate) + } + tokenizers = append(tokenizers, tokenText) + seen[tokenText] = true + } else { + // parseTokenOrVectorSpec should have returned either + // non-empty tokenText or non-nil vectorsSpec or an error. + x.AssertTrue(vectorSpec != nil) + // At the moment, we cannot accept two VectorSpecs of + // the same name. Later, we may reconsider this as we + // develop a simple means to distinguish how their keys + // are formed based on the specified options. The notion + // of "seen" still applies, but we just use the tokenizer name. + seen[vectorSpec.Name] = true + vectorSpecs = append(vectorSpecs, vectorSpec) + } + it.Next() next = it.Item() if next.Typ == itemRightRound { break } - if next.Typ == itemComma { - if expectArg { - return nil, next.Errorf("Expected a tokenizer but got comma") - } - expectArg = true - continue + if next.Typ != itemComma { + return tokenizers, vectorSpecs, next.Errorf( + "Expected ',' or ')' but found '%s' for predicate '%s'", + next.Val, predicate) } - if next.Typ != itemText { - return tokenizers, next.Errorf("Expected directive arg but got: %v", next.Val) + } + return tokenizers, vectorSpecs, nil +} + +// parseTokenOrVectorSpec(it, predicate, typ) will parse a "Token" according to the +// grammar specification below. +// +// Token ::= TokenName [ TokenOptions ] +// TokenName ::= {itemText from Lexer} +// +// For TokenOptions, it defers to parseTokenOptions parsing. +// We expect either to find the name of a Tokenizer or else the name of an IndexFactory +// along with its options. We also return a boolean value indicating whether or +// not the found index is Sortable. +func parseTokenOrVectorSpec( + it *lex.ItemIterator, + predicate string, + typ types.TypeID) (string, *pb.VectorSpec, bool, error) { + it.Next() + next := it.Item() + if next.Typ != itemText { + return "", nil, false, next.Errorf( + "Expected token or VectorFactory name, but found '%s'", + next.Val) + } + tokenOrFactoryName := strings.ToLower(next.Val) + factory, found := tok.GetIndexFactory(tokenOrFactoryName) + if found { + // TODO: Consider allowing IndexFactory types not related to + // VectorIndex objects. + if typ != types.VFloatID { + return "", nil, false, + next.Errorf("IndexFactory: %s isn't valid for predicate: %s of type: %s", + factory.Name(), x.ParseAttr(predicate), typ.Name()) } - if !expectArg { - return tokenizers, next.Errorf("Expected a comma but got: %v", next) + tokenOpts, err := parseTokenOptions(it, factory) + if err != nil { + return "", nil, false, err } - // Look for custom tokenizer. - tokenizer, has := tok.GetTokenizer(strings.ToLower(next.Val)) - if !has { - return tokenizers, next.Errorf("Invalid tokenizer %s", next.Val) + allowedOpts := factory.AllowedOptions() + for _, pair := range tokenOpts { + _, err := allowedOpts.GetParsedOption(pair.Key, pair.Value) + if err != nil { + return "", nil, false, + next.Errorf("IndexFactory: %s issues this error: '%s'", + factory.Name(), err) + } } - tokenizerType, ok := types.TypeForName(tokenizer.Type()) - x.AssertTrue(ok) // Type is validated during tokenizer loading. - if tokenizerType != typ { - return tokenizers, - next.Errorf("Tokenizer: %s isn't valid for predicate: %s of type: %s", - tokenizer.Name(), x.ParseAttr(predicate), typ.Name()) + vs := &pb.VectorSpec{ + Name: tokenOrFactoryName, + Options: tokenOpts, } - if _, found := seen[tokenizer.Name()]; found { - return tokenizers, next.Errorf("Duplicate tokenizers defined for pred %v", - predicate) + return "", vs, factory.IsSortable(), err + } + + // Look for custom tokenizer, and validate its type. + tokenizer, has := tok.GetTokenizer(tokenOrFactoryName) + if !has { + return tokenOrFactoryName, nil, false, + next.Errorf("Invalid tokenizer %s", next.Val) + } + tokenizerType, ok := types.TypeForName(tokenizer.Type()) + x.AssertTrue(ok) // Type is validated during tokenizer loading. + if tokenizerType != typ { + return tokenOrFactoryName, nil, false, + next.Errorf("Tokenizer: %s isn't valid for predicate: %s of type: %s", + tokenizer.Name(), x.ParseAttr(predicate), typ.Name()) + } + return tokenOrFactoryName, nil, tokenizer.IsSortable(), nil +} + +// parseTokenOptions(it, factory) will parse "TokenOptions" according to the +// following grammar: +// +// TokenOptions ::= ['(' TokenOptionList ')'] +// TokenOptionList ::= TokenOption [',' TokenOptionList ] +// +// For Parsing TokenOption, it defers to parseTokenOption +// Note that specifying TokenOptions is optional! The result is considered +// valid even if no token options are found as long as the first character +// discovered by it is a comma or end-parenthesis. (In the context where we +// invoke this, a comma indicates another tokenizer, and an end-parenthesis +// indicates the end of a list of tokenizers. +// TokenOptions provide the OptionKey-OptionValue pairs needed for building +// a VectorIndex. The factory is used to validate that any option name given +// is specified as an AllowedOption. +func parseTokenOptions(it *lex.ItemIterator, factory tok.IndexFactory) ([]*pb.OptionPair, error) { + retVal := []*pb.OptionPair{} + nextItem, found := it.PeekOne() + if !found { + return nil, nextItem.Errorf( + "unexpected end of stream when looking for IndexFactory options") + } + if nextItem.Typ == itemComma || nextItem.Typ == itemRightRound { + return []*pb.OptionPair{}, nil + } + if nextItem.Typ != itemLeftRound { + return nil, nextItem.Errorf( + "unexpected '%s' found when expecting '('", nextItem.Val) + } + it.Next() // Reads initial '(' + for { + optPair, err := parseTokenOption(it, factory) + if err != nil { + return retVal, err } - if tokenizer.IsSortable() { - if seenSortableTok { - return nil, next.Errorf("More than one sortable index encountered for: %v", - predicate) - } - seenSortableTok = true + retVal = append(retVal, optPair) + it.Next() + nextItem = it.Item() + if nextItem.Typ == itemRightRound { + return retVal, nil } - tokenizers = append(tokenizers, tokenizer.Name()) - seen[tokenizer.Name()] = true - expectArg = false + if nextItem.Typ != itemComma { + return nil, nextItem.Errorf( + "unexpected '%s' found when expecting ',' or ')'", + nextItem.Val) + } + } +} + +// parseTokenOption(it, factory) constructs OptionPair instances +// and validates that the options are okay via the factory. +// +// TokenOption ::= OptionName ':' OptionValue +// OptionName ::= {itemText from Lexer} +// OptionValue ::= {itemQuotedText from Lexer} +func parseTokenOption(it *lex.ItemIterator, factory tok.IndexFactory) (*pb.OptionPair, error) { + it.Next() + nextItem := it.Item() + if nextItem.Typ != itemText { + return nil, nextItem.Errorf( + "unexpected '%s' found when expecting option name", + nextItem.Val) } - return tokenizers, nil + optName := nextItem.Val + it.Next() + nextItem = it.Item() + if nextItem.Typ != itemColon { + return nil, nextItem.Errorf( + "unexpected '%s' found when expecting ':'", + nextItem.Val) + } + it.Next() + nextItem = it.Item() + if nextItem.Typ != itemQuotedText { + return nil, nextItem.Errorf( + "unexpected '%s' found when expecting quoted text", + nextItem.Val) + } + optVal := nextItem.Val + return &pb.OptionPair{Key: optName, Value: optVal}, nil +} + +func HasTokenizerOrVectorSpec(update *pb.SchemaUpdate) bool { + if update == nil { + return false + } + return len(update.Tokenizer) > 0 || len(update.VectorSpecs) > 0 } // resolveTokenizers resolves default tokenizers and verifies tokenizers definitions. @@ -263,13 +433,17 @@ func resolveTokenizers(updates []*pb.SchemaUpdate) error { continue } - if len(schema.Tokenizer) == 0 && schema.Directive == pb.SchemaUpdate_INDEX { - return errors.Errorf("Require type of tokenizer for pred: %s of type: %s for indexing.", + if !HasTokenizerOrVectorSpec(schema) && + schema.Directive == pb.SchemaUpdate_INDEX { + return errors.Errorf( + "Require type of tokenizer for pred: %s of type: %s for indexing.", schema.Predicate, typ.Name()) - } else if len(schema.Tokenizer) > 0 && schema.Directive != pb.SchemaUpdate_INDEX { - return errors.Errorf("Tokenizers present without indexing on attr %s", x.ParseAttr(schema.Predicate)) + } else if HasTokenizerOrVectorSpec(schema) && + schema.Directive != pb.SchemaUpdate_INDEX { + return errors.Errorf("Tokenizers present without indexing on attr %s", + x.ParseAttr(schema.Predicate)) } - // check for valid tokeniser types and duplicates + // check for valid tokenizer types and duplicates var seen = make(map[string]bool) var seenSortableTok bool for _, t := range schema.Tokenizer { diff --git a/schema/parse_test.go b/schema/parse_test.go index 4cf92e66a86..f5d6b5f0dad 100644 --- a/schema/parse_test.go +++ b/schema/parse_test.go @@ -35,11 +35,15 @@ type nameType struct { } func checkSchema(t *testing.T, h map[string]*pb.SchemaUpdate, expected []nameType) { + if len(h) != len(expected) { + t.Errorf("In checkSchema, expected len(h) == len(expected)") + } require.Len(t, h, len(expected)) for _, nt := range expected { typ, found := h[nt.name] require.True(t, found, nt) - require.EqualValues(t, *nt.typ, *typ) + require.EqualValuesf(t, *nt.typ, *typ, "found in map: %+v\n expected: %+v", + *typ, *nt.typ) } } diff --git a/schema/schema.go b/schema/schema.go index e04d67649aa..8aa14e14006 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -294,13 +294,14 @@ func (s *state) IsIndexed(ctx context.Context, pred string) bool { defer s.RUnlock() if isWrite { // TODO(Aman): we could return the query schema if it is a delete. - if schema, ok := s.mutSchema[pred]; ok && len(schema.Tokenizer) > 0 { + if schema, ok := s.mutSchema[pred]; ok && + (len(schema.Tokenizer) > 0 || len(schema.VectorSpecs) > 0) { return true } } if schema, ok := s.predicate[pred]; ok { - return len(schema.Tokenizer) > 0 + return len(schema.Tokenizer) > 0 || len(schema.VectorSpecs) > 0 } return false @@ -367,6 +368,42 @@ func (s *state) Tokenizer(ctx context.Context, pred string) []tok.Tokenizer { return tokenizers } +// FactoryCreateSpec(ctx, pred) returns the list of versioned +// FactoryCreateSpec instances for given predicate. +// The FactoryCreateSpec type defines the IndexFactory instance(s) +// for given predicate along with their options, if specified. +func (s *state) FactoryCreateSpec(ctx context.Context, pred string) ([]*tok.FactoryCreateSpec, error) { + isWrite, _ := ctx.Value(IsWrite).(bool) + s.RLock() + defer s.RUnlock() + var su *pb.SchemaUpdate + if isWrite { + if schema, ok := s.mutSchema[pred]; ok { + su = schema + } + } + if su == nil { + if schema, ok := s.predicate[pred]; ok { + su = schema + } + } + if su == nil { + // This may happen when some query that needs indexing over this predicate is executing + // while the predicate is dropped from the state (using drop operation). + glog.Errorf("Schema state not found for %s.", pred) + return nil, errors.Errorf("Schema state not found for %s.", pred) + } + creates := make([]*tok.FactoryCreateSpec, 0, len(su.VectorSpecs)) + for _, vs := range su.VectorSpecs { + c, err := tok.GetFactoryCreateSpecFromSpec(vs) + if err != nil { + return nil, err + } + creates = append(creates, c) + } + return creates, nil +} + // TokenizerNames returns the tokenizer names for given predicate func (s *state) TokenizerNames(ctx context.Context, pred string) []string { var names []string diff --git a/schema/state.go b/schema/state.go index d754828182e..fe525e5a37c 100644 --- a/schema/state.go +++ b/schema/state.go @@ -22,20 +22,22 @@ import ( // Constants representing type of different graphql lexed items. const ( - itemText lex.ItemType = 5 + iota // plain text - itemNumber // number - itemLeftCurl // left curly bracket - itemRightCurl // right curly bracket - itemColon // colon - itemLeftRound // left round bracket - itemRightRound // right round bracket - itemAt - itemComma - itemNewLine - itemDot - itemLeftSquare - itemRightSquare - itemExclamationMark + itemText lex.ItemType = 5 + iota // plain text + itemNumber // number + itemLeftCurl // left curly bracket + itemRightCurl // right curly bracket + itemColon // colon + itemLeftRound // left round bracket + itemRightRound // right round bracket + itemAt // '@' + itemComma // ',' + itemNewLine // carriage-return or line-feed. + itemDot // '.' + itemLeftSquare // '[' + itemRightSquare // ']' + itemExclamationMark // '!' + itemQuote // double quote char: '"' + itemQuotedText // See Lexer.LexQuotedString() ) func lexText(l *lex.Lexer) lex.StateFn { @@ -91,6 +93,11 @@ Loop: l.Backup() return lexNumber } + case r == '"': + if err := l.LexQuotedString(); err != nil { + return l.Errorf("Invalid schema: %v", err) + } + l.Emit(itemQuotedText) default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } diff --git a/tok/index_factory.go b/tok/index_factory.go new file mode 100644 index 00000000000..ff68848dc42 --- /dev/null +++ b/tok/index_factory.go @@ -0,0 +1,143 @@ +/* + * Copyright 2016-2023 Dgraph Labs, Inc. and Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tok + +import ( + "fmt" + "plugin" + + "github.com/golang/glog" + "github.com/pkg/errors" + + "github.com/dgraph-io/dgraph/x" + "github.com/dgraph-io/vector-indexer/index" + opts "github.com/dgraph-io/vector-indexer/options" +) + +func LoadCustomIndexFactory(soFile string) { + glog.Infof("Loading vector indexer and tokenizer from %q", soFile) + pl, err := plugin.Open(soFile) + x.Checkf(err, "count not open custom vector indexer plugin file") + symb, err := pl.Lookup("CreateFactory") + x.Checkf(err, `could not find symbol "CreateTokenizer while loading custom vector indexer: %v`, err) + namedFactory := symb.(func() interface{})().(index.NamedFactory[float64]) + registerIndexFactory(createIndexFactory(namedFactory)) +} + +// registerIndexFactory(f) will register f as both a Tokenizer and specifically +// as an IndexFactory. +func registerIndexFactory(f IndexFactory) { + // Note: All necessary checks for duplication, etc. is done in + // registerTokenizers. Since we add IndexFactory instances + // to both tokenizers map and indexFactories map, it suffices + // to just check the tokenizers map for uniqueness. + registerTokenizer(f) + indexFactories[f.Name()] = f +} + +// IndexFactory combines the notion of a Tokenizer with +// index.IndexFactory. We register IndexFactory instances just +// like we register Tokenizers. +type IndexFactory interface { + Tokenizer + // TODO: Distinguish between float64 and float32, allowing either. + // Default should be float32. + index.IndexFactory[float64] +} + +// FactoryCreateSpec includes an IndexFactory and the options required +// to instantiate a VectorIndex of the given type. +// In short, everything that is needed in order to create a VectorIndex! +type FactoryCreateSpec struct { + factory IndexFactory + opts opts.Options + // TODO: Consider adding in VectorSource. + // At the moment, we can't use this. +} + +func (fcs *FactoryCreateSpec) CreateIndex(name string) (index.VectorIndex[float64], error) { + if fcs == nil || fcs.factory == nil { + return nil, + errors.Errorf( + "cannot create Index for '%s' with nil factory", + name) + } + + // TODO: What we should really be doing here is a "Find it, and if found, + // replace it *only if* the options have changed!" However, there + // is currently no way to introspect the options. + // We cheat for the moment and simply do a CreateOrReplace. + // This avoids us getting into duplicate create conflicts, but + // has the downside of not allowing us to reuse the pre-existing + // index. + // nil VectorSource at the moment. + return fcs.factory.CreateOrReplace(name, fcs.opts, nil, 64) +} + +func createIndexFactory(f index.NamedFactory[float64]) IndexFactory { + return &indexFactory{delegate: f} +} + +type indexFactory struct { + delegate index.NamedFactory[float64] +} + +func (f *indexFactory) Name() string { return f.delegate.Name() } +func (f *indexFactory) AllowedOptions() opts.AllowedOptions { + return f.delegate.AllowedOptions() +} +func (f *indexFactory) Create( + name string, + o opts.Options, + source index.VectorSource[float64], + floatBits int) (index.VectorIndex[float64], error) { + return f.delegate.Create(name, o, source, floatBits) +} +func (f *indexFactory) Find(name string) (index.VectorIndex[float64], error) { + return f.delegate.Find(name) +} +func (f *indexFactory) Remove(name string) error { + return f.delegate.Remove(name) +} +func (f *indexFactory) CreateOrReplace( + name string, + o opts.Options, + source index.VectorSource[float64], + floatBits int) (index.VectorIndex[float64], error) { + return f.delegate.CreateOrReplace(name, o, source, floatBits) +} + +func (f *indexFactory) Type() string { + // TODO: rename to vfloat64, and distinguish between + // float64 support and float32 support. + return "vfloat" +} +func (f *indexFactory) Tokens(v interface{}) ([]string, error) { + return tokensForExpectedVFloat(v) +} +func (f *indexFactory) Identifier() byte { return IdentVFloat } +func (f *indexFactory) IsSortable() bool { return false } +func (f *indexFactory) IsLossy() bool { return true } + +func tokensForExpectedVFloat(v interface{}) ([]string, error) { + value, ok := v.([]float64) + if !ok { + return []string{}, errors.Errorf("could not convert %s to vfloat", v.(string)) + } + // Generates space-separated list of float64 values inside of "[]". + return []string{fmt.Sprintf("%+v", value)}, nil +} diff --git a/tok/tok.go b/tok/tok.go index 50429d602d6..36f60224624 100644 --- a/tok/tok.go +++ b/tok/tok.go @@ -18,7 +18,6 @@ package tok import ( "encoding/binary" - "fmt" "plugin" "strings" "time" @@ -29,9 +28,11 @@ import ( "golang.org/x/crypto/blake2b" "golang.org/x/text/collate" + "github.com/dgraph-io/dgraph/protos/pb" "github.com/dgraph-io/dgraph/types" "github.com/dgraph-io/dgraph/x" "github.com/dgraph-io/vector-indexer/hnsw" + opts "github.com/dgraph-io/vector-indexer/options" ) // Tokenizer identifiers are unique and can't be reused. @@ -89,11 +90,10 @@ type Tokenizer interface { } var tokenizers = make(map[string]Tokenizer) +var indexFactories = make(map[string]IndexFactory) func init() { - registerTokenizer(HNSWEuclidianTokenizer{}) - registerTokenizer(HNSWCosineTokenizer{}) - registerTokenizer(HNSWDotProdTokenizer{}) + registerIndexFactory(createIndexFactory(hnsw.CreateFactory[float64](64))) registerTokenizer(GeoTokenizer{}) registerTokenizer(IntTokenizer{}) registerTokenizer(FloatTokenizer{}) @@ -161,6 +161,63 @@ func GetTokenizer(name string) (Tokenizer, bool) { return t, found } +// GetIndexFactory returns IndexFactory given name. +func GetIndexFactory(name string) (IndexFactory, bool) { + f, found := indexFactories[name] + return f, found +} + +func getOptsFromFactorySpec(f IndexFactory, spec *pb.VectorSpec) (opts.Options, error) { + allowedOpts := f.AllowedOptions() + retVal := opts.NewOptions() + for _, optPair := range spec.Options { + val, err := allowedOpts.GetParsedOption(optPair.Key, optPair.Value) + if err != nil { + return nil, err + } + retVal.SetOpt(optPair.Key, val) + } + return retVal, nil +} + +func GetFactoryCreateSpecFromSpec(spec *pb.VectorSpec) (*FactoryCreateSpec, error) { + factory, found := GetIndexFactoryFromSpec(spec) + if !found { + return &FactoryCreateSpec{}, errors.Errorf( + "cannot find index factory named '%s'", spec.Name) + } + opts, err := getOptsFromFactorySpec(factory, spec) + if err != nil { + return &FactoryCreateSpec{}, err + } + return &FactoryCreateSpec{factory: factory, opts: opts}, nil +} + +func GetIndexFactoryFromSpec(spec *pb.VectorSpec) (IndexFactory, bool) { + return GetIndexFactory(spec.Name) +} + +func GetIndexFactoryOptsFromSpec(spec *pb.VectorSpec) (opts.Options, error) { + factory, found := GetIndexFactoryFromSpec(spec) + if !found { + return nil, errors.Errorf( + "cannot get Options for factory named '%s' (factory not found)", + spec.Name) + } + return getOptsFromFactorySpec(factory, spec) +} + +func GetIndexFactoriesFromSpecs(specs []*pb.VectorSpec) []IndexFactory { + retVal := []IndexFactory{} + for _, spec := range specs { + f, found := GetIndexFactoryFromSpec(spec) + if found { + retVal = append(retVal, f) + } + } + return retVal +} + // GetTokenizers returns a list of tokenizer given a list of unique names. func GetTokenizers(names []string) ([]Tokenizer, error) { var tokenizers []Tokenizer @@ -218,45 +275,6 @@ func (t FloatTokenizer) Identifier() byte { return IdentFloat } func (t FloatTokenizer) IsSortable() bool { return true } func (t FloatTokenizer) IsLossy() bool { return true } -// HNSWEuclidianTokenizer generates tokens from vectors of float64 values and uses -// euclidian distance to index. -type HNSWEuclidianTokenizer struct{} - -func (t HNSWEuclidianTokenizer) Name() string { return hnsw.HnswEuclidian } -func (t HNSWEuclidianTokenizer) Type() string { return "vfloat" } -func (t HNSWEuclidianTokenizer) Tokens(v interface{}) ([]string, error) { - return tokensForExpectedVFloat(v) -} -func (t HNSWEuclidianTokenizer) Identifier() byte { return IdentVFloat } -func (t HNSWEuclidianTokenizer) IsSortable() bool { return false } -func (t HNSWEuclidianTokenizer) IsLossy() bool { return true } - -// HNSWCosineTokenizer generates tokens from vectors of float64 values and uses -// cosine similarity to index. -type HNSWCosineTokenizer struct{} - -func (t HNSWCosineTokenizer) Name() string { return hnsw.HnswCosine } -func (t HNSWCosineTokenizer) Type() string { return "vfloat" } -func (t HNSWCosineTokenizer) Tokens(v interface{}) ([]string, error) { - return tokensForExpectedVFloat(v) -} -func (t HNSWCosineTokenizer) Identifier() byte { return IdentVFloat } -func (t HNSWCosineTokenizer) IsSortable() bool { return false } -func (t HNSWCosineTokenizer) IsLossy() bool { return true } - -// HNSWDotProdTokenizer generates tokens from vectors of float64 values and uses -// dotproduct to index. -type HNSWDotProdTokenizer struct{} - -func (t HNSWDotProdTokenizer) Name() string { return hnsw.HnswDotProd } -func (t HNSWDotProdTokenizer) Type() string { return "vfloat" } -func (t HNSWDotProdTokenizer) Tokens(v interface{}) ([]string, error) { - return tokensForExpectedVFloat(v) -} -func (t HNSWDotProdTokenizer) Identifier() byte { return IdentVFloat } -func (t HNSWDotProdTokenizer) IsSortable() bool { return false } -func (t HNSWDotProdTokenizer) IsLossy() bool { return true } - // YearTokenizer generates year tokens from datetime data. type YearTokenizer struct{} @@ -559,12 +577,3 @@ func EncodeRegexTokens(tokens []string) { tokens[i] = encodeToken(tokens[i], TrigramTokenizer{}.Identifier()) } } - -func tokensForExpectedVFloat(v interface{}) ([]string, error) { - value, ok := v.([]float64) - if !ok { - return []string{}, errors.Errorf("could not convert %s to vfloat", v.(string)) - } - // Generates space-separated list of float64 values inside of "[]". - return []string{fmt.Sprintf("%+v", value)}, nil -} diff --git a/worker/mutation.go b/worker/mutation.go index 2f98a042277..ff8ea4aba77 100644 --- a/worker/mutation.go +++ b/worker/mutation.go @@ -399,11 +399,11 @@ func checkSchema(s *pb.SchemaUpdate) error { x.ParseAttr(s.Predicate)) } - if s.Directive == pb.SchemaUpdate_INDEX && len(s.Tokenizer) == 0 { + if s.Directive == pb.SchemaUpdate_INDEX && !schema.HasTokenizerOrVectorSpec(s) { return errors.Errorf("Tokenizer must be specified while indexing a predicate: %+v", s) } - if len(s.Tokenizer) > 0 && s.Directive != pb.SchemaUpdate_INDEX { + if schema.HasTokenizerOrVectorSpec(s) && s.Directive != pb.SchemaUpdate_INDEX { return errors.Errorf("Directive must be SchemaUpdate_INDEX when a tokenizer is specified") } diff --git a/worker/task.go b/worker/task.go index 969f330377f..10df213a51a 100644 --- a/worker/task.go +++ b/worker/task.go @@ -47,7 +47,6 @@ import ( "github.com/dgraph-io/dgraph/x" "github.com/dgraph-io/vector-indexer/hnsw" "github.com/dgraph-io/vector-indexer/index" - "github.com/dgraph-io/vector-indexer/manager" ) func invokeNetworkRequest(ctx context.Context, addr string, @@ -363,7 +362,7 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) (m if err != nil { return nil, fmt.Errorf("invalid value for number of neighbors: %s", q.SrcFunc.Args[0]) } - tokenizer, err := pickVFloatTokenizer(ctx, args.q.Attr, srcFn.fname) + cspec, err := pickFactoryCreateSpec(ctx, args.q.Attr) if err != nil { return nil, err } @@ -372,17 +371,17 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) (m posting.NewViLocalCache(qs.cache), args.q.ReadTs, ) - indexer, err := manager.NewIndexManager().Create(args.q.Attr, manager.KnownFlavors[tokenizer.Name()], 3, nil) + indexer, err := cspec.CreateIndex(args.q.Attr) if err != nil { return nil, err } var nnUids []uint64 if srcFn.vectorInfo != nil { nnUids, err = indexer.Search(ctx, qc, srcFn.vectorInfo, - int(numNeighbors), index.AcceptAll) + int(numNeighbors), index.AcceptAll[float64]) } else { nnUids, err = indexer.SearchWithUid(ctx, qc, srcFn.vectorUid, - int(numNeighbors), index.AcceptAll) + int(numNeighbors), index.AcceptAll[float64]) } if err != nil { @@ -392,40 +391,47 @@ func (qs *queryState) handleValuePostings(ctx context.Context, args funcArgs) (m args.out.UidMatrix = append(args.out.UidMatrix, &pb.List{Uids: nnUids}) return nil, nil } - - if srcFn.fnType == indexPathFn { - numNeighbors, err := strconv.ParseInt(q.SrcFunc.Args[0], 10, 32) - if err != nil { - return nil, fmt.Errorf("invalid value for number of neighbors: %s", q.SrcFunc.Args[0]) - } - tokenizer, err := pickVFloatTokenizer(ctx, args.q.Attr, srcFn.fname) - if err != nil { - return nil, err - } - //TODO: generate maxLevels from schema, filter, etc. - qc := hnsw.NewQueryCache( - posting.NewViLocalCache(qs.cache), - args.q.ReadTs, - ) - indexer, err := manager.NewIndexManager().Create(args.q.Attr, manager.KnownFlavors[tokenizer.Name()], 3, nil) - if err != nil { - return nil, err - } - hnswIndexer, ok := indexer.(*hnsw.PersistentHNSW) - if !ok { - return nil, errors.Errorf("indexer is not hnsw") - } - r, err := hnswIndexer.SearchWithPath(ctx, qc, srcFn.vectorInfo, - int(numNeighbors), index.AcceptAll) - traversalPath := r.GetTraversalPath() - extraMetrics := r.GetExtraMetrics() - if err != nil { - return nil, err + /* + if srcFn.fnType == indexPathFn { + numNeighbors, err := strconv.ParseInt(q.SrcFunc.Args[0], 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid value for number of neighbors: %s", q.SrcFunc.Args[0]) + } + cspec, err := pickFactoryCreateSpec(ctx, args.q.Attr) + if err != nil { + return nil, err + } + //TODO: generate maxLevels from schema, filter, etc. + qc := hnsw.NewQueryCache( + posting.NewViLocalCache(qs.cache), + args.q.ReadTs, + ) + indexer, err := cspec.CreateIndex(args.q.Attr) + if err != nil { + return nil, err + } + // TODO: Kill this mechanism. We either expose SearchWithPath + // as a public function in interface (along with possibly a + // "supports SearchWithPath" capability), + // Or we stop supporting getting traversal path. + // Type inference of this kind is almost always a sign that + // someone did not fully consider the design. + hnswIndexer, ok := indexer.(*hnsw.PersistentHNSW) + if !ok { + return nil, errors.Errorf("indexer is not hnsw") + } + r, err := hnswIndexer.SearchWithPath(ctx, qc, srcFn.vectorInfo, + int(numNeighbors), index.AcceptAll) + traversalPath := r.GetTraversalPath() + extraMetrics := r.GetExtraMetrics() + if err != nil { + return nil, err + } + sort.Slice(traversalPath, func(i, j int) bool { return traversalPath[i] < traversalPath[j] }) + args.out.UidMatrix = append(args.out.UidMatrix, &pb.List{Uids: traversalPath}) + return extraMetrics, nil } - sort.Slice(traversalPath, func(i, j int) bool { return traversalPath[i] < traversalPath[j] }) - args.out.UidMatrix = append(args.out.UidMatrix, &pb.List{Uids: traversalPath}) - return extraMetrics, nil - } + */ if srcFn.atype == types.PasswordID && srcFn.fnType != passwordFn { // Silently skip if the user is trying to fetch an attribute of type password. diff --git a/worker/tokens.go b/worker/tokens.go index dcca5ed56eb..13f7f2cf703 100644 --- a/worker/tokens.go +++ b/worker/tokens.go @@ -27,7 +27,6 @@ import ( "github.com/dgraph-io/dgraph/tok" "github.com/dgraph-io/dgraph/types" "github.com/dgraph-io/dgraph/x" - "github.com/dgraph-io/vector-indexer/hnsw" ) func verifyStringIndex(ctx context.Context, attr string, funcType FuncType) (string, bool) { @@ -123,23 +122,28 @@ func pickTokenizer(ctx context.Context, attr string, f string) (tok.Tokenizer, e return tokenizers[0], nil } -func pickVFloatTokenizer(ctx context.Context, attr string, f string) (tok.Tokenizer, error) { +// pickFactoryCreateSpec(ctx, attr) will find the FactoryCreateSpec (i.e., +// index name + options) for the given attribute "attr". +// Note that unlike pickTokenizer(ctx, attr, f), we do not include the +// parameter "f" (for function name), as we do not take action with it. +// This is otherwise similar to pickTokenizer. +func pickFactoryCreateSpec(ctx context.Context, attr string) (*tok.FactoryCreateSpec, error) { // Get the tokenizers and choose the corresponding one. if !schema.State().IsIndexed(ctx, attr) { return nil, errors.Errorf("Attribute %s is not indexed.", attr) } - tokenizers := schema.State().Tokenizer(ctx, attr) - if tokenizers == nil { + cspecs, err := schema.State().FactoryCreateSpec(ctx, attr) + if err != nil { + return nil, err + } + if len(cspecs) == 0 { return nil, errors.Errorf("Schema state not found for %s.", attr) } - // otherwise, lets return the first one. - if len(tokenizers) == 0 { - token, _ := tok.GetTokenizer(hnsw.HnswEuclidian) - return token, nil - } - return tokenizers[0], nil + // At the moment, it would only be relevant to consider the first one. + // This is similar to pickTokenizer in behavior. + return cspecs[0], nil } // getInequalityTokens gets tokens ge/le/between compared to given tokens using the first sortable