volume_loading.go 7.9 KB

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