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  }