コード例 #1
0
ファイル: store.go プロジェクト: Terry-Mao/bfs
// CompactVolume compact a super block to another file.
func (s *Store) CompactVolume(id int32) (err error) {
	var (
		v, nv      *volume.Volume
		bdir, idir string
	)
	// try check volume
	if v = s.Volumes[id]; v != nil {
		if v.Compact {
			return errors.ErrVolumeInCompact
		}
	} else {
		return errors.ErrVolumeExist
	}
	// find a free volume
	if nv, err = s.freeVolume(id); err != nil {
		return
	}
	log.Infof("start compact volume: (%d) %s to %s", id, v.Block.File, nv.Block.File)
	// no lock here, Compact is no side-effect
	if err = v.StartCompact(nv); err != nil {
		nv.Destroy()
		v.StopCompact(nil)
		return
	}
	s.vlock.Lock()
	if v = s.Volumes[id]; v != nil {
		log.Infof("stop compact volume: (%d) %s to %s", id, v.Block.File, nv.Block.File)
		if err = v.StopCompact(nv); err == nil {
			// WARN no need update volumes map, use same object, only update
			// zookeeper the local index cause the block and index file changed.
			if err = s.saveVolumeIndex(); err == nil {
				err = s.zk.SetVolume(id, v.Meta())
			}
			if err != nil {
				log.Errorf("compact volume: %d error(%v), local index or zookeeper index may save failed", id, err)
			}
		}
	} else {
		// never happen
		err = errors.ErrVolumeExist
		log.Errorf("compact volume: %d not exist(may bug)", id)
	}
	s.vlock.Unlock()
	// WARN if failed, nv is free volume, if succeed nv replace with v.
	// Sleep untill anyone had old volume variables all processed.
	time.Sleep(_compactSleep)
	nv.Destroy()
	if err == nil {
		bdir, idir = filepath.Dir(nv.Block.File), filepath.Dir(nv.Indexer.File)
		_, err = s.AddFreeVolume(1, bdir, idir)
	}
	return
}