Skip to content

Commit

Permalink
Protect entityMetadataMap from concurrent access #197 (#214)
Browse files Browse the repository at this point in the history
  • Loading branch information
platsko committed May 2, 2021
1 parent 6e9d4c1 commit 3c1da95
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 39 deletions.
71 changes: 32 additions & 39 deletions code/go/0chain.net/core/datastore/entity_metadata.go
Original file line number Diff line number Diff line change
@@ -1,63 +1,56 @@
package datastore

type InstanceProvider func() Entity

var entityMetadataMap = make(map[string]EntityMetadata)

/*RegisterEntityProvider - keep track of a list of entity providers. An entity can be registered with multiple names
* as long as two entities don't use the same name
*/
func RegisterEntityMetadata(entityName string, entityMetadata EntityMetadata) {
entityMetadataMap[entityName] = entityMetadata
}

/*GetEntityMetadata - return an instance of the entity */
func GetEntityMetadata(entityName string) EntityMetadata {
return entityMetadataMap[entityName]
}

/*GetEntity - return an instance of the entity */
func GetEntity(entityName string) Entity {
return GetEntityMetadata(entityName).Instance()
}

type EntityMetadata interface {
GetName() string
GetDB() string
Instance() Entity
GetStore() Store
GetIDColumnName() string
}

type EntityMetadataImpl struct {
Name string
DB string
Store Store
Provider InstanceProvider
IDColumnName string
}

type (
// InstanceProvider describes the instance function signature.
InstanceProvider func() Entity

// EntityMetadata describes the interface of the metadata entity.
EntityMetadata interface {
GetName() string
GetDB() string
Instance() Entity
GetStore() Store
GetIDColumnName() string
}

// EntityMetadataImpl implements EntityMetadata interface.
EntityMetadataImpl struct {
Name string
DB string
Store Store
Provider InstanceProvider
IDColumnName string
}
)

// MetadataProvider constructs entity metadata instance.
func MetadataProvider() *EntityMetadataImpl {
em := EntityMetadataImpl{IDColumnName: "id"}
return &em
return &EntityMetadataImpl{
IDColumnName: "id",
}
}

// GetName implements EntityMetadata.GetName method of interface.
func (em *EntityMetadataImpl) GetName() string {
return em.Name
}

// GetDB implements EntityMetadata.GetDB method of interface.
func (em *EntityMetadataImpl) GetDB() string {
return em.DB
}

// Instance implements EntityMetadata.Instance method of interface.
func (em *EntityMetadataImpl) Instance() Entity {
return em.Provider()
}

// GetStore implements EntityMetadata.GetStore method of interface.
func (em *EntityMetadataImpl) GetStore() Store {
return em.Store
}

// GetIDColumnName implements EntityMetadata.GetIDColumnName method of interface.
func (em *EntityMetadataImpl) GetIDColumnName() string {
return em.IDColumnName
}
45 changes: 45 additions & 0 deletions code/go/0chain.net/core/datastore/entity_metadata_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package datastore

import (
"sync"
)

type (
// entityMetadataStore describes the structure of entity metadata storage
// it is safe for concurrent use by multiple read-write operation access.
entityMetadataStore struct {
store map[string]EntityMetadata // entity metadata storage
mutex sync.Mutex // read-write mutex
}
)

var (
// entityMetadataMap keeps instance of entity metadata store.
entityMetadataMap = entityMetadataStore{
store: make(map[string]EntityMetadata),
}
)

// RegisterEntityMetadata registers an instance of the entity
// in track of a list of entity providers by given name.
// An entity can be registered with multiple names
// as long as two entities don't use the same name.
func RegisterEntityMetadata(entityName string, entityMetadata EntityMetadata) {
entityMetadataMap.mutex.Lock()
entityMetadataMap.store[entityName] = entityMetadata
entityMetadataMap.mutex.Unlock()
}

// GetEntityMetadata returns an instance of the entity by name.
func GetEntityMetadata(entityName string) EntityMetadata {
entityMetadataMap.mutex.Lock()
em := entityMetadataMap.store[entityName]
entityMetadataMap.mutex.Unlock()

return em
}

// GetEntity returns an instance of the entity.
func GetEntity(entityName string) Entity {
return GetEntityMetadata(entityName).Instance()
}

0 comments on commit 3c1da95

Please sign in to comment.