github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/pkg/sorted/mem.go (about) 1 /* 2 Copyright 2011 Google Inc. 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 18 19 import ( 20 "bytes" 21 "errors" 22 "sync" 23 24 "camlistore.org/pkg/jsonconfig" 25 "camlistore.org/third_party/code.google.com/p/leveldb-go/leveldb/db" 26 "camlistore.org/third_party/code.google.com/p/leveldb-go/leveldb/memdb" 27 ) 28 29 // NewMemoryKeyValue returns a KeyValue implementation that's backed only 30 // by memory. It's mostly useful for tests and development. 31 func NewMemoryKeyValue() KeyValue { 32 db := memdb.New(nil) 33 return &memKeys{db: db} 34 } 35 36 // memKeys is a naive in-memory implementation of KeyValue for test & development 37 // purposes only. 38 type memKeys struct { 39 mu sync.Mutex // guards db 40 db db.DB 41 } 42 43 // memIter converts from leveldb's db.Iterator interface, which 44 // operates on []byte, to Camlistore's index.Iterator, which operates 45 // on string. 46 type memIter struct { 47 lit db.Iterator // underlying leveldb iterator 48 k, v *string // if nil, not stringified yet 49 end []byte // if len(end) > 0, the upper bound 50 } 51 52 func (t *memIter) Next() bool { 53 t.k, t.v = nil, nil 54 if !t.lit.Next() { 55 return false 56 } 57 if len(t.end) > 0 && bytes.Compare(t.KeyBytes(), t.end) >= 0 { 58 return false 59 } 60 return true 61 } 62 63 func (s *memIter) Close() error { 64 err := s.lit.Close() 65 *s = memIter{} // to cause crashes on future access 66 return err 67 } 68 69 func (s *memIter) KeyBytes() []byte { 70 return s.lit.Key() 71 } 72 73 func (s *memIter) ValueBytes() []byte { 74 return s.lit.Value() 75 } 76 77 func (s *memIter) Key() string { 78 if s.k != nil { 79 return *s.k 80 } 81 str := string(s.KeyBytes()) 82 s.k = &str 83 return str 84 } 85 86 func (s *memIter) Value() string { 87 if s.v != nil { 88 return *s.v 89 } 90 str := string(s.ValueBytes()) 91 s.v = &str 92 return str 93 } 94 95 func (mk *memKeys) Get(key string) (string, error) { 96 mk.mu.Lock() 97 defer mk.mu.Unlock() 98 k, err := mk.db.Get([]byte(key), nil) 99 if err == db.ErrNotFound { 100 return "", ErrNotFound 101 } 102 return string(k), err 103 } 104 105 func (mk *memKeys) Find(start, end string) Iterator { 106 mk.mu.Lock() 107 defer mk.mu.Unlock() 108 lit := mk.db.Find([]byte(start), nil) 109 it := &memIter{lit: lit} 110 if end != "" { 111 it.end = []byte(end) 112 } 113 return it 114 } 115 116 func (mk *memKeys) Set(key, value string) error { 117 mk.mu.Lock() 118 defer mk.mu.Unlock() 119 return mk.db.Set([]byte(key), []byte(value), nil) 120 } 121 122 func (mk *memKeys) Delete(key string) error { 123 mk.mu.Lock() 124 defer mk.mu.Unlock() 125 err := mk.db.Delete([]byte(key), nil) 126 if err == db.ErrNotFound { 127 return nil 128 } 129 return err 130 } 131 132 func (mk *memKeys) BeginBatch() BatchMutation { 133 return &batch{} 134 } 135 136 func (mk *memKeys) CommitBatch(bm BatchMutation) error { 137 b, ok := bm.(*batch) 138 if !ok { 139 return errors.New("invalid batch type; not an instance returned by BeginBatch") 140 } 141 mk.mu.Lock() 142 defer mk.mu.Unlock() 143 for _, m := range b.Mutations() { 144 if m.IsDelete() { 145 if err := mk.db.Delete([]byte(m.Key()), nil); err != nil { 146 return err 147 } 148 } else { 149 if err := mk.db.Set([]byte(m.Key()), []byte(m.Value()), nil); err != nil { 150 return err 151 } 152 } 153 } 154 return nil 155 } 156 157 func (mk *memKeys) Close() error { return nil } 158 159 func init() { 160 RegisterKeyValue("memory", func(cfg jsonconfig.Obj) (KeyValue, error) { 161 if err := cfg.Validate(); err != nil { 162 return nil, err 163 } 164 return NewMemoryKeyValue(), nil 165 }) 166 }