diff options
Diffstat (limited to 'weed/mount/filehandle.go')
| -rw-r--r-- | weed/mount/filehandle.go | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/weed/mount/filehandle.go b/weed/mount/filehandle.go index 6cbc9745e..d3836754f 100644 --- a/weed/mount/filehandle.go +++ b/weed/mount/filehandle.go @@ -31,6 +31,11 @@ type FileHandle struct { isDeleted bool + // RDMA chunk offset cache for performance optimization + chunkOffsetCache []int64 + chunkCacheValid bool + chunkCacheLock sync.RWMutex + // for debugging mirrorFile *os.File } @@ -84,14 +89,25 @@ func (fh *FileHandle) SetEntry(entry *filer_pb.Entry) { glog.Fatalf("setting file handle entry to nil") } fh.entry.SetEntry(entry) + + // Invalidate chunk offset cache since chunks may have changed + fh.invalidateChunkCache() } func (fh *FileHandle) UpdateEntry(fn func(entry *filer_pb.Entry)) *filer_pb.Entry { - return fh.entry.UpdateEntry(fn) + result := fh.entry.UpdateEntry(fn) + + // Invalidate chunk offset cache since entry may have been modified + fh.invalidateChunkCache() + + return result } func (fh *FileHandle) AddChunks(chunks []*filer_pb.FileChunk) { fh.entry.AppendChunks(chunks) + + // Invalidate chunk offset cache since new chunks were added + fh.invalidateChunkCache() } func (fh *FileHandle) ReleaseHandle() { @@ -111,3 +127,48 @@ func lessThan(a, b *filer_pb.FileChunk) bool { } return a.ModifiedTsNs < b.ModifiedTsNs } + +// getCumulativeOffsets returns cached cumulative offsets for chunks, computing them if necessary +func (fh *FileHandle) getCumulativeOffsets(chunks []*filer_pb.FileChunk) []int64 { + fh.chunkCacheLock.RLock() + if fh.chunkCacheValid && len(fh.chunkOffsetCache) == len(chunks)+1 { + // Cache is valid and matches current chunk count + result := make([]int64, len(fh.chunkOffsetCache)) + copy(result, fh.chunkOffsetCache) + fh.chunkCacheLock.RUnlock() + return result + } + fh.chunkCacheLock.RUnlock() + + // Need to compute/recompute cache + fh.chunkCacheLock.Lock() + defer fh.chunkCacheLock.Unlock() + + // Double-check in case another goroutine computed it while we waited for the lock + if fh.chunkCacheValid && len(fh.chunkOffsetCache) == len(chunks)+1 { + result := make([]int64, len(fh.chunkOffsetCache)) + copy(result, fh.chunkOffsetCache) + return result + } + + // Compute cumulative offsets + cumulativeOffsets := make([]int64, len(chunks)+1) + for i, chunk := range chunks { + cumulativeOffsets[i+1] = cumulativeOffsets[i] + int64(chunk.Size) + } + + // Cache the result + fh.chunkOffsetCache = make([]int64, len(cumulativeOffsets)) + copy(fh.chunkOffsetCache, cumulativeOffsets) + fh.chunkCacheValid = true + + return cumulativeOffsets +} + +// invalidateChunkCache invalidates the chunk offset cache when chunks are modified +func (fh *FileHandle) invalidateChunkCache() { + fh.chunkCacheLock.Lock() + fh.chunkCacheValid = false + fh.chunkOffsetCache = nil + fh.chunkCacheLock.Unlock() +} |
