aboutsummaryrefslogtreecommitdiff
path: root/weed/mount/filehandle.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/mount/filehandle.go')
-rw-r--r--weed/mount/filehandle.go63
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()
+}