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.

155 lines
5.6 KiB

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