2016-07-03 14:56:49 +08:00
|
|
|
package storage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2016-07-03 14:58:23 +08:00
|
|
|
"time"
|
2016-07-03 14:56:49 +08:00
|
|
|
|
2019-09-12 21:18:21 +08:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/stats"
|
|
|
|
"github.com/chrislusf/seaweedfs/weed/storage/needle"
|
2019-04-19 12:43:36 +08:00
|
|
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
|
|
|
|
2019-09-12 21:18:21 +08:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/glog"
|
2016-07-03 14:56:49 +08:00
|
|
|
)
|
|
|
|
|
2019-04-19 12:43:36 +08:00
|
|
|
func loadVolumeWithoutIndex(dirname string, collection string, id needle.VolumeId, needleMapKind NeedleMapType) (v *Volume, e error) {
|
2016-07-03 14:56:49 +08:00
|
|
|
v = &Volume{dir: dirname, Collection: collection, Id: id}
|
|
|
|
v.SuperBlock = SuperBlock{}
|
|
|
|
v.needleMapKind = needleMapKind
|
2019-09-04 00:00:59 +08:00
|
|
|
e = v.load(false, false, needleMapKind, 0)
|
2016-07-03 14:56:49 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-09-04 00:00:59 +08:00
|
|
|
func (v *Volume) load(alsoLoadIndex bool, createDatIfMissing bool, needleMapKind NeedleMapType, preallocate int64) error {
|
2016-07-03 14:56:49 +08:00
|
|
|
var e error
|
|
|
|
fileName := v.FileName()
|
2018-09-09 17:48:58 +08:00
|
|
|
alreadyHasSuperBlock := false
|
2016-07-03 14:56:49 +08:00
|
|
|
|
2018-09-09 17:48:58 +08:00
|
|
|
if exists, canRead, canWrite, modifiedTime, fileSize := checkFile(fileName + ".dat"); exists {
|
2016-07-03 14:56:49 +08:00
|
|
|
if !canRead {
|
|
|
|
return fmt.Errorf("cannot read Volume Data file %s.dat", fileName)
|
|
|
|
}
|
|
|
|
if canWrite {
|
|
|
|
v.dataFile, e = os.OpenFile(fileName+".dat", os.O_RDWR|os.O_CREATE, 0644)
|
|
|
|
} else {
|
|
|
|
glog.V(0).Infoln("opening " + fileName + ".dat in READONLY mode")
|
|
|
|
v.dataFile, e = os.Open(fileName + ".dat")
|
|
|
|
v.readOnly = true
|
|
|
|
}
|
2019-08-21 11:26:01 +08:00
|
|
|
v.lastModifiedTsSeconds = uint64(modifiedTime.Unix())
|
2018-09-09 17:48:58 +08:00
|
|
|
if fileSize >= _SuperBlockSize {
|
|
|
|
alreadyHasSuperBlock = true
|
|
|
|
}
|
2016-07-03 14:56:49 +08:00
|
|
|
} else {
|
|
|
|
if createDatIfMissing {
|
2019-10-22 13:57:01 +08:00
|
|
|
v.dataFile, e = createVolumeFile(fileName+".dat", preallocate, v.MemoryMapMaxSizeMb)
|
2016-07-03 14:56:49 +08:00
|
|
|
} else {
|
|
|
|
return fmt.Errorf("Volume Data file %s.dat does not exist.", fileName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if e != nil {
|
|
|
|
if !os.IsPermission(e) {
|
|
|
|
return fmt.Errorf("cannot load Volume Data %s.dat: %v", fileName, e)
|
2018-07-10 14:31:25 +08:00
|
|
|
} else {
|
|
|
|
return fmt.Errorf("load data file %s.dat: %v", fileName, e)
|
2016-07-03 14:56:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-09 17:48:58 +08:00
|
|
|
if alreadyHasSuperBlock {
|
2016-07-03 14:56:49 +08:00
|
|
|
e = v.readSuperBlock()
|
|
|
|
} else {
|
2019-10-09 15:02:50 +08:00
|
|
|
if !v.SuperBlock.Initialized() {
|
|
|
|
return fmt.Errorf("volume %s.dat not initialized", fileName)
|
|
|
|
}
|
2016-07-03 14:56:49 +08:00
|
|
|
e = v.maybeWriteSuperBlock()
|
|
|
|
}
|
|
|
|
if e == nil && alsoLoadIndex {
|
|
|
|
var indexFile *os.File
|
|
|
|
if v.readOnly {
|
|
|
|
glog.V(1).Infoln("open to read file", fileName+".idx")
|
|
|
|
if indexFile, e = os.OpenFile(fileName+".idx", os.O_RDONLY, 0644); e != nil {
|
|
|
|
return fmt.Errorf("cannot read Volume Index %s.idx: %v", fileName, e)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
glog.V(1).Infoln("open to write file", fileName+".idx")
|
|
|
|
if indexFile, e = os.OpenFile(fileName+".idx", os.O_RDWR|os.O_CREATE, 0644); e != nil {
|
|
|
|
return fmt.Errorf("cannot write Volume Index %s.idx: %v", fileName, e)
|
|
|
|
}
|
|
|
|
}
|
2019-04-19 16:56:38 +08:00
|
|
|
if v.lastAppendAtNs, e = CheckVolumeDataIntegrity(v, indexFile); e != nil {
|
2016-07-03 14:56:49 +08:00
|
|
|
v.readOnly = true
|
|
|
|
glog.V(0).Infof("volumeDataIntegrityChecking failed %v", e)
|
|
|
|
}
|
|
|
|
switch needleMapKind {
|
|
|
|
case NeedleMapInMemory:
|
2017-05-27 13:51:25 +08:00
|
|
|
glog.V(0).Infoln("loading index", fileName+".idx", "to memory readonly", v.readOnly)
|
|
|
|
if v.nm, e = LoadCompactNeedleMap(indexFile); e != nil {
|
|
|
|
glog.V(0).Infof("loading index %s to memory error: %v", fileName+".idx", e)
|
2016-07-03 14:56:49 +08:00
|
|
|
}
|
|
|
|
case NeedleMapLevelDb:
|
2017-05-27 13:51:25 +08:00
|
|
|
glog.V(0).Infoln("loading leveldb", fileName+".ldb")
|
2019-04-10 00:42:06 +08:00
|
|
|
opts := &opt.Options{
|
2019-05-18 08:34:03 +08:00
|
|
|
BlockCacheCapacity: 2 * 1024 * 1024, // default value is 8MiB
|
|
|
|
WriteBuffer: 1 * 1024 * 1024, // default value is 4MiB
|
|
|
|
CompactionTableSizeMultiplier: 10, // default value is 1
|
2019-04-10 00:42:06 +08:00
|
|
|
}
|
|
|
|
if v.nm, e = NewLevelDbNeedleMap(fileName+".ldb", indexFile, opts); e != nil {
|
2016-07-03 14:56:49 +08:00
|
|
|
glog.V(0).Infof("loading leveldb %s error: %v", fileName+".ldb", e)
|
|
|
|
}
|
2019-04-10 00:42:06 +08:00
|
|
|
case NeedleMapLevelDbMedium:
|
|
|
|
glog.V(0).Infoln("loading leveldb medium", fileName+".ldb")
|
|
|
|
opts := &opt.Options{
|
2019-05-18 08:34:03 +08:00
|
|
|
BlockCacheCapacity: 4 * 1024 * 1024, // default value is 8MiB
|
|
|
|
WriteBuffer: 2 * 1024 * 1024, // default value is 4MiB
|
|
|
|
CompactionTableSizeMultiplier: 10, // default value is 1
|
2019-04-10 00:42:06 +08:00
|
|
|
}
|
|
|
|
if v.nm, e = NewLevelDbNeedleMap(fileName+".ldb", indexFile, opts); e != nil {
|
|
|
|
glog.V(0).Infof("loading leveldb %s error: %v", fileName+".ldb", e)
|
2016-07-03 14:56:49 +08:00
|
|
|
}
|
2019-04-10 00:42:06 +08:00
|
|
|
case NeedleMapLevelDbLarge:
|
|
|
|
glog.V(0).Infoln("loading leveldb large", fileName+".ldb")
|
|
|
|
opts := &opt.Options{
|
2019-05-18 08:34:03 +08:00
|
|
|
BlockCacheCapacity: 8 * 1024 * 1024, // default value is 8MiB
|
|
|
|
WriteBuffer: 4 * 1024 * 1024, // default value is 4MiB
|
|
|
|
CompactionTableSizeMultiplier: 10, // default value is 1
|
2019-04-10 00:42:06 +08:00
|
|
|
}
|
|
|
|
if v.nm, e = NewLevelDbNeedleMap(fileName+".ldb", indexFile, opts); e != nil {
|
|
|
|
glog.V(0).Infof("loading leveldb %s error: %v", fileName+".ldb", e)
|
2017-05-27 13:51:25 +08:00
|
|
|
}
|
2016-07-03 14:56:49 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-07 02:22:20 +08:00
|
|
|
|
2019-06-18 12:02:50 +08:00
|
|
|
stats.VolumeServerVolumeCounter.WithLabelValues(v.Collection, "volume").Inc()
|
2019-06-16 17:24:15 +08:00
|
|
|
|
2016-07-03 14:56:49 +08:00
|
|
|
return e
|
|
|
|
}
|
2016-07-03 14:58:23 +08:00
|
|
|
|
2018-09-09 17:48:58 +08:00
|
|
|
func checkFile(filename string) (exists, canRead, canWrite bool, modTime time.Time, fileSize int64) {
|
2016-07-03 14:58:23 +08:00
|
|
|
exists = true
|
|
|
|
fi, err := os.Stat(filename)
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
exists = false
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if fi.Mode()&0400 != 0 {
|
|
|
|
canRead = true
|
|
|
|
}
|
|
|
|
if fi.Mode()&0200 != 0 {
|
|
|
|
canWrite = true
|
|
|
|
}
|
|
|
|
modTime = fi.ModTime()
|
2018-09-09 17:48:58 +08:00
|
|
|
fileSize = fi.Size()
|
2016-07-03 14:58:23 +08:00
|
|
|
return
|
|
|
|
}
|