Merge branch '19362-all-webdav-via-sitefs'
[arvados.git] / sdk / go / arvados / fs_collection.go
index 256f513cf9f3e9a126bb918fe18a021ca7ca2e8b..a26c876b932304ab6fdfefbafe36145665cbac90 100644 (file)
@@ -469,8 +469,6 @@ func (fs *collectionFileSystem) Flush(path string, shortBlocks bool) error {
 }
 
 func (fs *collectionFileSystem) MemorySize() int64 {
-       fs.fileSystem.root.Lock()
-       defer fs.fileSystem.root.Unlock()
        return fs.fileSystem.root.(*dirnode).MemorySize()
 }
 
@@ -602,6 +600,16 @@ func (fn *filenode) FS() FileSystem {
        return fn.fs
 }
 
+func (fn *filenode) MemorySize() (size int64) {
+       fn.RLock()
+       defer fn.RUnlock()
+       size = 64
+       for _, seg := range fn.segments {
+               size += seg.memorySize()
+       }
+       return
+}
+
 // Read reads file data from a single segment, starting at startPtr,
 // into p. startPtr is assumed not to be up-to-date. Caller must have
 // RLock or Lock.
@@ -1176,28 +1184,18 @@ func (dn *dirnode) flush(ctx context.Context, names []string, opts flushOpts) er
        return cg.Wait()
 }
 
-// caller must have write lock.
 func (dn *dirnode) MemorySize() (size int64) {
-       for _, name := range dn.sortedNames() {
-               node := dn.inodes[name]
-               node.Lock()
-               defer node.Unlock()
-               switch node := node.(type) {
-               case *dirnode:
-                       size += node.MemorySize()
-               case *filenode:
-                       size += 64
-                       for _, seg := range node.segments {
-                               switch seg := seg.(type) {
-                               case storedSegment:
-                                       size += int64(len(seg.locator)) + 40
-                               case *memSegment:
-                                       size += int64(seg.Len()) + 8
-                               }
-                       }
-               }
+       dn.RLock()
+       todo := make([]inode, 0, len(dn.inodes))
+       for _, node := range dn.inodes {
+               todo = append(todo, node)
+       }
+       dn.RUnlock()
+       size = 64
+       for _, node := range todo {
+               size += node.MemorySize()
        }
-       return 64 + size
+       return
 }
 
 // caller must have write lock.
@@ -1654,6 +1652,7 @@ type segment interface {
        // Return a new segment with a subsection of the data from this
        // one. length<0 means length=Len()-off.
        Slice(off int, length int) segment
+       memorySize() int64
 }
 
 type memSegment struct {
@@ -1732,6 +1731,10 @@ func (me *memSegment) ReadAt(p []byte, off int64) (n int, err error) {
        return
 }
 
+func (me *memSegment) memorySize() int64 {
+       return 64 + int64(len(me.buf))
+}
+
 type storedSegment struct {
        kc      fsBackend
        locator string
@@ -1769,6 +1772,10 @@ func (se storedSegment) ReadAt(p []byte, off int64) (n int, err error) {
        return se.kc.ReadAt(se.locator, p, int(off)+se.offset)
 }
 
+func (se storedSegment) memorySize() int64 {
+       return 64 + int64(len(se.locator))
+}
+
 func canonicalName(name string) string {
        name = path.Clean("/" + name)
        if name == "/" || name == "./" {