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 }