Skip to content

Commit

Permalink
Merge pull request #398 from tigrisdata/main
Browse files Browse the repository at this point in the history
Release Alpha
  • Loading branch information
himank authored Aug 3, 2022
2 parents 207f64c + 49285cd commit 468ef86
Show file tree
Hide file tree
Showing 36 changed files with 481 additions and 217 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.12.0
github.com/stretchr/testify v1.7.2
github.com/tigrisdata/tigris-client-go v1.0.0-alpha.20
github.com/tigrisdata/tigris-client-go v1.0.0-alpha.21
github.com/typesense/typesense-go v0.5.0
github.com/uber-go/tally v3.5.0+incompatible
github.com/ugorji/go/codec v1.2.7
github.com/valyala/bytebufferpool v1.0.0
go.uber.org/atomic v1.9.0
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b
google.golang.org/grpc v1.48.0
google.golang.org/protobuf v1.28.0
Expand Down Expand Up @@ -107,13 +109,11 @@ require (
github.com/yudai/gojsondiff v1.0.0 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
github.com/yudai/pp v2.0.1+incompatible // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/net v0.0.0-20220726230323-06994584191e // indirect
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc/examples v0.0.0-20220215234149-ec717cad7395 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -863,8 +863,8 @@ github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/rtred v0.1.2/go.mod h1:hd69WNXQ5RP9vHd7dqekAz+RIdtfBogmglkZSRxCHFQ=
github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw=
github.com/tigrisdata/tigris-client-go v1.0.0-alpha.20 h1:J4BazYr7EZjhlfZZEHRTQ7OYbfRi4ypwySLxxkXmZTc=
github.com/tigrisdata/tigris-client-go v1.0.0-alpha.20/go.mod h1:/L4tilHC26feio8KDuitajcGXabCLAElYtUQRkewkyM=
github.com/tigrisdata/tigris-client-go v1.0.0-alpha.21 h1:JwtFfVRDHI6qjAFEv5Uk0uiaARSuiN3nvBMjxOg9fY4=
github.com/tigrisdata/tigris-client-go v1.0.0-alpha.21/go.mod h1:/L4tilHC26feio8KDuitajcGXabCLAElYtUQRkewkyM=
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw=
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
Expand Down
44 changes: 44 additions & 0 deletions lib/json/encoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2022 Tigris Data, Inc.
//
// 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 json

import (
"bytes"

jsoniter "github.com/json-iterator/go"
)

func Encode(data map[string]any) ([]byte, error) {
var buffer bytes.Buffer
encoder := jsoniter.NewEncoder(&buffer)
err := encoder.Encode(data)
if err != nil {
return nil, err
}

return buffer.Bytes(), nil
}

func Decode(data []byte) (map[string]any, error) {
var decoded map[string]any

decoder := jsoniter.NewDecoder(bytes.NewReader(data))
decoder.UseNumber()
if err := decoder.Decode(&decoded); err != nil {
return nil, err
}

return decoded, nil
}
14 changes: 14 additions & 0 deletions lib/uuid/uuid.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright 2022 Tigris Data, Inc.
//
// 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 uuid

import uuid2 "github.com/google/uuid"
Expand Down
4 changes: 4 additions & 0 deletions schema/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ func (d *DefaultCollection) GetIndexes() *Indexes {
return d.Indexes
}

func (d *DefaultCollection) GetQueryableFields() []*QueryableField {
return d.QueryableFields
}

// Validate expects an unmarshalled document which it will validate again the schema of this collection.
func (d *DefaultCollection) Validate(document interface{}) error {
err := d.Validator.Validate(document)
Expand Down
12 changes: 6 additions & 6 deletions server/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import (
)

type ServerConfig struct {
Host string
Port int16
FDBDelete bool `mapstructure:"fdb_delete" yaml:"fdb_delete" json:"fdb_delete"`
Host string
Port int16
FDBHardDrop bool `mapstructure:"fdb_hard_drop" yaml:"fdb_hard_drop" json:"fdb_hard_drop"`
}

type Config struct {
Expand Down Expand Up @@ -107,9 +107,9 @@ var DefaultConfig = Config{
SampleRate: 0.01,
},
Server: ServerConfig{
Host: "0.0.0.0",
Port: 8081,
FDBDelete: false,
Host: "0.0.0.0",
Port: 8081,
FDBHardDrop: false,
},
Auth: AuthConfig{
IssuerURL: "https://tigrisdata-dev.us.auth0.com/",
Expand Down
84 changes: 84 additions & 0 deletions server/metadata/key_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package metadata

import (
"context"

"github.com/tigrisdata/tigris/internal"
"github.com/tigrisdata/tigris/keys"
"github.com/tigrisdata/tigris/server/metadata/encoding"
"github.com/tigrisdata/tigris/server/transaction"
"github.com/tigrisdata/tigris/store/kv"
)

const (
// generatorSubspaceKey is used to store ids in storage so that we can guarantee uniqueness
generatorSubspaceKey = "generator"
// int32IdKey is the prefix after generator subspace to store int32 counters
int32IdKey = "int32_id"
)

// TableKeyGenerator is used to generated keys that may need persistence like counter.
type TableKeyGenerator struct{}

func NewTableKeyGenerator() *TableKeyGenerator {
return &TableKeyGenerator{}
}

// GenerateCounter is used to generate an id in a transaction for int32 field only. This is mainly used to guarantee
// uniqueness with auto-incremented ids, so what we are doing is reserving this id in storage before returning to the
// caller so that only one id is assigned to one caller.
func (g *TableKeyGenerator) GenerateCounter(ctx context.Context, txMgr *transaction.Manager, table []byte) (int32, error) {
for {
tx, err := txMgr.StartTx(ctx)
if err != nil {
return -1, err
}

var valueI32 int32
if valueI32, err = g.generateCounter(ctx, tx, table); err != nil {
_ = tx.Rollback(ctx)
}

if err = tx.Commit(ctx); err == nil {
return valueI32, nil
}
if err != kv.ErrConflictingTransaction {
return -1, err
}
}
}

// generateCounter as it is used to generate int32 value, we are simply maintaining a counter. There is a contention to
// generate a counter if it is concurrently getting executed but the generation should be fast then it is best to start
// with this approach.
func (g *TableKeyGenerator) generateCounter(ctx context.Context, tx transaction.Tx, table []byte) (int32, error) {
key := keys.NewKey([]byte(generatorSubspaceKey), table, int32IdKey)
it, err := tx.Read(ctx, key)
if err != nil {
return 0, err
}

id := uint32(1)
var row kv.KeyValue
if it.Next(&row) {
id = encoding.ByteToUInt32(row.Data.RawData) + uint32(1)
}
if err := it.Err(); err != nil {
return 0, err
}

if err := tx.Replace(ctx, key, internal.NewTableData(encoding.UInt32ToByte(id))); err != nil {
return 0, err
}

return int32(id), nil
}

func (g *TableKeyGenerator) removeCounter(ctx context.Context, tx transaction.Tx, table []byte) error {
key := keys.NewKey([]byte(generatorSubspaceKey), table, int32IdKey)
if err := tx.Delete(ctx, key); err != nil {
return err
}

return nil
}
81 changes: 46 additions & 35 deletions server/metadata/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,17 @@ func (n *TenantNamespace) Id() uint32 {
type TenantManager struct {
sync.RWMutex

metaStore *encoding.MetadataDictionary
schemaStore *encoding.SchemaSubspace
kvStore kv.KeyValueStore
searchStore search.Store
tenants map[string]*Tenant
idToTenantMap map[uint32]string
version Version
versionH *VersionHandler
mdNameRegistry encoding.MDNameRegistry
encoder Encoder
metaStore *encoding.MetadataDictionary
schemaStore *encoding.SchemaSubspace
kvStore kv.KeyValueStore
searchStore search.Store
tenants map[string]*Tenant
idToTenantMap map[uint32]string
version Version
versionH *VersionHandler
mdNameRegistry encoding.MDNameRegistry
encoder Encoder
tableKeyGenerator *TableKeyGenerator
}

func NewTenantManager(kvStore kv.KeyValueStore, searchStore search.Store) *TenantManager {
Expand All @@ -125,15 +126,16 @@ func NewTenantManager(kvStore kv.KeyValueStore, searchStore search.Store) *Tenan

func newTenantManager(kvStore kv.KeyValueStore, searchStore search.Store, mdNameRegistry encoding.MDNameRegistry) *TenantManager {
return &TenantManager{
kvStore: kvStore,
searchStore: searchStore,
encoder: NewEncoder(),
metaStore: encoding.NewMetadataDictionary(mdNameRegistry),
schemaStore: encoding.NewSchemaStore(mdNameRegistry),
tenants: make(map[string]*Tenant),
idToTenantMap: make(map[uint32]string),
versionH: &VersionHandler{},
mdNameRegistry: mdNameRegistry,
kvStore: kvStore,
searchStore: searchStore,
encoder: NewEncoder(),
metaStore: encoding.NewMetadataDictionary(mdNameRegistry),
schemaStore: encoding.NewSchemaStore(mdNameRegistry),
tenants: make(map[string]*Tenant),
idToTenantMap: make(map[uint32]string),
versionH: &VersionHandler{},
mdNameRegistry: mdNameRegistry,
tableKeyGenerator: NewTableKeyGenerator(),
}
}

Expand Down Expand Up @@ -269,7 +271,7 @@ func (m *TenantManager) GetTenant(ctx context.Context, namespaceName string, txM
}

namespace := NewTenantNamespace(namespaceName, id)
tenant = NewTenant(namespace, m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, currentVersion)
tenant = NewTenant(namespace, m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, currentVersion, m.tableKeyGenerator)
if err = tenant.reload(ctx, tx, currentVersion); err != nil {
return nil, err
}
Expand Down Expand Up @@ -305,7 +307,7 @@ func (m *TenantManager) createOrGetTenantInternal(ctx context.Context, tx transa
return nil, err
}

tenant := NewTenant(namespace, m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, currentVersion)
tenant := NewTenant(namespace, m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, currentVersion, m.tableKeyGenerator)
tenant.Lock()
err = tenant.reload(ctx, tx, currentVersion)
tenant.Unlock()
Expand All @@ -323,7 +325,7 @@ func (m *TenantManager) createOrGetTenantInternal(ctx context.Context, tx transa
return nil, err
}

return NewTenant(namespace, m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, nil), nil
return NewTenant(namespace, m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, nil, m.tableKeyGenerator), nil
}

// GetTableNameFromIds returns tenant name, database name, collection name corresponding to their encoded ids.
Expand Down Expand Up @@ -421,7 +423,7 @@ func (m *TenantManager) reload(ctx context.Context, tx transaction.Tx, currentVe

for namespace, id := range namespaces {
if _, ok := m.tenants[namespace]; !ok {
m.tenants[namespace] = NewTenant(NewTenantNamespace(namespace, id), m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, currentVersion)
m.tenants[namespace] = NewTenant(NewTenantNamespace(namespace, id), m.kvStore, m.searchStore, m.metaStore, m.schemaStore, m.encoder, m.versionH, currentVersion, m.tableKeyGenerator)
m.idToTenantMap[id] = namespace
}
}
Expand All @@ -443,19 +445,20 @@ func (m *TenantManager) reload(ctx context.Context, tx transaction.Tx, currentVe
type Tenant struct {
sync.RWMutex

kvStore kv.KeyValueStore
searchStore search.Store
schemaStore *encoding.SchemaSubspace
metaStore *encoding.MetadataDictionary
Encoder Encoder
databases map[string]*Database
idToDatabaseMap map[uint32]string
namespace Namespace
version Version
versionH *VersionHandler
kvStore kv.KeyValueStore
searchStore search.Store
schemaStore *encoding.SchemaSubspace
metaStore *encoding.MetadataDictionary
Encoder Encoder
databases map[string]*Database
idToDatabaseMap map[uint32]string
namespace Namespace
version Version
versionH *VersionHandler
TableKeyGenerator *TableKeyGenerator
}

func NewTenant(namespace Namespace, kvStore kv.KeyValueStore, searchStore search.Store, dict *encoding.MetadataDictionary, schemaStore *encoding.SchemaSubspace, encoder Encoder, versionH *VersionHandler, currentVersion Version) *Tenant {
func NewTenant(namespace Namespace, kvStore kv.KeyValueStore, searchStore search.Store, dict *encoding.MetadataDictionary, schemaStore *encoding.SchemaSubspace, encoder Encoder, versionH *VersionHandler, currentVersion Version, tableKeyGenerator *TableKeyGenerator) *Tenant {
return &Tenant{
kvStore: kvStore,
searchStore: searchStore,
Expand Down Expand Up @@ -819,8 +822,16 @@ func (tenant *Tenant) dropCollection(ctx context.Context, tx transaction.Tx, db
return err
}

tableName, err := tenant.Encoder.EncodeTableName(tenant.namespace, db, cHolder.collection)
if err != nil {
return err
}
if err := tenant.TableKeyGenerator.removeCounter(ctx, tx, tableName); err != nil {
return err
}

// TODO: Move actual deletion out of the mutex
if config.DefaultConfig.Server.FDBDelete {
if config.DefaultConfig.Server.FDBHardDrop {
tableName, err := tenant.Encoder.EncodeTableName(tenant.namespace, db, cHolder.collection)
if err != nil {
return err
Expand Down
Loading

0 comments on commit 468ef86

Please sign in to comment.