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.

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