You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
5.3 KiB

9 years ago
6 years ago
6 years ago
9 years ago
9 years ago
9 years ago
  1. package storage
  2. import (
  3. "fmt"
  4. "os"
  5. "time"
  6. "github.com/syndtr/goleveldb/leveldb/opt"
  7. "github.com/chrislusf/seaweedfs/weed/glog"
  8. "github.com/chrislusf/seaweedfs/weed/stats"
  9. "github.com/chrislusf/seaweedfs/weed/storage/backend"
  10. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  11. )
  12. func loadVolumeWithoutIndex(dirname string, collection string, id needle.VolumeId, needleMapKind NeedleMapType) (v *Volume, err error) {
  13. v = &Volume{dir: dirname, Collection: collection, Id: id}
  14. v.SuperBlock = SuperBlock{}
  15. v.needleMapKind = needleMapKind
  16. err = v.load(false, false, needleMapKind, 0)
  17. return
  18. }
  19. func (v *Volume) load(alsoLoadIndex bool, createDatIfMissing bool, needleMapKind NeedleMapType, preallocate int64) (err error) {
  20. fileName := v.FileName()
  21. alreadyHasSuperBlock := false
  22. if v.maybeLoadVolumeTierInfo() {
  23. v.noWriteCanDelete = true
  24. // open remote file
  25. alreadyHasSuperBlock = true
  26. } else if exists, canRead, canWrite, modifiedTime, fileSize := checkFile(fileName + ".dat"); exists {
  27. // open dat file
  28. if !canRead {
  29. return fmt.Errorf("cannot read Volume Data file %s.dat", fileName)
  30. }
  31. var dataFile *os.File
  32. if canWrite {
  33. dataFile, err = os.OpenFile(fileName+".dat", os.O_RDWR|os.O_CREATE, 0644)
  34. } else {
  35. glog.V(0).Infoln("opening " + fileName + ".dat in READONLY mode")
  36. dataFile, err = os.Open(fileName + ".dat")
  37. v.noWriteOrDelete = true
  38. }
  39. v.lastModifiedTsSeconds = uint64(modifiedTime.Unix())
  40. if fileSize >= _SuperBlockSize {
  41. alreadyHasSuperBlock = true
  42. }
  43. v.DataBackend = backend.NewDiskFile(dataFile)
  44. } else {
  45. if createDatIfMissing {
  46. v.DataBackend, err = createVolumeFile(fileName+".dat", preallocate, v.MemoryMapMaxSizeMb)
  47. } else {
  48. return fmt.Errorf("Volume Data file %s.dat does not exist.", fileName)
  49. }
  50. }
  51. if err != nil {
  52. if !os.IsPermission(err) {
  53. return fmt.Errorf("cannot load Volume Data %s.dat: %v", fileName, err)
  54. } else {
  55. return fmt.Errorf("load data file %s.dat: %v", fileName, err)
  56. }
  57. }
  58. if alreadyHasSuperBlock {
  59. err = v.readSuperBlock()
  60. } else {
  61. if !v.SuperBlock.Initialized() {
  62. return fmt.Errorf("volume %s.dat not initialized", fileName)
  63. }
  64. err = v.maybeWriteSuperBlock()
  65. }
  66. if err == nil && alsoLoadIndex {
  67. var indexFile *os.File
  68. if v.noWriteOrDelete {
  69. glog.V(1).Infoln("open to read file", fileName+".idx")
  70. if indexFile, err = os.OpenFile(fileName+".idx", os.O_RDONLY, 0644); err != nil {
  71. return fmt.Errorf("cannot read Volume Index %s.idx: %v", fileName, err)
  72. }
  73. } else {
  74. glog.V(1).Infoln("open to write file", fileName+".idx")
  75. if indexFile, err = os.OpenFile(fileName+".idx", os.O_RDWR|os.O_CREATE, 0644); err != nil {
  76. return fmt.Errorf("cannot write Volume Index %s.idx: %v", fileName, err)
  77. }
  78. }
  79. if v.lastAppendAtNs, err = CheckVolumeDataIntegrity(v, indexFile); err != nil {
  80. v.noWriteOrDelete = true
  81. glog.V(0).Infof("volumeDataIntegrityChecking failed %v", err)
  82. }
  83. if v.noWriteOrDelete || v.noWriteCanDelete {
  84. if v.nm, err = NewSortedFileNeedleMap(fileName, indexFile); err != nil {
  85. glog.V(0).Infof("loading sorted db %s error: %v", fileName+".sdb", err)
  86. }
  87. } else {
  88. switch needleMapKind {
  89. case NeedleMapInMemory:
  90. glog.V(0).Infoln("loading index", fileName+".idx", "to memory")
  91. if v.nm, err = LoadCompactNeedleMap(indexFile); err != nil {
  92. glog.V(0).Infof("loading index %s to memory error: %v", fileName+".idx", err)
  93. }
  94. case NeedleMapLevelDb:
  95. glog.V(0).Infoln("loading leveldb", fileName+".ldb")
  96. opts := &opt.Options{
  97. BlockCacheCapacity: 2 * 1024 * 1024, // default value is 8MiB
  98. WriteBuffer: 1 * 1024 * 1024, // default value is 4MiB
  99. CompactionTableSizeMultiplier: 10, // default value is 1
  100. }
  101. if v.nm, err = NewLevelDbNeedleMap(fileName+".ldb", indexFile, opts); err != nil {
  102. glog.V(0).Infof("loading leveldb %s error: %v", fileName+".ldb", err)
  103. }
  104. case NeedleMapLevelDbMedium:
  105. glog.V(0).Infoln("loading leveldb medium", fileName+".ldb")
  106. opts := &opt.Options{
  107. BlockCacheCapacity: 4 * 1024 * 1024, // default value is 8MiB
  108. WriteBuffer: 2 * 1024 * 1024, // default value is 4MiB
  109. CompactionTableSizeMultiplier: 10, // default value is 1
  110. }
  111. if v.nm, err = NewLevelDbNeedleMap(fileName+".ldb", indexFile, opts); err != nil {
  112. glog.V(0).Infof("loading leveldb %s error: %v", fileName+".ldb", err)
  113. }
  114. case NeedleMapLevelDbLarge:
  115. glog.V(0).Infoln("loading leveldb large", fileName+".ldb")
  116. opts := &opt.Options{
  117. BlockCacheCapacity: 8 * 1024 * 1024, // default value is 8MiB
  118. WriteBuffer: 4 * 1024 * 1024, // default value is 4MiB
  119. CompactionTableSizeMultiplier: 10, // default value is 1
  120. }
  121. if v.nm, err = NewLevelDbNeedleMap(fileName+".ldb", indexFile, opts); err != nil {
  122. glog.V(0).Infof("loading leveldb %s error: %v", fileName+".ldb", err)
  123. }
  124. }
  125. }
  126. }
  127. stats.VolumeServerVolumeCounter.WithLabelValues(v.Collection, "volume").Inc()
  128. return err
  129. }
  130. func checkFile(filename string) (exists, canRead, canWrite bool, modTime time.Time, fileSize int64) {
  131. exists = true
  132. fi, err := os.Stat(filename)
  133. if os.IsNotExist(err) {
  134. exists = false
  135. return
  136. }
  137. if fi.Mode()&0400 != 0 {
  138. canRead = true
  139. }
  140. if fi.Mode()&0200 != 0 {
  141. canWrite = true
  142. }
  143. modTime = fi.ModTime()
  144. fileSize = fi.Size()
  145. return
  146. }