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  }