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.

226 lines
8.0 KiB

6 years ago
4 years ago
4 years ago
4 years ago
5 years ago
4 years ago
  1. package storage
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/seaweedfs/seaweedfs/weed/storage/types"
  6. "github.com/syndtr/goleveldb/leveldb/opt"
  7. "github.com/seaweedfs/seaweedfs/weed/glog"
  8. "github.com/seaweedfs/seaweedfs/weed/stats"
  9. "github.com/seaweedfs/seaweedfs/weed/storage/backend"
  10. "github.com/seaweedfs/seaweedfs/weed/storage/needle"
  11. "github.com/seaweedfs/seaweedfs/weed/storage/super_block"
  12. "github.com/seaweedfs/seaweedfs/weed/util"
  13. )
  14. func loadVolumeWithoutIndex(dirname string, collection string, id needle.VolumeId, needleMapKind NeedleMapKind) (v *Volume, err error) {
  15. v = &Volume{dir: dirname, Collection: collection, Id: id}
  16. v.SuperBlock = super_block.SuperBlock{}
  17. v.needleMapKind = needleMapKind
  18. err = v.load(false, false, needleMapKind, 0)
  19. return
  20. }
  21. func (v *Volume) load(alsoLoadIndex bool, createDatIfMissing bool, needleMapKind NeedleMapKind, preallocate int64) (err error) {
  22. alreadyHasSuperBlock := false
  23. hasLoadedVolume := false
  24. defer func() {
  25. if !hasLoadedVolume {
  26. if v.nm != nil {
  27. v.nm.Close()
  28. v.nm = nil
  29. }
  30. if v.DataBackend != nil {
  31. v.DataBackend.Close()
  32. v.DataBackend = nil
  33. }
  34. }
  35. }()
  36. hasVolumeInfoFile := v.maybeLoadVolumeInfo()
  37. if v.volumeInfo.ReadOnly && !v.HasRemoteFile() {
  38. // this covers the case where the volume is marked as read-only and has no remote file
  39. v.noWriteOrDelete = true
  40. }
  41. if v.HasRemoteFile() {
  42. v.noWriteCanDelete = true
  43. v.noWriteOrDelete = false
  44. glog.V(0).Infof("loading volume %d from remote %v", v.Id, v.volumeInfo)
  45. if err := v.LoadRemoteFile(); err != nil {
  46. return fmt.Errorf("load remote file %v: %v", v.volumeInfo, err)
  47. }
  48. alreadyHasSuperBlock = true
  49. } else if exists, canRead, canWrite, modifiedTime, fileSize := util.CheckFile(v.FileName(".dat")); exists {
  50. // open dat file
  51. if !canRead {
  52. return fmt.Errorf("cannot read Volume Data file %s", v.FileName(".dat"))
  53. }
  54. var dataFile *os.File
  55. if canWrite {
  56. dataFile, err = os.OpenFile(v.FileName(".dat"), os.O_RDWR|os.O_CREATE, 0644)
  57. } else {
  58. glog.V(0).Infof("opening %s in READONLY mode", v.FileName(".dat"))
  59. dataFile, err = os.Open(v.FileName(".dat"))
  60. v.noWriteOrDelete = true
  61. }
  62. v.lastModifiedTsSeconds = uint64(modifiedTime.Unix())
  63. if fileSize >= super_block.SuperBlockSize {
  64. alreadyHasSuperBlock = true
  65. }
  66. v.DataBackend = backend.NewDiskFile(dataFile)
  67. } else {
  68. if createDatIfMissing {
  69. v.DataBackend, err = backend.CreateVolumeFile(v.FileName(".dat"), preallocate, v.MemoryMapMaxSizeMb)
  70. } else {
  71. return fmt.Errorf("volume data file %s does not exist", v.FileName(".dat"))
  72. }
  73. }
  74. if err != nil {
  75. if !os.IsPermission(err) {
  76. return fmt.Errorf("cannot load volume data %s: %v", v.FileName(".dat"), err)
  77. } else {
  78. return fmt.Errorf("load data file %s: %v", v.FileName(".dat"), err)
  79. }
  80. }
  81. if alreadyHasSuperBlock {
  82. err = v.readSuperBlock()
  83. if err == nil {
  84. v.volumeInfo.Version = uint32(v.SuperBlock.Version)
  85. }
  86. glog.V(0).Infof("readSuperBlock volume %d version %v", v.Id, v.SuperBlock.Version)
  87. if v.HasRemoteFile() {
  88. // maybe temporary network problem
  89. glog.Errorf("readSuperBlock remote volume %d: %v", v.Id, err)
  90. err = nil
  91. }
  92. } else {
  93. if !v.SuperBlock.Initialized() {
  94. return fmt.Errorf("volume %s not initialized", v.FileName(".dat"))
  95. }
  96. err = v.maybeWriteSuperBlock()
  97. }
  98. if err == nil && alsoLoadIndex {
  99. // adjust for existing volumes with .idx together with .dat files
  100. if v.dirIdx != v.dir {
  101. if util.FileExists(v.DataFileName() + ".idx") {
  102. v.dirIdx = v.dir
  103. }
  104. }
  105. // check volume idx files
  106. if err := v.checkIdxFile(); err != nil {
  107. glog.Fatalf("check volume idx file %s: %v", v.FileName(".idx"), err)
  108. }
  109. var indexFile *os.File
  110. if v.noWriteOrDelete {
  111. glog.V(0).Infoln("open to read file", v.FileName(".idx"))
  112. if indexFile, err = os.OpenFile(v.FileName(".idx"), os.O_RDONLY, 0644); err != nil {
  113. return fmt.Errorf("cannot read Volume Index %s: %v", v.FileName(".idx"), err)
  114. }
  115. } else {
  116. glog.V(1).Infoln("open to write file", v.FileName(".idx"))
  117. if indexFile, err = os.OpenFile(v.FileName(".idx"), os.O_RDWR|os.O_CREATE, 0644); err != nil {
  118. return fmt.Errorf("cannot write Volume Index %s: %v", v.FileName(".idx"), err)
  119. }
  120. }
  121. // Do not need to check the data integrity for remote volumes,
  122. // since the remote storage tier may have larger capacity, the volume
  123. // data read will trigger the ReadAt() function to read from the remote
  124. // storage tier, and download to local storage, which may cause the
  125. // capactiy overloading.
  126. if !v.HasRemoteFile() {
  127. glog.V(0).Infof("checking volume data integrity for volume %d", v.Id)
  128. if v.lastAppendAtNs, err = CheckVolumeDataIntegrity(v, indexFile); err != nil {
  129. v.noWriteOrDelete = true
  130. glog.V(0).Infof("volumeDataIntegrityChecking failed %v", err)
  131. }
  132. }
  133. if v.noWriteOrDelete || v.noWriteCanDelete {
  134. if v.nm, err = NewSortedFileNeedleMap(v.IndexFileName(), indexFile); err != nil {
  135. glog.V(0).Infof("loading sorted db %s error: %v", v.FileName(".sdx"), err)
  136. }
  137. } else {
  138. switch needleMapKind {
  139. case NeedleMapInMemory:
  140. if v.tmpNm != nil {
  141. glog.V(0).Infof("updating memory compact index %s ", v.FileName(".idx"))
  142. err = v.tmpNm.UpdateNeedleMap(v, indexFile, nil, 0)
  143. } else {
  144. glog.V(0).Infoln("loading memory index", v.FileName(".idx"), "to memory")
  145. if v.nm, err = LoadCompactNeedleMap(indexFile); err != nil {
  146. glog.V(0).Infof("loading index %s to memory error: %v", v.FileName(".idx"), err)
  147. }
  148. }
  149. case NeedleMapLevelDb:
  150. opts := &opt.Options{
  151. BlockCacheCapacity: 2 * 1024 * 1024, // default value is 8MiB
  152. WriteBuffer: 1 * 1024 * 1024, // default value is 4MiB
  153. CompactionTableSizeMultiplier: 10, // default value is 1
  154. }
  155. if v.tmpNm != nil {
  156. glog.V(0).Infoln("updating leveldb index", v.FileName(".ldb"))
  157. err = v.tmpNm.UpdateNeedleMap(v, indexFile, opts, v.ldbTimeout)
  158. } else {
  159. glog.V(0).Infoln("loading leveldb index", v.FileName(".ldb"))
  160. if v.nm, err = NewLevelDbNeedleMap(v.FileName(".ldb"), indexFile, opts, v.ldbTimeout); err != nil {
  161. glog.V(0).Infof("loading leveldb %s error: %v", v.FileName(".ldb"), err)
  162. }
  163. }
  164. case NeedleMapLevelDbMedium:
  165. opts := &opt.Options{
  166. BlockCacheCapacity: 4 * 1024 * 1024, // default value is 8MiB
  167. WriteBuffer: 2 * 1024 * 1024, // default value is 4MiB
  168. CompactionTableSizeMultiplier: 10, // default value is 1
  169. }
  170. if v.tmpNm != nil {
  171. glog.V(0).Infoln("updating leveldb medium index", v.FileName(".ldb"))
  172. err = v.tmpNm.UpdateNeedleMap(v, indexFile, opts, v.ldbTimeout)
  173. } else {
  174. glog.V(0).Infoln("loading leveldb medium index", v.FileName(".ldb"))
  175. if v.nm, err = NewLevelDbNeedleMap(v.FileName(".ldb"), indexFile, opts, v.ldbTimeout); err != nil {
  176. glog.V(0).Infof("loading leveldb %s error: %v", v.FileName(".ldb"), err)
  177. }
  178. }
  179. case NeedleMapLevelDbLarge:
  180. opts := &opt.Options{
  181. BlockCacheCapacity: 8 * 1024 * 1024, // default value is 8MiB
  182. WriteBuffer: 4 * 1024 * 1024, // default value is 4MiB
  183. CompactionTableSizeMultiplier: 10, // default value is 1
  184. }
  185. if v.tmpNm != nil {
  186. glog.V(0).Infoln("updating leveldb large index", v.FileName(".ldb"))
  187. err = v.tmpNm.UpdateNeedleMap(v, indexFile, opts, v.ldbTimeout)
  188. } else {
  189. glog.V(0).Infoln("loading leveldb large index", v.FileName(".ldb"))
  190. if v.nm, err = NewLevelDbNeedleMap(v.FileName(".ldb"), indexFile, opts, v.ldbTimeout); err != nil {
  191. glog.V(0).Infof("loading leveldb %s error: %v", v.FileName(".ldb"), err)
  192. }
  193. }
  194. }
  195. }
  196. }
  197. if !hasVolumeInfoFile {
  198. v.volumeInfo.Version = uint32(v.SuperBlock.Version)
  199. v.volumeInfo.BytesOffset = uint32(types.OffsetSize)
  200. if err := v.SaveVolumeInfo(); err != nil {
  201. glog.Warningf("volume %d failed to save file info: %v", v.Id, err)
  202. }
  203. }
  204. stats.VolumeServerVolumeGauge.WithLabelValues(v.Collection, "volume").Inc()
  205. if err == nil {
  206. hasLoadedVolume = true
  207. }
  208. return err
  209. }