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 }