Browse Source
weed volume: remove boltdb, btree options, add options for leveldb medium, large
pull/925/head
weed volume: remove boltdb, btree options, add options for leveldb medium, large
pull/925/head
Chris Lu
6 years ago
6 changed files with 34 additions and 205 deletions
-
2weed/command/server.go
-
8weed/command/volume.go
-
6weed/storage/needle_map.go
-
185weed/storage/needle_map_boltdb.go
-
7weed/storage/needle_map_leveldb.go
-
31weed/storage/volume_loading.go
@ -1,185 +0,0 @@ |
|||
package storage |
|||
|
|||
import ( |
|||
"fmt" |
|||
"os" |
|||
|
|||
"github.com/boltdb/bolt" |
|||
|
|||
"errors" |
|||
"github.com/chrislusf/seaweedfs/weed/glog" |
|||
"github.com/chrislusf/seaweedfs/weed/storage/needle" |
|||
. "github.com/chrislusf/seaweedfs/weed/storage/types" |
|||
"github.com/chrislusf/seaweedfs/weed/util" |
|||
) |
|||
|
|||
type BoltDbNeedleMap struct { |
|||
dbFileName string |
|||
db *bolt.DB |
|||
baseNeedleMapper |
|||
} |
|||
|
|||
var boltdbBucket = []byte("weed") |
|||
|
|||
var NotFound = errors.New("not found") |
|||
|
|||
func NewBoltDbNeedleMap(dbFileName string, indexFile *os.File) (m *BoltDbNeedleMap, err error) { |
|||
m = &BoltDbNeedleMap{dbFileName: dbFileName} |
|||
m.indexFile = indexFile |
|||
if !isBoltDbFresh(dbFileName, indexFile) { |
|||
glog.V(0).Infof("Start to Generate %s from %s", dbFileName, indexFile.Name()) |
|||
generateBoltDbFile(dbFileName, indexFile) |
|||
glog.V(0).Infof("Finished Generating %s from %s", dbFileName, indexFile.Name()) |
|||
} |
|||
glog.V(1).Infof("Opening %s...", dbFileName) |
|||
if m.db, err = bolt.Open(dbFileName, 0644, nil); err != nil { |
|||
return |
|||
} |
|||
glog.V(1).Infof("Loading %s...", indexFile.Name()) |
|||
mm, indexLoadError := newNeedleMapMetricFromIndexFile(indexFile) |
|||
if indexLoadError != nil { |
|||
return nil, indexLoadError |
|||
} |
|||
m.mapMetric = *mm |
|||
return |
|||
} |
|||
|
|||
func isBoltDbFresh(dbFileName string, indexFile *os.File) bool { |
|||
// normally we always write to index file first
|
|||
dbLogFile, err := os.Open(dbFileName) |
|||
if err != nil { |
|||
return false |
|||
} |
|||
defer dbLogFile.Close() |
|||
dbStat, dbStatErr := dbLogFile.Stat() |
|||
indexStat, indexStatErr := indexFile.Stat() |
|||
if dbStatErr != nil || indexStatErr != nil { |
|||
glog.V(0).Infof("Can not stat file: %v and %v", dbStatErr, indexStatErr) |
|||
return false |
|||
} |
|||
|
|||
return dbStat.ModTime().After(indexStat.ModTime()) |
|||
} |
|||
|
|||
func generateBoltDbFile(dbFileName string, indexFile *os.File) error { |
|||
db, err := bolt.Open(dbFileName, 0644, nil) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer db.Close() |
|||
return WalkIndexFile(indexFile, func(key NeedleId, offset Offset, size uint32) error { |
|||
if !offset.IsZero() && size != TombstoneFileSize { |
|||
boltDbWrite(db, key, offset, size) |
|||
} else { |
|||
boltDbDelete(db, key) |
|||
} |
|||
return nil |
|||
}) |
|||
} |
|||
|
|||
func (m *BoltDbNeedleMap) Get(key NeedleId) (element *needle.NeedleValue, ok bool) { |
|||
var offset Offset |
|||
var size uint32 |
|||
bytes := make([]byte, NeedleIdSize) |
|||
NeedleIdToBytes(bytes, key) |
|||
err := m.db.View(func(tx *bolt.Tx) error { |
|||
bucket := tx.Bucket(boltdbBucket) |
|||
if bucket == nil { |
|||
return fmt.Errorf("Bucket %q not found!", boltdbBucket) |
|||
} |
|||
|
|||
data := bucket.Get(bytes) |
|||
|
|||
if len(data) == 0 { |
|||
return NotFound |
|||
} |
|||
|
|||
if len(data) != OffsetSize+SizeSize { |
|||
glog.V(0).Infof("key:%v has wrong data length: %d", key, len(data)) |
|||
return fmt.Errorf("key:%v has wrong data length: %d", key, len(data)) |
|||
} |
|||
|
|||
offset = BytesToOffset(data[0:OffsetSize]) |
|||
size = util.BytesToUint32(data[OffsetSize : OffsetSize+SizeSize]) |
|||
|
|||
return nil |
|||
}) |
|||
|
|||
if err != nil { |
|||
return nil, false |
|||
} |
|||
return &needle.NeedleValue{Key: key, Offset: offset, Size: size}, true |
|||
} |
|||
|
|||
func (m *BoltDbNeedleMap) Put(key NeedleId, offset Offset, size uint32) error { |
|||
var oldSize uint32 |
|||
if oldNeedle, ok := m.Get(key); ok { |
|||
oldSize = oldNeedle.Size |
|||
} |
|||
m.logPut(key, oldSize, size) |
|||
// write to index file first
|
|||
if err := m.appendToIndexFile(key, offset, size); err != nil { |
|||
return fmt.Errorf("cannot write to indexfile %s: %v", m.indexFile.Name(), err) |
|||
} |
|||
return boltDbWrite(m.db, key, offset, size) |
|||
} |
|||
|
|||
func boltDbWrite(db *bolt.DB, |
|||
key NeedleId, offset Offset, size uint32) error { |
|||
|
|||
bytes := make([]byte, NeedleIdSize+OffsetSize+SizeSize) |
|||
NeedleIdToBytes(bytes[0:NeedleIdSize], key) |
|||
OffsetToBytes(bytes[NeedleIdSize:NeedleIdSize+OffsetSize], offset) |
|||
util.Uint32toBytes(bytes[NeedleIdSize+OffsetSize:NeedleIdSize+OffsetSize+SizeSize], size) |
|||
|
|||
return db.Update(func(tx *bolt.Tx) error { |
|||
bucket, err := tx.CreateBucketIfNotExists(boltdbBucket) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
err = bucket.Put(bytes[0:NeedleIdSize], bytes[NeedleIdSize:NeedleIdSize+OffsetSize+SizeSize]) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
return nil |
|||
}) |
|||
} |
|||
func boltDbDelete(db *bolt.DB, key NeedleId) error { |
|||
bytes := make([]byte, NeedleIdSize) |
|||
NeedleIdToBytes(bytes, key) |
|||
return db.Update(func(tx *bolt.Tx) error { |
|||
bucket, err := tx.CreateBucketIfNotExists(boltdbBucket) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
err = bucket.Delete(bytes) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
return nil |
|||
}) |
|||
} |
|||
|
|||
func (m *BoltDbNeedleMap) Delete(key NeedleId, offset Offset) error { |
|||
if oldNeedle, ok := m.Get(key); ok { |
|||
m.logDelete(oldNeedle.Size) |
|||
} |
|||
// write to index file first
|
|||
if err := m.appendToIndexFile(key, offset, TombstoneFileSize); err != nil { |
|||
return err |
|||
} |
|||
return boltDbDelete(m.db, key) |
|||
} |
|||
|
|||
func (m *BoltDbNeedleMap) Close() { |
|||
m.indexFile.Close() |
|||
m.db.Close() |
|||
} |
|||
|
|||
func (m *BoltDbNeedleMap) Destroy() error { |
|||
m.Close() |
|||
os.Remove(m.indexFile.Name()) |
|||
return os.Remove(m.dbFileName) |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue