seaweedfs/weed/filesys/dirty_page.go

151 lines
3.5 KiB
Go
Raw Normal View History

package filesys
import (
"bytes"
2021-05-10 06:15:18 +08:00
"fmt"
2020-10-15 14:28:03 +08:00
"io"
"sync"
"time"
2020-10-21 17:16:21 +08:00
"github.com/chrislusf/seaweedfs/weed/glog"
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
)
type ContinuousDirtyPages struct {
2021-01-29 07:23:46 +08:00
intervals *ContinuousIntervals
f *File
2021-05-10 06:22:38 +08:00
writeOnly bool
2021-01-29 07:23:46 +08:00
writeWaitGroup sync.WaitGroup
chunkAddLock sync.Mutex
lastErr error
collection string
replication string
}
2021-05-10 06:22:38 +08:00
func newDirtyPages(file *File, writeOnly bool) *ContinuousDirtyPages {
2020-10-21 17:16:21 +08:00
dirtyPages := &ContinuousDirtyPages{
2021-01-29 07:23:46 +08:00
intervals: &ContinuousIntervals{},
f: file,
2021-05-10 06:22:38 +08:00
writeOnly: writeOnly,
}
2020-10-21 17:16:21 +08:00
return dirtyPages
2018-05-29 16:21:21 +08:00
}
2020-10-15 14:28:03 +08:00
func (pages *ContinuousDirtyPages) AddPage(offset int64, data []byte) {
glog.V(4).Infof("%s AddPage [%d,%d)", pages.f.fullpath(), offset, offset+int64(len(data)))
2019-01-01 18:14:40 +08:00
if len(data) > int(pages.f.wfs.option.ChunkSizeLimit) {
2018-05-31 13:09:24 +08:00
// this is more than what buffer can hold.
2020-10-15 14:28:03 +08:00
pages.flushAndSave(offset, data)
}
2020-01-27 05:01:11 +08:00
pages.intervals.AddInterval(data, offset)
2020-10-22 10:29:51 +08:00
if pages.intervals.TotalSize() >= pages.f.wfs.option.ChunkSizeLimit {
2020-10-15 14:28:03 +08:00
pages.saveExistingLargestPageToStorage()
}
return
}
2020-10-15 14:28:03 +08:00
func (pages *ContinuousDirtyPages) flushAndSave(offset int64, data []byte) {
// flush existing
2020-10-15 14:28:03 +08:00
pages.saveExistingPagesToStorage()
// flush the new page
2020-10-15 14:28:03 +08:00
pages.saveToStorage(bytes.NewReader(data), offset, int64(len(data)))
return
}
2021-05-10 06:15:18 +08:00
func (pages *ContinuousDirtyPages) FlushData() error {
pages.saveExistingPagesToStorage()
pages.writeWaitGroup.Wait()
if pages.lastErr != nil {
return fmt.Errorf("flush data: %v", pages.lastErr)
}
return nil
}
2020-10-15 14:28:03 +08:00
func (pages *ContinuousDirtyPages) saveExistingPagesToStorage() {
for pages.saveExistingLargestPageToStorage() {
}
}
2020-10-15 14:28:03 +08:00
func (pages *ContinuousDirtyPages) saveExistingLargestPageToStorage() (hasSavedData bool) {
maxList := pages.intervals.RemoveLargestIntervalLinkedList()
if maxList == nil {
2020-10-15 14:28:03 +08:00
return false
}
entry := pages.f.getEntry()
if entry == nil {
return false
}
fileSize := int64(entry.Attributes.FileSize)
2020-10-15 14:28:03 +08:00
chunkSize := min(maxList.Size(), fileSize-maxList.Offset())
if chunkSize == 0 {
return false
}
2020-10-15 14:28:03 +08:00
pages.saveToStorage(maxList.ToReader(), maxList.Offset(), chunkSize)
return true
}
2020-10-15 14:28:03 +08:00
func (pages *ContinuousDirtyPages) saveToStorage(reader io.Reader, offset int64, size int64) {
mtime := time.Now().UnixNano()
2020-10-15 14:28:03 +08:00
pages.writeWaitGroup.Add(1)
writer := func() {
2020-10-15 14:28:03 +08:00
defer pages.writeWaitGroup.Done()
2020-10-15 14:28:03 +08:00
reader = io.LimitReader(reader, size)
2021-05-10 06:22:38 +08:00
chunk, collection, replication, err := pages.f.wfs.saveDataAsChunk(pages.f.fullpath(), pages.writeOnly)(reader, pages.f.Name, offset)
2020-10-15 14:28:03 +08:00
if err != nil {
glog.V(0).Infof("%s saveToStorage [%d,%d): %v", pages.f.fullpath(), offset, offset+size, err)
pages.lastErr = err
2020-10-15 14:28:03 +08:00
return
}
chunk.Mtime = mtime
2020-10-15 14:28:03 +08:00
pages.collection, pages.replication = collection, replication
2020-11-04 04:20:41 +08:00
pages.chunkAddLock.Lock()
defer pages.chunkAddLock.Unlock()
2020-10-15 14:28:03 +08:00
pages.f.addChunks([]*filer_pb.FileChunk{chunk})
2020-10-21 17:17:40 +08:00
glog.V(3).Infof("%s saveToStorage [%d,%d)", pages.f.fullpath(), offset, offset+size)
}
if pages.f.wfs.concurrentWriters != nil {
pages.f.wfs.concurrentWriters.Execute(writer)
} else {
go writer()
}
}
2018-05-29 16:21:21 +08:00
func max(x, y int64) int64 {
if x > y {
return x
}
return y
}
func min(x, y int64) int64 {
if x < y {
return x
}
return y
}
2020-08-18 02:12:10 +08:00
func (pages *ContinuousDirtyPages) ReadDirtyDataAt(data []byte, startOffset int64) (maxStop int64) {
return pages.intervals.ReadDataAt(data, startOffset)
}
2021-05-10 06:28:54 +08:00
func (pages *ContinuousDirtyPages) GetStorageOptions() (collection, replication string) {
return pages.collection, pages.replication
}