blob: a84a366cfddd76bb4d0f027930c2370a43d6c6cf [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
/*
Package datastore - enables data to be persisted in built in datebase (Bolt)
*/
package datastore
import (
"errors"
)
var (
// ErrBackendNotInitialized is returned when the backend is not set
ErrBackendNotInitialized = errors.New("backend not initialized")
// ErrCodecNotInitialized is returned when the codec is not set
ErrCodecNotInitialized = errors.New("codec not initialized")
// ErrKeyNotFound is returned when an attempt to load a value of a missing key is made
ErrKeyNotFound = errors.New("key not found")
)
// Store provides key-value data storage with
// specific backend and codec
type Store struct {
backend Backend
codec Codec
}
// NewStore constructs a new store
func NewStore(options ...StoreOption) (*Store, error) {
s := &Store{}
for _, option := range options {
if err := option(s); err != nil {
return nil, err
}
}
return s, nil
}
// Set stores the value for a key of datatype
func (s *Store) Set(datatype, key string, v interface{}, indexData map[string]string) error {
if err := s.checkInit(); err != nil {
return err
}
vbytes, err := s.codec.Marshal(v)
if err != nil {
return err
}
if err := s.backend.Set(datatype, key, vbytes, indexData); err != nil {
return err
}
return nil
}
// Get retreives the value for specified key and datatyoe
// Returns ErrKeyNotFound if the key has no value set
func (s *Store) Get(datatype, key string, v interface{}) error {
if err := s.checkInit(); err != nil {
return err
}
vbytes, err := s.backend.Get(datatype, key)
if err != nil {
return err
}
if err := s.codec.Unmarshal(vbytes, v); err != nil {
return err
}
return nil
}
// Del deletes a key and all the indexes
func (s *Store) Del(datatype, key string) error {
if err := s.checkInit(); err != nil {
return err
}
return s.backend.Del(datatype, key)
}
// Close closes the database
func (s *Store) Close() error {
return s.backend.Close()
}
// ListKeys lists keys by index
func (s *Store) ListKeys(datatype, index string, skip, limit int, reverse bool) (keys []string, err error) {
return s.backend.ListKeys(datatype, index, skip, limit, reverse)
}
func (s *Store) checkInit() error {
if s.backend == nil {
return ErrBackendNotInitialized
}
if s.codec == nil {
return ErrBackendNotInitialized
}
return nil
}
// StoreOption sets additional parameters to the Store
type StoreOption func(s *Store) error
// WithBackend sets the store backend
func WithBackend(b Backend) StoreOption {
return func(s *Store) error {
s.backend = b
return nil
}
}
// WithCodec sets the store codec
func WithCodec(enc Codec) StoreOption {
return func(s *Store) error {
s.codec = enc
return nil
}
}
// Backend provides data storage interface
type Backend interface {
Set(datatype, key string, value []byte, indexData map[string]string) error
Get(datatype, key string) ([]byte, error)
Del(datatype, key string) error
ListKeys(datatype, index string, skip, limit int, reverse bool) (keys []string, err error)
Close() error
}
// Codec probides data serialization interface
type Codec interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal([]byte, interface{}) error
}