github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/sorted/kv.go (about)

     1  /*
     2  Copyright 2013 The Camlistore Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package sorted provides a KeyValue interface and constructor registry.
    18  package sorted
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  
    24  	"camlistore.org/pkg/jsonconfig"
    25  )
    26  
    27  var ErrNotFound = errors.New("index: key not found")
    28  
    29  // KeyValue is a sorted, enumerable key-value interface supporting
    30  // batch mutations.
    31  type KeyValue interface {
    32  	// Get gets the value for the given key. It returns ErrNotFound if the DB
    33  	// does not contain the key.
    34  	Get(key string) (string, error)
    35  
    36  	Set(key, value string) error
    37  
    38  	// Delete deletes keys. Deleting a non-existent key does not return an error.
    39  	Delete(key string) error
    40  
    41  	BeginBatch() BatchMutation
    42  	CommitBatch(b BatchMutation) error
    43  
    44  	// Find returns an iterator positioned before the first key/value pair
    45  	// whose key is 'greater than or equal to' the given key. There may be no
    46  	// such pair, in which case the iterator will return false on Next.
    47  	//
    48  	// The optional end value specifies the exclusive upper
    49  	// bound. If the empty string, the iterator returns keys
    50  	// where "key >= start".
    51  	// If non-empty, the iterator returns keys where
    52  	// "key >= start && key < endHint".
    53  	//
    54  	// Any error encountered will be implicitly returned via the iterator. An
    55  	// error-iterator will yield no key/value pairs and closing that iterator
    56  	// will return that error.
    57  	Find(start, end string) Iterator
    58  
    59  	// Close is a polite way for the server to shut down the storage.
    60  	// Implementations should never lose data after a Set, Delete,
    61  	// or CommmitBatch, though.
    62  	Close() error
    63  }
    64  
    65  // Wiper is an optional interface that may be implemented by storage
    66  // implementations.
    67  type Wiper interface {
    68  	KeyValue
    69  
    70  	// Wipe removes all key/value pairs.
    71  	Wipe() error
    72  }
    73  
    74  // Iterator iterates over an index KeyValue's key/value pairs in key order.
    75  //
    76  // An iterator must be closed after use, but it is not necessary to read an
    77  // iterator until exhaustion.
    78  //
    79  // An iterator is not necessarily goroutine-safe, but it is safe to use
    80  // multiple iterators concurrently, with each in a dedicated goroutine.
    81  type Iterator interface {
    82  	// Next moves the iterator to the next key/value pair.
    83  	// It returns false when the iterator is exhausted.
    84  	Next() bool
    85  
    86  	// Key returns the key of the current key/value pair.
    87  	// Only valid after a call to Next returns true.
    88  	Key() string
    89  
    90  	// KeyBytes returns the key as bytes. The returned bytes
    91  	// should not be written and are invalid after the next call
    92  	// to Next or Close.
    93  	// TODO(bradfitz): rename this and change it to return a
    94  	// mem.RO instead?
    95  	KeyBytes() []byte
    96  
    97  	// Value returns the value of the current key/value pair.
    98  	// Only valid after a call to Next returns true.
    99  	Value() string
   100  
   101  	// ValueBytes returns the value as bytes. The returned bytes
   102  	// should not be written and are invalid after the next call
   103  	// to Next or Close.
   104  	// TODO(bradfitz): rename this and change it to return a
   105  	// mem.RO instead?
   106  	ValueBytes() []byte
   107  
   108  	// Close closes the iterator and returns any accumulated error. Exhausting
   109  	// all the key/value pairs in a table is not considered to be an error.
   110  	// It is valid to call Close multiple times. Other methods should not be
   111  	// called after the iterator has been closed.
   112  	Close() error
   113  }
   114  
   115  type BatchMutation interface {
   116  	Set(key, value string)
   117  	Delete(key string)
   118  }
   119  
   120  type Mutation interface {
   121  	Key() string
   122  	Value() string
   123  	IsDelete() bool
   124  }
   125  
   126  type mutation struct {
   127  	key    string
   128  	value  string // used if !delete
   129  	delete bool   // if to be deleted
   130  }
   131  
   132  func (m mutation) Key() string {
   133  	return m.key
   134  }
   135  
   136  func (m mutation) Value() string {
   137  	return m.value
   138  }
   139  
   140  func (m mutation) IsDelete() bool {
   141  	return m.delete
   142  }
   143  
   144  func NewBatchMutation() BatchMutation {
   145  	return &batch{}
   146  }
   147  
   148  type batch struct {
   149  	m []Mutation
   150  }
   151  
   152  func (b *batch) Mutations() []Mutation {
   153  	return b.m
   154  }
   155  
   156  func (b *batch) Delete(key string) {
   157  	b.m = append(b.m, mutation{key: key, delete: true})
   158  }
   159  
   160  func (b *batch) Set(key, value string) {
   161  	b.m = append(b.m, mutation{key: key, value: value})
   162  }
   163  
   164  var (
   165  	ctors = make(map[string]func(jsonconfig.Obj) (KeyValue, error))
   166  )
   167  
   168  func RegisterKeyValue(typ string, fn func(jsonconfig.Obj) (KeyValue, error)) {
   169  	if typ == "" || fn == nil {
   170  		panic("zero type or func")
   171  	}
   172  	if _, dup := ctors[typ]; dup {
   173  		panic("duplication registration of type " + typ)
   174  	}
   175  	ctors[typ] = fn
   176  }
   177  
   178  func NewKeyValue(cfg jsonconfig.Obj) (KeyValue, error) {
   179  	var s KeyValue
   180  	var err error
   181  	typ := cfg.RequiredString("type")
   182  	ctor, ok := ctors[typ]
   183  	if typ != "" && !ok {
   184  		return nil, fmt.Errorf("Invalid sorted.KeyValue type %q", typ)
   185  	}
   186  	if ok {
   187  		s, err = ctor(cfg)
   188  		if err != nil {
   189  			return nil, fmt.Errorf("error from %q KeyValue: %v", typ, err)
   190  		}
   191  	}
   192  	return s, cfg.Validate()
   193  }