-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #398 from tigrisdata/main
Release Alpha
- Loading branch information
Showing
36 changed files
with
481 additions
and
217 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.