storage/map.go

99 lines
1.8 KiB
Go
Executable File

package storage
import (
"fmt"
"local/storage/resolve"
"sync"
)
type Map struct {
m map[string]map[string][]byte
lock *sync.RWMutex
}
func NewMap() *Map {
return &Map{
m: make(map[string]map[string][]byte),
lock: &sync.RWMutex{},
}
}
func (m *Map) String() string {
m.lock.RLock()
defer m.lock.RUnlock()
s := ""
for k, v := range m.m {
if s != "" {
s += ",\n"
}
s += fmt.Sprintf("[%s]:[%s]", k, v)
}
return s
}
func (m *Map) Close() error {
m.lock.Lock()
defer m.lock.Unlock()
m.m = nil
return nil
}
func (m *Map) Namespaces() ([][]string, error) {
keys := [][]string{}
for key := range m.m {
keys = append(keys, resolve.UnNamespace(key))
}
return keys, nil
}
func (m *Map) List(ns []string, limits ...string) ([]string, error) {
m.lock.RLock()
defer m.lock.RUnlock()
namespace := resolve.Namespace(ns)
limits = resolve.Limits(limits)
keys := []string{}
if _, ok := m.m[namespace]; !ok {
namespace = resolve.DefaultNamespace
}
for k := range m.m[namespace] {
if k >= limits[0] && k <= limits[1] {
keys = append(keys, k)
}
}
return keys, nil
}
func (m *Map) Get(key string, ns ...string) ([]byte, error) {
m.lock.RLock()
defer m.lock.RUnlock()
namespace := resolve.Namespace(ns)
if _, ok := m.m[namespace]; !ok {
return nil, ErrNotFound
}
if _, ok := m.m[namespace][key]; !ok {
return nil, ErrNotFound
}
return m.m[namespace][key], nil
}
func (m *Map) Set(key string, value []byte, ns ...string) error {
m.lock.Lock()
defer m.lock.Unlock()
namespace := resolve.Namespace(ns)
if value == nil {
if _, ok := m.m[namespace]; !ok {
return nil
} else if _, ok := m.m[namespace][key]; ok {
delete(m.m[namespace], key)
}
} else {
if _, ok := m.m[namespace]; !ok {
m.m[namespace] = make(map[string][]byte)
}
m.m[namespace][key] = value
}
return nil
}