seaweedfs/go/storage/needle_map.go

115 lines
3 KiB
Go
Raw Normal View History

package storage
import (
"code.google.com/p/weed-fs/go/util"
2013-02-10 22:00:06 +00:00
"fmt"
2013-02-12 07:54:21 +00:00
"io"
2013-02-10 22:00:06 +00:00
"os"
)
type NeedleMap struct {
indexFile *os.File
m CompactMap
2012-10-10 03:53:31 +00:00
//transient
2012-11-24 01:03:27 +00:00
bytes []byte
deletionCounter int
fileCounter int
deletionByteCounter uint64
fileByteCounter uint64
}
func NewNeedleMap(file *os.File) *NeedleMap {
nm := &NeedleMap{
m: NewCompactMap(),
bytes: make([]byte, 16),
indexFile: file,
}
return nm
}
const (
RowsToRead = 1024
)
2013-02-10 22:00:06 +00:00
func LoadNeedleMap(file *os.File) (*NeedleMap, error) {
nm := NewNeedleMap(file)
bytes := make([]byte, 16*RowsToRead)
count, e := nm.indexFile.Read(bytes)
for count > 0 && e == nil {
for i := 0; i < count; i += 16 {
key := util.BytesToUint64(bytes[i : i+8])
offset := util.BytesToUint32(bytes[i+8 : i+12])
size := util.BytesToUint32(bytes[i+12 : i+16])
nm.fileCounter++
nm.fileByteCounter = nm.fileByteCounter + uint64(size)
if offset > 0 {
oldSize := nm.m.Set(Key(key), offset, size)
//log.Println("reading key", key, "offset", offset, "size", size, "oldSize", oldSize)
if oldSize > 0 {
nm.deletionCounter++
nm.deletionByteCounter = nm.deletionByteCounter + uint64(oldSize)
}
} else {
oldSize := nm.m.Delete(Key(key))
//log.Println("removing key", key, "offset", offset, "size", size, "oldSize", oldSize)
nm.deletionCounter++
nm.deletionByteCounter = nm.deletionByteCounter + uint64(oldSize)
}
}
count, e = nm.indexFile.Read(bytes)
}
2013-02-12 07:54:21 +00:00
if e == io.EOF {
e = nil
}
return nm, e
}
func (nm *NeedleMap) Put(key uint64, offset uint32, size uint32) (int, error) {
2012-11-24 01:03:27 +00:00
oldSize := nm.m.Set(Key(key), offset, size)
util.Uint64toBytes(nm.bytes[0:8], key)
util.Uint32toBytes(nm.bytes[8:12], offset)
util.Uint32toBytes(nm.bytes[12:16], size)
2012-10-10 03:53:31 +00:00
nm.fileCounter++
nm.fileByteCounter = nm.fileByteCounter + uint64(size)
2012-11-24 01:03:27 +00:00
if oldSize > 0 {
nm.deletionCounter++
nm.deletionByteCounter = nm.deletionByteCounter + uint64(oldSize)
2012-11-24 01:03:27 +00:00
}
return nm.indexFile.Write(nm.bytes)
}
func (nm *NeedleMap) Get(key uint64) (element *NeedleValue, ok bool) {
element, ok = nm.m.Get(Key(key))
return
}
2013-02-10 22:00:06 +00:00
func (nm *NeedleMap) Delete(key uint64) error {
nm.deletionByteCounter = nm.deletionByteCounter + uint64(nm.m.Delete(Key(key)))
2013-02-10 22:00:06 +00:00
offset, err := nm.indexFile.Seek(0, 1)
if err != nil {
return fmt.Errorf("cannot get position of indexfile: %s", err)
}
util.Uint64toBytes(nm.bytes[0:8], key)
util.Uint32toBytes(nm.bytes[8:12], 0)
util.Uint32toBytes(nm.bytes[12:16], 0)
2013-02-10 22:00:06 +00:00
if _, err = nm.indexFile.Write(nm.bytes); err != nil {
2013-02-27 06:54:22 +00:00
plus := ""
if e := nm.indexFile.Truncate(offset); e != nil {
plus = "\ncouldn't truncate index file: " + e.Error()
}
return fmt.Errorf("error writing to indexfile %s: %s%s", nm.indexFile, err, plus)
2013-02-10 22:00:06 +00:00
}
2012-10-10 03:53:31 +00:00
nm.deletionCounter++
2013-02-10 22:00:06 +00:00
return nil
}
func (nm *NeedleMap) Close() {
2013-02-27 06:54:22 +00:00
_ = nm.indexFile.Close()
}
func (nm *NeedleMap) ContentSize() uint64 {
return nm.fileByteCounter
}
func (nm *NeedleMap) Visit(visit func(NeedleValue) error) (err error) {
return nm.m.Visit(visit)
}