github.com/yasker/longhorn-engine@v0.0.0-20160621014712-6ed6cfca0729/replica/server.go (about) 1 package replica 2 3 import ( 4 "fmt" 5 "os" 6 "sync" 7 8 "github.com/Sirupsen/logrus" 9 ) 10 11 const ( 12 Initial = State("initial") 13 Open = State("open") 14 Closed = State("closed") 15 Dirty = State("dirty") 16 Rebuilding = State("rebuilding") 17 Error = State("error") 18 ) 19 20 type State string 21 22 type Server struct { 23 sync.RWMutex 24 r *Replica 25 dir string 26 defaultSectorSize int64 27 backing *BackingFile 28 } 29 30 func NewServer(dir string, backing *BackingFile, sectorSize int64) *Server { 31 return &Server{ 32 dir: dir, 33 backing: backing, 34 defaultSectorSize: sectorSize, 35 } 36 } 37 38 func (s *Server) getSectorSize() int64 { 39 if s.backing != nil && s.backing.SectorSize > 0 { 40 return s.backing.SectorSize 41 } 42 return s.defaultSectorSize 43 } 44 45 func (s *Server) getSize(size int64) int64 { 46 if s.backing != nil && s.backing.Size > 0 { 47 return s.backing.Size 48 } 49 return size 50 } 51 52 func (s *Server) Create(size int64) error { 53 s.Lock() 54 defer s.Unlock() 55 56 state, _ := s.Status() 57 if state != Initial { 58 return nil 59 } 60 61 size = s.getSize(size) 62 sectorSize := s.getSectorSize() 63 64 logrus.Infof("Creating volume %s, size %d/%d", s.dir, size, sectorSize) 65 r, err := New(size, sectorSize, s.dir, s.backing) 66 if err != nil { 67 return err 68 } 69 70 return r.Close() 71 } 72 73 func (s *Server) Open() error { 74 s.Lock() 75 defer s.Unlock() 76 77 if s.r != nil { 78 return fmt.Errorf("Replica is already open") 79 } 80 81 _, info := s.Status() 82 size := s.getSize(info.Size) 83 sectorSize := s.getSectorSize() 84 85 logrus.Infof("Opening volume %s, size %d/%d", s.dir, size, sectorSize) 86 r, err := New(size, sectorSize, s.dir, s.backing) 87 if err != nil { 88 return err 89 } 90 s.r = r 91 return nil 92 } 93 94 func (s *Server) Reload() error { 95 s.Lock() 96 defer s.Unlock() 97 98 if s.r == nil { 99 return nil 100 } 101 102 logrus.Infof("Reloading volume") 103 newReplica, err := s.r.Reload() 104 if err != nil { 105 return err 106 } 107 108 oldReplica := s.r 109 s.r = newReplica 110 oldReplica.Close() 111 return nil 112 } 113 114 func (s *Server) Status() (State, Info) { 115 if s.r == nil { 116 info, err := ReadInfo(s.dir) 117 if os.IsNotExist(err) { 118 return Initial, Info{} 119 } else if err != nil { 120 return Error, Info{} 121 } 122 return Closed, info 123 } 124 info := s.r.Info() 125 switch { 126 case info.Rebuilding: 127 return Rebuilding, info 128 case info.Dirty: 129 return Dirty, info 130 default: 131 return Open, info 132 } 133 } 134 135 func (s *Server) SetRebuilding(rebuilding bool) error { 136 state, _ := s.Status() 137 // Must be Open/Dirty to set true or must be Rebuilding to set false 138 if (rebuilding && state != Open && state != Dirty) || 139 (!rebuilding && state != Rebuilding) { 140 return fmt.Errorf("Can not set rebuilding=%v from state %s", rebuilding, state) 141 } 142 143 return s.r.SetRebuilding(rebuilding) 144 } 145 146 func (s *Server) Replica() *Replica { 147 return s.r 148 } 149 150 func (s *Server) Revert(name string) error { 151 s.Lock() 152 defer s.Unlock() 153 154 if s.r == nil { 155 return nil 156 } 157 158 logrus.Infof("Reverting to snapshot [%s] on volume", name) 159 r, err := s.r.Revert(name) 160 if err != nil { 161 return err 162 } 163 164 s.r = r 165 return nil 166 } 167 168 func (s *Server) Snapshot(name string) error { 169 s.Lock() 170 defer s.Unlock() 171 172 if s.r == nil { 173 return nil 174 } 175 176 logrus.Infof("Snapshotting [%s] volume", name) 177 return s.r.Snapshot(name) 178 } 179 180 func (s *Server) RemoveDiffDisk(name string, markOnly bool) error { 181 s.Lock() 182 defer s.Unlock() 183 184 if s.r == nil { 185 return nil 186 } 187 188 logrus.Infof("Removing disk: %s, markonly %v", name, markOnly) 189 return s.r.RemoveDiffDisk(name, markOnly) 190 } 191 192 func (s *Server) PrepareRemoveDisk(name string) ([]PrepareRemoveAction, error) { 193 s.Lock() 194 defer s.Unlock() 195 196 if s.r == nil { 197 return nil, nil 198 } 199 200 logrus.Infof("Prepare removing disk: %s", name) 201 return s.r.PrepareRemoveDisk(name) 202 } 203 204 func (s *Server) Delete() error { 205 s.Lock() 206 defer s.Unlock() 207 208 if s.r == nil { 209 return nil 210 } 211 212 logrus.Infof("Deleting volume") 213 if err := s.r.Close(); err != nil { 214 return err 215 } 216 217 err := s.r.Delete() 218 s.r = nil 219 return err 220 } 221 222 func (s *Server) Close() error { 223 s.Lock() 224 defer s.Unlock() 225 226 if s.r == nil { 227 return nil 228 } 229 230 logrus.Infof("Closing volume") 231 if err := s.r.Close(); err != nil { 232 return err 233 } 234 235 s.r = nil 236 return nil 237 } 238 239 func (s *Server) WriteAt(buf []byte, offset int64) (int, error) { 240 s.RLock() 241 i, err := s.r.WriteAt(buf, offset) 242 s.RUnlock() 243 return i, err 244 } 245 246 func (s *Server) ReadAt(buf []byte, offset int64) (int, error) { 247 s.RLock() 248 i, err := s.r.ReadAt(buf, offset) 249 s.RUnlock() 250 return i, err 251 }