github.com/m3db/m3@v1.5.0/src/cluster/kv/fake/store.go (about)

     1  // Copyright (c) 2020  Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package fake
    22  
    23  import (
    24  	"errors"
    25  
    26  	"github.com/m3db/m3/src/cluster/kv"
    27  
    28  	"github.com/golang/protobuf/proto"
    29  )
    30  
    31  // NewStore returns a fakeStore adhering to the kv.Store interface.
    32  // All methods except Watch are implemented. Implementation is not threadsafe
    33  // and should only be used for tests.
    34  func NewStore() kv.Store {
    35  	return &fakeStore{
    36  		store: make(map[string][]kv.Value),
    37  	}
    38  }
    39  
    40  type fakeStore struct {
    41  	store map[string][]kv.Value
    42  }
    43  
    44  func (f *fakeStore) Get(key string) (kv.Value, error) {
    45  	value, ok := f.store[key]
    46  	if !ok {
    47  		return nil, kv.ErrNotFound
    48  	}
    49  
    50  	return value[len(value)-1], nil
    51  }
    52  
    53  func (f *fakeStore) Watch(_ string) (kv.ValueWatch, error) {
    54  	panic("implement me")
    55  }
    56  
    57  func (f *fakeStore) Set(key string, v proto.Message) (int, error) {
    58  	oldVal, err := f.Get(key)
    59  	if err != nil && err != kv.ErrNotFound {
    60  		return 0, err
    61  	}
    62  
    63  	data, err := proto.Marshal(v)
    64  	if err != nil {
    65  		return 0, err
    66  	}
    67  
    68  	var newVer int
    69  	if oldVal == nil {
    70  		f.store[key] = []kv.Value{newValue(data, int64(newVer))}
    71  	} else {
    72  		newVer = oldVal.Version() + 1
    73  		f.store[key] = append(f.store[key], newValue(data, int64(newVer)))
    74  	}
    75  
    76  	return newVer, nil
    77  }
    78  
    79  func (f *fakeStore) SetIfNotExists(key string, v proto.Message) (int, error) {
    80  	_, err := f.Get(key)
    81  	if err == kv.ErrNotFound {
    82  		return f.Set(key, v)
    83  	} else {
    84  		return 0, kv.ErrAlreadyExists
    85  	}
    86  }
    87  
    88  func (f *fakeStore) CheckAndSet(key string, version int, v proto.Message) (int, error) {
    89  	val, err := f.Get(key)
    90  	if err != nil && err != kv.ErrNotFound {
    91  		return 0, err
    92  	} else if err != nil && err == kv.ErrNotFound && version == 0 {
    93  		return f.Set(key, v)
    94  	} else if val == nil {
    95  		return 0, kv.ErrVersionMismatch
    96  	} else if val.Version() == version {
    97  		return f.Set(key, v)
    98  	} else {
    99  		return 0, kv.ErrVersionMismatch
   100  	}
   101  }
   102  
   103  func (f *fakeStore) Delete(key string) (kv.Value, error) {
   104  	val, err := f.Get(key)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	delete(f.store, key)
   109  
   110  	return val, nil
   111  }
   112  
   113  func (f *fakeStore) History(key string, from, to int) ([]kv.Value, error) {
   114  	if from > to || from < 0 || to < 0 {
   115  		return nil, errors.New("invalid history range")
   116  	}
   117  
   118  	if from == to {
   119  		return nil, nil
   120  	}
   121  
   122  	vals, ok := f.store[key]
   123  	if !ok {
   124  		return nil, kv.ErrNotFound
   125  	}
   126  	if to > len(vals) {
   127  		return nil, errors.New("invalid history range")
   128  	}
   129  
   130  	return vals[from:to], nil
   131  }
   132  
   133  type value struct {
   134  	Val []byte
   135  	Ver int64
   136  }
   137  
   138  func newValue(val []byte, ver int64) *value {
   139  	return &value{
   140  		Val: val,
   141  		Ver: ver,
   142  	}
   143  }
   144  
   145  func (c *value) IsNewer(other kv.Value) bool {
   146  	return c.Version() > other.Version()
   147  }
   148  
   149  func (c *value) Unmarshal(v proto.Message) error {
   150  	err := proto.Unmarshal(c.Val, v)
   151  	return err
   152  }
   153  
   154  func (c *value) Version() int {
   155  	return int(c.Ver)
   156  }