2016-02-10 02:29:58 +01:00
|
|
|
// Copyright (c) 2016 Couchbase, Inc.
|
2016-10-02 16:13:14 +02:00
|
|
|
//
|
|
|
|
// Licensed 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.
|
2016-02-10 02:29:58 +01:00
|
|
|
|
|
|
|
// Package moss provides a KVStore implementation based on the
|
|
|
|
// github.com/couchbaselabs/moss library.
|
|
|
|
|
|
|
|
package moss
|
|
|
|
|
|
|
|
import (
|
2016-03-04 19:43:39 +01:00
|
|
|
"encoding/json"
|
2016-02-10 02:29:58 +01:00
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/couchbase/moss"
|
|
|
|
|
|
|
|
"github.com/blevesearch/bleve/index/store"
|
|
|
|
"github.com/blevesearch/bleve/registry"
|
|
|
|
)
|
|
|
|
|
2016-03-09 18:39:01 +01:00
|
|
|
// RegistryCollectionOptions should be treated as read-only after
|
|
|
|
// process init()'ialization.
|
|
|
|
var RegistryCollectionOptions = map[string]moss.CollectionOptions{}
|
|
|
|
|
2016-02-10 02:29:58 +01:00
|
|
|
const Name = "moss"
|
|
|
|
|
|
|
|
type Store struct {
|
2016-03-04 19:43:39 +01:00
|
|
|
m sync.Mutex
|
|
|
|
ms moss.Collection
|
|
|
|
mo store.MergeOperator
|
2016-11-18 19:34:27 +01:00
|
|
|
llstore store.KVStore // May be nil.
|
2016-09-09 01:22:15 +02:00
|
|
|
llstats statsFunc // May be nil.
|
2016-03-08 00:37:46 +01:00
|
|
|
|
|
|
|
s *stats
|
2016-02-10 02:29:58 +01:00
|
|
|
}
|
|
|
|
|
2016-09-09 01:22:15 +02:00
|
|
|
type statsFunc func() map[string]interface{}
|
|
|
|
|
2016-03-09 18:39:01 +01:00
|
|
|
// New initializes a moss storage with values from the optional
|
|
|
|
// config["mossCollectionOptions"] (a JSON moss.CollectionOptions).
|
|
|
|
// Next, values from the RegistryCollectionOptions, named by the
|
|
|
|
// optional config["mossCollectionOptionsName"], take precedence.
|
|
|
|
// Finally, base case defaults are taken from
|
|
|
|
// moss.DefaultCollectionOptions.
|
2016-02-10 02:29:58 +01:00
|
|
|
func New(mo store.MergeOperator, config map[string]interface{}) (
|
|
|
|
store.KVStore, error) {
|
2016-03-09 18:39:01 +01:00
|
|
|
options := moss.DefaultCollectionOptions // Copy.
|
2016-02-10 02:29:58 +01:00
|
|
|
|
2016-03-09 18:39:01 +01:00
|
|
|
v, ok := config["mossCollectionOptionsName"]
|
2016-02-10 02:29:58 +01:00
|
|
|
if ok {
|
2016-03-09 18:39:01 +01:00
|
|
|
name, ok := v.(string)
|
2016-02-10 02:29:58 +01:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("moss store,"+
|
2016-03-09 18:39:01 +01:00
|
|
|
" could not parse config[mossCollectionOptionsName]: %v", v)
|
2016-02-10 02:29:58 +01:00
|
|
|
}
|
|
|
|
|
2016-03-09 18:39:01 +01:00
|
|
|
options, ok = RegistryCollectionOptions[name] // Copy.
|
2016-02-10 02:29:58 +01:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("moss store,"+
|
2016-03-09 18:39:01 +01:00
|
|
|
" could not find RegistryCollectionOptions, name: %s", name)
|
2016-02-10 02:29:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-08 02:38:43 +02:00
|
|
|
options.MergeOperator = mo
|
|
|
|
options.DeferredSort = true
|
|
|
|
|
2016-03-09 18:39:01 +01:00
|
|
|
v, ok = config["mossCollectionOptions"]
|
2016-02-10 02:29:58 +01:00
|
|
|
if ok {
|
2016-03-09 18:39:01 +01:00
|
|
|
b, err := json.Marshal(v) // Convert from map[string]interface{}.
|
|
|
|
if err != nil {
|
2016-02-10 02:29:58 +01:00
|
|
|
return nil, fmt.Errorf("moss store,"+
|
2016-05-21 01:37:40 +02:00
|
|
|
" could not marshal config[mossCollectionOptions]: %v, err: %v", v, err)
|
2016-02-10 02:29:58 +01:00
|
|
|
}
|
|
|
|
|
2016-03-09 18:39:01 +01:00
|
|
|
err = json.Unmarshal(b, &options)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("moss store,"+
|
2016-05-21 01:37:40 +02:00
|
|
|
" could not unmarshal config[mossCollectionOptions]: %v, err: %v", v, err)
|
2016-03-09 18:39:01 +01:00
|
|
|
}
|
2016-02-10 02:29:58 +01:00
|
|
|
}
|
|
|
|
|
2016-03-09 18:39:01 +01:00
|
|
|
// --------------------------------------------------
|
|
|
|
|
2016-03-12 00:47:09 +01:00
|
|
|
if options.Log == nil || options.Debug <= 0 {
|
2016-03-09 19:15:11 +01:00
|
|
|
options.Log = func(format string, a ...interface{}) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
|
2016-02-10 02:29:58 +01:00
|
|
|
mossLowerLevelStoreName := ""
|
|
|
|
v, ok = config["mossLowerLevelStoreName"]
|
|
|
|
if ok {
|
|
|
|
mossLowerLevelStoreName, ok = v.(string)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("moss store,"+
|
|
|
|
" could not parse config[mossLowerLevelStoreName]: %v", v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-04 19:43:39 +01:00
|
|
|
var llStore store.KVStore
|
2016-09-09 01:22:15 +02:00
|
|
|
var llStats statsFunc
|
|
|
|
|
2016-02-10 02:29:58 +01:00
|
|
|
if options.LowerLevelInit == nil &&
|
|
|
|
options.LowerLevelUpdate == nil &&
|
|
|
|
mossLowerLevelStoreName != "" {
|
|
|
|
mossLowerLevelStoreConfig := map[string]interface{}{}
|
|
|
|
v, ok := config["mossLowerLevelStoreConfig"]
|
|
|
|
if ok {
|
|
|
|
mossLowerLevelStoreConfig, ok = v.(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("moss store, initLowerLevelStore,"+
|
|
|
|
" could parse mossLowerLevelStoreConfig: %v", v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 19:09:15 +01:00
|
|
|
mossLowerLevelMaxBatchSize := uint64(0)
|
|
|
|
v, ok = config["mossLowerLevelMaxBatchSize"]
|
|
|
|
if ok {
|
|
|
|
mossLowerLevelMaxBatchSizeF, ok := v.(float64)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("moss store,"+
|
|
|
|
" could not parse config[mossLowerLevelMaxBatchSize]: %v", v)
|
|
|
|
}
|
|
|
|
|
|
|
|
mossLowerLevelMaxBatchSize = uint64(mossLowerLevelMaxBatchSizeF)
|
|
|
|
}
|
|
|
|
|
2016-09-09 01:22:15 +02:00
|
|
|
lowerLevelInit, lowerLevelUpdate, lowerLevelStore, lowerLevelStats, err :=
|
2016-06-08 02:38:43 +02:00
|
|
|
initLowerLevelStore(config,
|
2016-02-10 02:29:58 +01:00
|
|
|
mossLowerLevelStoreName,
|
|
|
|
mossLowerLevelStoreConfig,
|
|
|
|
mossLowerLevelMaxBatchSize,
|
2016-06-08 02:38:43 +02:00
|
|
|
options)
|
2016-02-10 02:29:58 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
options.LowerLevelInit = lowerLevelInit
|
|
|
|
options.LowerLevelUpdate = lowerLevelUpdate
|
2016-09-09 01:22:15 +02:00
|
|
|
|
2016-03-04 19:43:39 +01:00
|
|
|
llStore = lowerLevelStore
|
2016-09-09 01:22:15 +02:00
|
|
|
llStats = lowerLevelStats
|
2016-02-10 02:29:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
|
|
|
|
ms, err := moss.NewCollection(options)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
err = ms.Start()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
rv := Store{
|
2016-03-04 19:43:39 +01:00
|
|
|
ms: ms,
|
|
|
|
mo: mo,
|
|
|
|
llstore: llStore,
|
2016-09-09 01:22:15 +02:00
|
|
|
llstats: llStats,
|
2016-02-10 02:29:58 +01:00
|
|
|
}
|
2016-03-08 00:37:46 +01:00
|
|
|
rv.s = &stats{s: &rv}
|
2016-02-10 02:29:58 +01:00
|
|
|
return &rv, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Store) Close() error {
|
|
|
|
return s.ms.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Store) Reader() (store.KVReader, error) {
|
|
|
|
ss, err := s.ms.Snapshot()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &Reader{ss: ss}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Store) Writer() (store.KVWriter, error) {
|
|
|
|
return &Writer{s: s}, nil
|
|
|
|
}
|
|
|
|
|
2016-02-17 22:03:54 +01:00
|
|
|
func (s *Store) Logf(fmt string, args ...interface{}) {
|
|
|
|
options := s.ms.Options()
|
|
|
|
if options.Log != nil {
|
|
|
|
options.Log(fmt, args...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-04 19:43:39 +01:00
|
|
|
func (s *Store) Stats() json.Marshaler {
|
2016-03-08 00:37:46 +01:00
|
|
|
return s.s
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Store) StatsMap() map[string]interface{} {
|
|
|
|
return s.s.statsMap()
|
2016-03-04 19:43:39 +01:00
|
|
|
}
|
|
|
|
|
2016-11-18 19:34:27 +01:00
|
|
|
func (s *Store) LowerLevelStore() store.KVStore {
|
|
|
|
return s.llstore
|
|
|
|
}
|
|
|
|
|
2016-02-10 02:29:58 +01:00
|
|
|
func init() {
|
|
|
|
registry.RegisterKVStore(Name, New)
|
|
|
|
}
|