This commit is contained in:
Ilja Neumann
2020-10-01 12:33:23 +02:00
parent 85743a2129
commit e054bfc996
6 changed files with 59 additions and 51 deletions

View File

@@ -18,9 +18,9 @@ type Config struct {
Log zerolog.Logger
}
// Type can be implemented to create new index-strategies. See Unique for example.
// IndexType can be implemented to create new index-strategies. See Unique for example.
// Each index implementation is bound to one data-column (IndexBy) and a data-type (TypeName)
type Type interface {
type IndexType interface {
Init() error
Lookup(v string) ([]string, error)
Add(id, v string) (string, error)
@@ -39,63 +39,52 @@ func NewIndex(cfg *Config) *Index {
}
}
func (man Index) AddUniqueIndex(typeName, indexBy, entityDirName string) error {
fullDataPath := path.Join(man.config.DataDir, entityDirName)
indexPath := path.Join(man.config.DataDir, man.config.IndexRootDirName)
func (i Index) AddUniqueIndex(t interface{}, indexBy, pkName, entityDirName string) error {
typeName := getTypeFQN(t)
fullDataPath := path.Join(i.config.DataDir, entityDirName)
indexPath := path.Join(i.config.DataDir, i.config.IndexRootDirName)
idx := NewUniqueIndex(typeName, indexBy, fullDataPath, indexPath)
man.indices.addIndex(idx)
i.indices.addIndex(typeName, pkName, idx)
return idx.Init()
}
func (man Index) AddNormalIndex(typeName, indexBy, entityDirName string) error {
fullDataPath := path.Join(man.config.DataDir, entityDirName)
indexPath := path.Join(man.config.DataDir, man.config.IndexRootDirName)
func (i Index) AddNonUniqueIndex(t interface{}, indexBy, pkName, entityDirName string) error {
typeName := getTypeFQN(t)
fullDataPath := path.Join(i.config.DataDir, entityDirName)
indexPath := path.Join(i.config.DataDir, i.config.IndexRootDirName)
idx := NewNormalIndex(typeName, indexBy, fullDataPath, indexPath)
man.indices.addIndex(idx)
idx := NewNonUniqueIndex(typeName, indexBy, fullDataPath, indexPath)
i.indices.addIndex(typeName, pkName, idx)
return idx.Init()
}
func (man Index) AddIndex(idx Type) error {
man.indices.addIndex(idx)
return idx.Init()
}
// Add a new entry to the index
func (man Index) Add(primaryKey string, entity interface{}) error {
t, err := getType(entity)
if err != nil {
return err
func (i Index) Add(t interface{}) error {
typeName := getTypeFQN(t)
val, ok := i.indices[typeName]
if ok {
}
typeName := t.Type().Name()
if typeIndices, ok := man.indices[typeName]; ok {
for _, fieldIndices := range typeIndices {
for k := range fieldIndices {
curIdx := fieldIndices[k]
idxBy := curIdx.IndexBy()
val := valueOf(entity, idxBy)
_, err := curIdx.Add(primaryKey, val)
if err != nil {
return err
}
}
}
}
return nil
}
// Find a entry by type,field and value.
// // Find a User type by email
// man.Find("User", "Email", "foo@example.com")
func (man Index) Find(typeName, key, value string) (pk string, err error) {
func (i Index) Find(typeName, key, value string) (pk string, err error) {
var res = []string{}
if indices, ok := man.indices[typeName][key]; ok {
if indices, ok := i.indices[typeName][key]; ok {
for _, idx := range indices {
if res, err = idx.Lookup(value); IsNotFoundErr(err) {
continue
@@ -114,7 +103,9 @@ func (man Index) Find(typeName, key, value string) (pk string, err error) {
return path.Base(res[0]), err
}
func (man Index) Delete(typeName, pk string) error {
func (i Index) Delete(typeName, pk string) error {
return nil
}
*/

View File

@@ -1,16 +1,24 @@
package index
// indexMap stores the index layout at runtime.
type indexMap map[tName]map[indexByKey][]Type
type indexMap map[tName]typeMapping
type tName = string
type indexByKey = string
func (m indexMap) addIndex(idx Type) {
typeName, indexBy := idx.TypeName(), idx.IndexBy()
if _, ok := m[typeName]; !ok {
m[typeName] = map[indexByKey][]Type{}
}
m[typeName][indexBy] = append(m[typeName][indexBy], idx)
type typeMapping struct {
pKFieldName string
indicesByField map[string][]IndexType
}
func (m indexMap) addIndex(typeName string, pkName string, idx IndexType) {
if val, ok := m[typeName]; ok {
val.indicesByField[idx.IndexBy()] = append(val.indicesByField[idx.IndexBy()], idx)
return
}
m[typeName] = typeMapping{
pKFieldName: pkName,
indicesByField: map[string][]IndexType{
pkName: {idx},
},
}
}

View File

@@ -27,9 +27,9 @@ type NonUniqueIndex struct {
indexRootDir string
}
// NewNormalIndex instantiates a new NonUniqueIndex instance. Init() should be
// NewNonUniqueIndex instantiates a new NonUniqueIndex instance. Init() should be
// called afterward to ensure correct on-disk structure.
func NewNormalIndex(typeName, indexBy, filesDir, indexBaseDir string) NonUniqueIndex {
func NewNonUniqueIndex(typeName, indexBy, filesDir, indexBaseDir string) NonUniqueIndex {
return NonUniqueIndex{
indexBy: indexBy,
typeName: typeName,

View File

@@ -55,7 +55,7 @@ func TestNonUniqueIndexInit(t *testing.T) {
indexRootDir := path.Join(dataDir, "index.disk")
filesDir := path.Join(dataDir, "users")
uniq := NewNormalIndex("User", "DisplayName", filesDir, indexRootDir)
uniq := NewNonUniqueIndex("User", "DisplayName", filesDir, indexRootDir)
assert.Error(t, uniq.Init(), "Init should return an error about missing files-dir")
if err := os.Mkdir(filesDir, 0777); err != nil {
@@ -87,9 +87,9 @@ func TestNonUniqueIndexSearch(t *testing.T) {
_ = os.RemoveAll(dataPath)
}
func getNonUniqueIdxSut(t *testing.T) (sut Type, dataPath string) {
func getNonUniqueIdxSut(t *testing.T) (sut IndexType, dataPath string) {
dataPath = writeIndexTestData(t, testData, "Id")
sut = NewNormalIndex("Pet", "Color", path.Join(dataPath, "pets"), path.Join(dataPath, "index.disk"))
sut = NewNonUniqueIndex("Pet", "Color", path.Join(dataPath, "pets"), path.Join(dataPath, "index.disk"))
err := sut.Init()
if err != nil {
t.Fatal(err)

View File

@@ -2,7 +2,9 @@ package index
import (
"errors"
"path"
"reflect"
"strings"
)
func getType(v interface{}) (reflect.Value, error) {
@@ -17,6 +19,13 @@ func getType(v interface{}) (reflect.Value, error) {
return rv, nil
}
func getTypeFQN(t interface{}) string {
typ, _ := getType(t)
typeName := path.Join(typ.Type().PkgPath(), typ.Type().Name())
typeName = strings.ReplaceAll(typeName, "/", ".")
return typeName
}
func valueOf(v interface{}, field string) string {
r := reflect.ValueOf(v)
f := reflect.Indirect(r).FieldByName(field)

View File

@@ -112,7 +112,7 @@ func TestErrors(t *testing.T) {
assert.True(t, IsNotFoundErr(&notFoundErr{}))
}
func getUniqueIdxSut(t *testing.T) (sut Type, dataPath string) {
func getUniqueIdxSut(t *testing.T) (sut IndexType, dataPath string) {
dataPath = writeIndexTestData(t, testData, "Id")
sut = NewUniqueIndex("User", "Email", path.Join(dataPath, "users"), path.Join(dataPath, "index.disk"))
err := sut.Init()