goc/pkg/server/store/filestore.go
2021-09-09 14:26:42 +08:00

219 lines
3.5 KiB
Go

package store
import (
"bufio"
"fmt"
"os"
"strings"
"sync"
)
type FileStore struct {
storePath string
mu sync.Mutex
}
func NewFileStore(path string) (Store, error) {
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, os.ModePerm)
if err != nil {
return nil, err
}
defer f.Close()
return &FileStore{
storePath: path,
}, nil
}
func (s *FileStore) Get(key string) (string, error) {
s.mu.Lock()
defer s.mu.Unlock()
f, err := os.Open(s.storePath)
if err != nil {
return "", err
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
items := strings.SplitN(line, " ", 2)
keyCandidate := items[0]
value := items[1]
if key == keyCandidate {
return value, nil
}
}
if scanner.Err() != nil {
return "", scanner.Err()
}
return "", fmt.Errorf("no key found")
}
func (s *FileStore) Set(key string, value string) error {
s.mu.Lock()
defer s.mu.Unlock()
f, err := os.OpenFile(s.storePath, os.O_RDWR, os.ModePerm)
if err != nil {
return err
}
defer f.Close()
var outputLines string
scanner := bufio.NewScanner(f)
isFound := false
for scanner.Scan() {
line := scanner.Text()
items := strings.SplitN(line, " ", 2)
keyCandidate := items[0]
if key == keyCandidate {
line = key + " " + value
isFound = true
} else {
}
outputLines += line + "\n"
}
if scanner.Err() != nil {
return scanner.Err()
}
if !isFound {
outputLines += key + " " + value + "\n"
}
if err := os.Truncate(s.storePath, 0); err != nil {
return err
}
f.Seek(0, os.SEEK_SET)
f.WriteString(outputLines)
f.Sync()
return nil
}
func (s *FileStore) Remove(key string) error {
s.mu.Lock()
defer s.mu.Unlock()
f, err := os.OpenFile(s.storePath, os.O_RDWR, os.ModePerm)
if err != nil {
return err
}
defer f.Close()
var outputLines string
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
items := strings.SplitN(line, " ", 2)
keyCandidate := items[0]
if key == keyCandidate {
// pass
} else {
outputLines += line + "\n"
}
}
if scanner.Err() != nil {
return scanner.Err()
}
if err := os.Truncate(s.storePath, 0); err != nil {
return err
}
f.Seek(0, os.SEEK_SET)
f.WriteString(outputLines)
f.Sync()
return nil
}
func (s *FileStore) Range(pattern string) ([]string, error) {
s.mu.Lock()
defer s.mu.Unlock()
f, err := os.Open(s.storePath)
if err != nil {
return nil, err
}
defer f.Close()
output := make([]string, 0)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
items := strings.SplitN(line, " ", 2)
fmt.Println(items)
keyCandidate := items[0]
value := items[1]
if strings.HasPrefix(keyCandidate, pattern) {
output = append(output, value)
}
}
if scanner.Err() != nil {
return nil, scanner.Err()
}
if len(output) == 0 {
return nil, fmt.Errorf("no key found")
} else {
return output, nil
}
}
func (s *FileStore) RangeRemove(pattern string) error {
s.mu.Lock()
defer s.mu.Unlock()
f, err := os.OpenFile(s.storePath, os.O_RDWR, os.ModePerm)
if err != nil {
return err
}
defer f.Close()
var outputLines string
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
items := strings.SplitN(line, " ", 2)
keyCandidate := items[0]
if strings.HasPrefix(keyCandidate, pattern) {
// pass
} else {
outputLines += line + "\n"
}
}
if scanner.Err() != nil {
return scanner.Err()
}
if err := os.Truncate(s.storePath, 0); err != nil {
return err
}
f.Seek(0, os.SEEK_SET)
f.WriteString(outputLines)
f.Sync()
return nil
}