github.com/m3db/m3@v1.5.0/src/cluster/placement/storage/storage.go (about)

     1  // Copyright (c) 2016 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 storage
    22  
    23  import (
    24  	"github.com/m3db/m3/src/cluster/kv"
    25  	"github.com/m3db/m3/src/cluster/placement"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  	"go.uber.org/zap"
    29  )
    30  
    31  const errorVersionValue = 0
    32  
    33  type storage struct {
    34  	helper helper
    35  	key    string
    36  	store  kv.Store
    37  	opts   placement.Options
    38  	logger *zap.Logger
    39  }
    40  
    41  // NewPlacementStorage creates a placement.Storage.
    42  func NewPlacementStorage(store kv.Store, key string, opts placement.Options) placement.Storage {
    43  	if opts == nil {
    44  		opts = placement.NewOptions()
    45  	}
    46  	return &storage{
    47  		key:    key,
    48  		store:  store,
    49  		helper: newHelper(store, key, opts),
    50  		opts:   opts,
    51  		logger: opts.InstrumentOptions().Logger(),
    52  	}
    53  }
    54  
    55  func (s *storage) CheckAndSetProto(p proto.Message, version int) (int, error) {
    56  	if err := s.helper.ValidateProto(p); err != nil {
    57  		return errorVersionValue, err
    58  	}
    59  
    60  	if s.opts.Dryrun() {
    61  		s.logger.Info("this is a dryrun, the operation is not persisted")
    62  		return version + 1, nil
    63  	}
    64  
    65  	return s.store.CheckAndSet(s.key, version, p)
    66  }
    67  
    68  func (s *storage) SetProto(p proto.Message) (int, error) {
    69  	if err := s.helper.ValidateProto(p); err != nil {
    70  		return errorVersionValue, err
    71  	}
    72  
    73  	if s.opts.Dryrun() {
    74  		s.logger.Info("this is a dryrun, the operation is not persisted")
    75  		return errorVersionValue, nil
    76  	}
    77  	return s.store.Set(s.key, p)
    78  }
    79  
    80  func (s *storage) Proto() (proto.Message, int, error) {
    81  	return s.helper.PlacementProto()
    82  }
    83  
    84  func (s *storage) Set(p placement.Placement) (placement.Placement, error) {
    85  	if err := placement.Validate(p); err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	placementProto, err := s.helper.GenerateProto(p)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	if s.opts.Dryrun() {
    95  		s.logger.Info("this is a dryrun, the operation is not persisted")
    96  		return p, nil
    97  	}
    98  
    99  	v, err := s.store.Set(s.key, placementProto)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	return p.Clone().SetVersion(v), nil
   105  }
   106  
   107  func (s *storage) CheckAndSet(p placement.Placement, version int) (placement.Placement, error) {
   108  	if err := placement.Validate(p); err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	placementProto, err := s.helper.GenerateProto(p)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	if s.opts.Dryrun() {
   118  		s.logger.Info("this is a dryrun, the operation is not persisted")
   119  		return p, nil
   120  	}
   121  
   122  	v, err := s.store.CheckAndSet(
   123  		s.key,
   124  		version,
   125  		placementProto,
   126  	)
   127  
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  
   132  	return p.Clone().SetVersion(v), nil
   133  }
   134  
   135  func (s *storage) SetIfNotExist(p placement.Placement) (placement.Placement, error) {
   136  	if err := placement.Validate(p); err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	placementProto, err := s.helper.GenerateProto(p)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	if s.opts.Dryrun() {
   146  		s.logger.Info("this is a dryrun, the operation is not persisted")
   147  		return p, nil
   148  	}
   149  
   150  	v, err := s.store.SetIfNotExists(
   151  		s.key,
   152  		placementProto,
   153  	)
   154  
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  
   159  	return p.Clone().SetVersion(v), nil
   160  }
   161  
   162  func (s *storage) Delete() error {
   163  	if s.opts.Dryrun() {
   164  		s.logger.Info("this is a dryrun, the operation is not persisted")
   165  		return nil
   166  	}
   167  
   168  	_, err := s.store.Delete(s.key)
   169  	return err
   170  }
   171  
   172  func (s *storage) Placement() (placement.Placement, error) {
   173  	p, _, err := s.helper.Placement()
   174  	return p, err
   175  }
   176  
   177  func (s *storage) Watch() (placement.Watch, error) {
   178  	w, err := s.store.Watch(s.key)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	return newPlacementWatch(w, s.opts), nil
   183  }
   184  
   185  func (s *storage) PlacementForVersion(version int) (placement.Placement, error) {
   186  	return s.helper.PlacementForVersion(version)
   187  }