1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
package inmemory
import (
"fmt"
"sync"
"github.com/go-logr/logr"
"github.com/google/uuid"
"github.com/ovn-kubernetes/libovsdb/cache"
dbase "github.com/ovn-kubernetes/libovsdb/database"
"github.com/ovn-kubernetes/libovsdb/database/transaction"
"github.com/ovn-kubernetes/libovsdb/model"
"github.com/ovn-kubernetes/libovsdb/ovsdb"
)
type inMemoryDatabase struct {
databases map[string]*cache.TableCache
models map[string]model.ClientDBModel
references map[string]dbase.References
logger *logr.Logger
mutex sync.RWMutex
}
func NewDatabase(models map[string]model.ClientDBModel, logger *logr.Logger) dbase.Database {
return &inMemoryDatabase{
databases: make(map[string]*cache.TableCache),
models: models,
references: make(map[string]dbase.References),
mutex: sync.RWMutex{},
logger: logger,
}
}
func (db *inMemoryDatabase) NewTransaction(dbName string) dbase.Transaction {
db.mutex.Lock()
defer db.mutex.Unlock()
var model model.DatabaseModel
if database, ok := db.databases[dbName]; ok {
model = database.DatabaseModel()
}
transaction := transaction.NewTransaction(model, dbName, db, db.logger)
return &transaction
}
func (db *inMemoryDatabase) CreateDatabase(name string, schema ovsdb.DatabaseSchema) error {
db.mutex.Lock()
defer db.mutex.Unlock()
var mo model.ClientDBModel
var ok bool
if mo, ok = db.models[schema.Name]; !ok {
return fmt.Errorf("no db model provided for schema with name %s", name)
}
dbModel, errs := model.NewDatabaseModel(schema, mo)
if len(errs) > 0 {
return fmt.Errorf("failed to create DatabaseModel: %#+v", errs)
}
database, err := cache.NewTableCache(dbModel, nil, nil)
if err != nil {
return err
}
db.databases[name] = database
db.references[name] = make(dbase.References)
return nil
}
func (db *inMemoryDatabase) Exists(name string) bool {
db.mutex.RLock()
defer db.mutex.RUnlock()
_, ok := db.databases[name]
return ok
}
func (db *inMemoryDatabase) Commit(database string, _ uuid.UUID, update dbase.Update) error {
if !db.Exists(database) {
return fmt.Errorf("db does not exist")
}
db.mutex.RLock()
targetDb := db.databases[database]
db.mutex.RUnlock()
err := targetDb.ApplyCacheUpdate(update)
if err != nil {
return err
}
return update.ForReferenceUpdates(func(references dbase.References) error {
db.references[database].UpdateReferences(references)
return nil
})
}
func (db *inMemoryDatabase) CheckIndexes(database string, table string, m model.Model) error {
if !db.Exists(database) {
return nil
}
db.mutex.RLock()
targetDb := db.databases[database]
db.mutex.RUnlock()
targetTable := targetDb.Table(table)
return targetTable.IndexExists(m)
}
func (db *inMemoryDatabase) List(database, table string, conditions ...ovsdb.Condition) (map[string]model.Model, error) {
if !db.Exists(database) {
return nil, fmt.Errorf("db does not exist")
}
db.mutex.RLock()
targetDb := db.databases[database]
db.mutex.RUnlock()
targetTable := targetDb.Table(table)
if targetTable == nil {
return nil, fmt.Errorf("table does not exist")
}
return targetTable.RowsByCondition(conditions)
}
func (db *inMemoryDatabase) Get(database, table string, uuid string) (model.Model, error) {
if !db.Exists(database) {
return nil, fmt.Errorf("db does not exist")
}
db.mutex.RLock()
targetDb := db.databases[database]
db.mutex.RUnlock()
targetTable := targetDb.Table(table)
if targetTable == nil {
return nil, fmt.Errorf("table does not exist")
}
return targetTable.Row(uuid), nil
}
func (db *inMemoryDatabase) GetReferences(database, table, row string) (dbase.References, error) {
if !db.Exists(database) {
return nil, fmt.Errorf("db does not exist")
}
db.mutex.RLock()
defer db.mutex.RUnlock()
return db.references[database].GetReferences(table, row), nil
}
|