Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move tableInfoStore to the transaction #245

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 3 additions & 62 deletions database/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ type TableInfo struct {
// name of the store associated with the table.
storeName []byte
readOnly bool
// if non-zero, this tableInfo has been created during the current transaction.
// it will be removed if the transaction is rolled back or set to false if its commited.
transactionID int64

FieldConstraints []FieldConstraint
}
Expand Down Expand Up @@ -152,7 +149,7 @@ func (ti *TableInfo) ScanDocument(d document.Document) error {
}

// tableInfoStore manages table information.
// It loads table information during database startup
// It loads table information on transaction start
// and holds it in memory.
type tableInfoStore struct {
db *Database
Expand All @@ -162,19 +159,6 @@ type tableInfoStore struct {
mu sync.RWMutex
}

func newTableInfoStore(db *Database, tx engine.Transaction) (*tableInfoStore, error) {
ts := tableInfoStore{
db: db,
}

err := ts.loadAllTableInfo(tx)
if err != nil {
return nil, err
}

return &ts, nil
}

// Insert a new tableInfo for the given table name.
// If info.storeName is nil, it generates one and stores it in info.
func (t *tableInfoStore) Insert(tx *Transaction, tableName string, info *TableInfo) error {
Expand All @@ -183,12 +167,6 @@ func (t *tableInfoStore) Insert(tx *Transaction, tableName string, info *TableIn

_, ok := t.tableInfos[tableName]
if ok {
// TODO(asdine): if a table already exists but is uncommited,
// there is a chance the other transaction will be rolled back.
// Instead of returning an error, wait until the other transaction is
// either commited or rolled back.
// If it is commited, return an error here
// If not, create the table in this transaction.
return ErrTableAlreadyExists
}

Expand Down Expand Up @@ -219,7 +197,6 @@ func (t *tableInfoStore) Insert(tx *Transaction, tableName string, info *TableIn
return err
}

info.transactionID = tx.id
t.tableInfos[tableName] = *info
return nil
}
Expand All @@ -233,26 +210,18 @@ func (t *tableInfoStore) Get(tx *Transaction, tableName string) (*TableInfo, err
return nil, ErrTableNotFound
}

if info.transactionID != 0 && info.transactionID != tx.id {
return nil, ErrTableNotFound
}

return &info, nil
}

func (t *tableInfoStore) Delete(tx *Transaction, tableName string) error {
t.mu.Lock()
defer t.mu.Unlock()

info, ok := t.tableInfos[tableName]
_, ok := t.tableInfos[tableName]
if !ok {
return ErrTableNotFound
}

if info.transactionID != 0 && info.transactionID != tx.id {
return ErrTableNotFound
}

st, err := tx.tx.GetStore([]byte(tableInfoStoreName))
if err != nil {
return err
Expand Down Expand Up @@ -319,7 +288,7 @@ func (t *tableInfoStore) loadAllTableInfo(tx engine.Transaction) error {

t.tableInfos[indexStoreName] = TableInfo{
storeName: []byte(indexStoreName),
readOnly: true,
readOnly: true,
FieldConstraints: []FieldConstraint{
{
Path: document.ValuePath{
Expand All @@ -335,34 +304,6 @@ func (t *tableInfoStore) loadAllTableInfo(tx engine.Transaction) error {
return nil
}

// remove all tableInfo whose transaction id is equal to the given transacrion id.
// this is called when a read/write transaction is being rolled back.
func (t *tableInfoStore) rollback(tx *Transaction) {
t.mu.Lock()
defer t.mu.Unlock()

for k, info := range t.tableInfos {
if info.transactionID == tx.id {
delete(t.tableInfos, k)
}
}
}

// set all the tableInfo created by this transaction to 0.
// this is called when a read/write transaction is being commited.
func (t *tableInfoStore) commit(tx *Transaction) {
t.mu.Lock()
defer t.mu.Unlock()

for k := range t.tableInfos {
if t.tableInfos[k].transactionID == tx.id {
info := t.tableInfos[k]
info.transactionID = 0
t.tableInfos[k] = info
}
}
}

// GetTableInfo returns a copy of all the table information.
func (t *tableInfoStore) GetTableInfo() map[string]TableInfo {
t.mu.RLock()
Expand Down
24 changes: 8 additions & 16 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package database
import (
"errors"
"sync"
"sync/atomic"

"github.com/genjidb/genji/document/encoding"
"github.com/genjidb/genji/engine"
Expand All @@ -17,11 +16,6 @@ type Database struct {
// tableInfoStore manages information about all the tables
tableInfoStore *tableInfoStore

// This stores the last transaction id created.
// It starts at 0 at database startup and is
// incremented atomically every time Begin is called.
lastTransactionID int64

// If this is non-nil, the user is running an explicit transaction
// using the BEGIN statement.
// Only one attached transaction can be run at a time and any calls to DB.Begin()
Expand Down Expand Up @@ -59,11 +53,6 @@ func New(ng engine.Engine, opts Options) (*Database, error) {
return nil, err
}

db.tableInfoStore, err = newTableInfoStore(&db, ntx)
if err != nil {
return nil, err
}

err = ntx.Commit()
if err != nil {
return nil, err
Expand Down Expand Up @@ -123,11 +112,14 @@ func (db *Database) BeginTx(opts *TxOptions) (*Transaction, error) {
}

tx := Transaction{
id: atomic.AddInt64(&db.lastTransactionID, 1),
db: db,
tx: ntx,
writable: !opts.ReadOnly,
tableInfoStore: db.tableInfoStore,
db: db,
tx: ntx,
writable: !opts.ReadOnly,
}

tx.tableInfoStore, err = tx.getTableInfoStore()
if err != nil {
return nil, err
}

tx.indexStore, err = tx.getIndexStore()
Expand Down
22 changes: 13 additions & 9 deletions database/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ var (
// Transaction is either read-only or read/write. Read-only can be used to read tables
// and read/write can be used to read, create, delete and modify tables.
type Transaction struct {
id int64
db *Database
tx engine.Transaction
writable bool
Expand All @@ -40,10 +39,6 @@ func (tx *Transaction) Rollback() error {
tx.db.attachedTxMu.Lock()
defer tx.db.attachedTxMu.Unlock()

if tx.writable {
tx.tableInfoStore.rollback(tx)
}

err := tx.tx.Rollback()
if err != nil {
return err
Expand All @@ -61,10 +56,6 @@ func (tx *Transaction) Commit() error {
tx.db.attachedTxMu.Lock()
defer tx.db.attachedTxMu.Unlock()

if tx.writable {
tx.tableInfoStore.commit(tx)
}

err := tx.tx.Commit()
if err != nil {
return err
Expand Down Expand Up @@ -342,6 +333,19 @@ func (tx *Transaction) ReIndexAll() error {
return nil
}

func (tx *Transaction) getTableInfoStore() (*tableInfoStore, error) {
ts := tableInfoStore{
db: tx.db,
}

err := ts.loadAllTableInfo(tx.tx)
if err != nil {
return nil, err
}

return &ts, nil
}

func (tx *Transaction) getIndexStore() (*indexStore, error) {
st, err := tx.tx.GetStore([]byte(indexStoreName))
if err != nil {
Expand Down