예제 #1
0
파일: store.go 프로젝트: yonglehou/bfs
// saveVolumeIndex save volumes index info to disk.
func (s *Store) saveVolumeIndex() (err error) {
	var (
		tn, n int
		v     *volume.Volume
	)
	if _, err = s.vf.Seek(0, os.SEEK_SET); err != nil {
		log.Errorf("vf.Seek() error(%v)", err)
		return
	}
	for _, v = range s.Volumes {
		if n, err = s.vf.WriteString(fmt.Sprintf("%s\n", string(v.Meta()))); err != nil {
			log.Errorf("vf.WriteString() error(%v)", err)
			return
		}
		tn += n
	}
	if err = s.vf.Sync(); err != nil {
		log.Errorf("vf.Sync() error(%v)", err)
		return
	}
	if err = os.Truncate(s.conf.Store.VolumeIndex, int64(tn)); err != nil {
		log.Errorf("os.Truncate() error(%v)", err)
	}
	return
}
예제 #2
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
}
예제 #3
0
파일: store.go 프로젝트: yonglehou/bfs
// BulkVolume copy a super block from another store server add to this server.
func (s *Store) BulkVolume(id int32, bfile, ifile string) (err error) {
	var v, nv *volume.Volume
	// recovery new block
	if nv, err = newVolume(id, bfile, ifile, s.conf); err != nil {
		return
	}
	s.vlock.Lock()
	if v = s.Volumes[id]; v == nil {
		s.addVolume(id, nv)
		if err = s.saveVolumeIndex(); err == nil {
			err = s.zk.AddVolume(id, nv.Meta())
		}
		if err != nil {
			log.Errorf("bulk volume: %d error(%v), local index or zookeeper index may save failed", id, err)
		}
	} else {
		err = errors.ErrVolumeExist
	}
	s.vlock.Unlock()
	return
}
예제 #4
0
파일: store.go 프로젝트: yonglehou/bfs
// parseVolumeIndex parse index from local config and zookeeper.
func (s *Store) parseVolumeIndex() (err error) {
	var (
		i          int
		ok         bool
		id         int32
		bfile      string
		ifile      string
		v          *volume.Volume
		data       []byte
		lids, zids []int32
		lines      []string
		lbfs, lifs []string
		zbfs, zifs []string
		lim, zim   map[int32]struct{}
	)
	if data, err = ioutil.ReadAll(s.vf); err != nil {
		log.Errorf("ioutil.ReadAll() error(%v)", err)
		return
	}
	lines = strings.Split(string(data), "\n")
	if lim, lids, lbfs, lifs, err = s.parseIndex(lines); err != nil {
		return
	}
	if lines, err = s.zk.Volumes(); err != nil {
		return
	}
	if zim, zids, zbfs, zifs, err = s.parseIndex(lines); err != nil {
		return
	}
	// local index
	for i = 0; i < len(lbfs); i++ {
		id, bfile, ifile = lids[i], lbfs[i], lifs[i]
		if _, ok = s.Volumes[id]; ok {
			continue
		}
		if v, err = newVolume(id, bfile, ifile, s.conf); err != nil {
			return
		}
		s.Volumes[id] = v
		if _, ok = zim[id]; !ok {
			if err = s.zk.AddVolume(id, v.Meta()); err != nil {
				return
			}
		} else {
			if err = s.zk.SetVolume(id, v.Meta()); err != nil {
				return
			}
		}
	}
	// zk index
	for i = 0; i < len(zbfs); i++ {
		id, bfile, ifile = zids[i], zbfs[i], zifs[i]
		if _, ok = s.Volumes[id]; ok {
			continue
		}
		// if not exists in local
		if _, ok = lim[id]; !ok {
			if v, err = newVolume(id, bfile, ifile, s.conf); err != nil {
				return
			}
			s.Volumes[id] = v
		}
	}
	err = s.saveVolumeIndex()
	return
}