mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-12-24 17:47:57 +08:00
5ce6bbf076
glide has its own requirements. My previous workaround caused me some code checkin errors. Need to fix this.
82 lines
2.2 KiB
Go
82 lines
2.2 KiB
Go
package storage
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/glog"
|
|
"github.com/chrislusf/seaweedfs/weed/util"
|
|
)
|
|
|
|
const (
|
|
SuperBlockSize = 8
|
|
)
|
|
|
|
/*
|
|
* Super block currently has 8 bytes allocated for each volume.
|
|
* Byte 0: version, 1 or 2
|
|
* Byte 1: Replica Placement strategy, 000, 001, 002, 010, etc
|
|
* Byte 2 and byte 3: Time to live. See TTL for definition
|
|
* Byte 4 and byte 5: The number of times the volume has been compacted.
|
|
* Rest bytes: Reserved
|
|
*/
|
|
type SuperBlock struct {
|
|
version Version
|
|
ReplicaPlacement *ReplicaPlacement
|
|
Ttl *TTL
|
|
CompactRevision uint16
|
|
}
|
|
|
|
func (s *SuperBlock) Version() Version {
|
|
return s.version
|
|
}
|
|
func (s *SuperBlock) Bytes() []byte {
|
|
header := make([]byte, SuperBlockSize)
|
|
header[0] = byte(s.version)
|
|
header[1] = s.ReplicaPlacement.Byte()
|
|
s.Ttl.ToBytes(header[2:4])
|
|
util.Uint16toBytes(header[4:6], s.CompactRevision)
|
|
return header
|
|
}
|
|
|
|
func (v *Volume) maybeWriteSuperBlock() error {
|
|
stat, e := v.dataFile.Stat()
|
|
if e != nil {
|
|
glog.V(0).Infof("failed to stat datafile %s: %v", v.dataFile, e)
|
|
return e
|
|
}
|
|
if stat.Size() == 0 {
|
|
v.SuperBlock.version = CurrentVersion
|
|
_, e = v.dataFile.Write(v.SuperBlock.Bytes())
|
|
if e != nil && os.IsPermission(e) {
|
|
//read-only, but zero length - recreate it!
|
|
if v.dataFile, e = os.Create(v.dataFile.Name()); e == nil {
|
|
if _, e = v.dataFile.Write(v.SuperBlock.Bytes()); e == nil {
|
|
v.readOnly = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return e
|
|
}
|
|
func (v *Volume) readSuperBlock() (err error) {
|
|
if _, err = v.dataFile.Seek(0, 0); err != nil {
|
|
return fmt.Errorf("cannot seek to the beginning of %s: %v", v.dataFile.Name(), err)
|
|
}
|
|
header := make([]byte, SuperBlockSize)
|
|
if _, e := v.dataFile.Read(header); e != nil {
|
|
return fmt.Errorf("cannot read volume %d super block: %v", v.Id, e)
|
|
}
|
|
v.SuperBlock, err = ParseSuperBlock(header)
|
|
return err
|
|
}
|
|
func ParseSuperBlock(header []byte) (superBlock SuperBlock, err error) {
|
|
superBlock.version = Version(header[0])
|
|
if superBlock.ReplicaPlacement, err = NewReplicaPlacementFromByte(header[1]); err != nil {
|
|
err = fmt.Errorf("cannot read replica type: %s", err.Error())
|
|
}
|
|
superBlock.Ttl = LoadTTLFromBytes(header[2:4])
|
|
superBlock.CompactRevision = util.BytesToUint16(header[4:6])
|
|
return
|
|
}
|