vfs: keep track of number of open RWHandles
This commit is contained in:
parent
5e334eedd2
commit
9b011ce7e4
3 changed files with 52 additions and 1 deletions
26
vfs/file.go
26
vfs/file.go
|
@ -21,6 +21,7 @@ type File struct {
|
||||||
mu sync.Mutex // protects the following
|
mu sync.Mutex // protects the following
|
||||||
o fs.Object // NB o may be nil if file is being written
|
o fs.Object // NB o may be nil if file is being written
|
||||||
leaf string // leaf name of the object
|
leaf string // leaf name of the object
|
||||||
|
rwOpenCount int // number of open files on this handle
|
||||||
writers []Handle // writers for this file
|
writers []Handle // writers for this file
|
||||||
readWriters int // how many RWFileHandle are open for writing
|
readWriters int // how many RWFileHandle are open for writing
|
||||||
readWriterClosing bool // is a RWFileHandle currently cosing?
|
readWriterClosing bool // is a RWFileHandle currently cosing?
|
||||||
|
@ -138,6 +139,31 @@ func (f *File) delWriter(h Handle, modifiedCacheFile bool) (lastWriterAndModifie
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addRWOpen should be called by ReadWriteHandle when they have
|
||||||
|
// actually opened the file for read or write.
|
||||||
|
func (f *File) addRWOpen() {
|
||||||
|
f.mu.Lock()
|
||||||
|
f.rwOpenCount++
|
||||||
|
f.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// delRWOpen should be called by ReadWriteHandle when they have closed
|
||||||
|
// an actually opene file for read or write.
|
||||||
|
func (f *File) delRWOpen() {
|
||||||
|
f.mu.Lock()
|
||||||
|
f.rwOpenCount--
|
||||||
|
f.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// rwOpens returns how many active open ReadWriteHandles there are.
|
||||||
|
// Note that file handles which are in pending open state aren't
|
||||||
|
// counted.
|
||||||
|
func (f *File) rwOpens() int {
|
||||||
|
f.mu.Lock()
|
||||||
|
defer f.mu.Unlock()
|
||||||
|
return f.rwOpenCount
|
||||||
|
}
|
||||||
|
|
||||||
// finishWriterClose resets the readWriterClosing flag
|
// finishWriterClose resets the readWriterClosing flag
|
||||||
func (f *File) finishWriterClose() {
|
func (f *File) finishWriterClose() {
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
|
|
|
@ -192,6 +192,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
|
||||||
}
|
}
|
||||||
fh.File = fd
|
fh.File = fd
|
||||||
fh.opened = true
|
fh.opened = true
|
||||||
|
fh.file.addRWOpen()
|
||||||
fh.d.addObject(fh.file) // make sure the directory has this object in it now
|
fh.d.addObject(fh.file) // make sure the directory has this object in it now
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -246,7 +247,12 @@ func (fh *RWFileHandle) close() (err error) {
|
||||||
return ECLOSED
|
return ECLOSED
|
||||||
}
|
}
|
||||||
fh.closed = true
|
fh.closed = true
|
||||||
defer fh.d.vfs.cache.close(fh.remote)
|
defer func() {
|
||||||
|
if fh.opened {
|
||||||
|
fh.file.delRWOpen()
|
||||||
|
}
|
||||||
|
fh.d.vfs.cache.close(fh.remote)
|
||||||
|
}()
|
||||||
rdwrMode := fh.flags & accessModeMask
|
rdwrMode := fh.flags & accessModeMask
|
||||||
writer := rdwrMode != os.O_RDONLY
|
writer := rdwrMode != os.O_RDONLY
|
||||||
|
|
||||||
|
|
|
@ -74,9 +74,15 @@ func TestRWFileHandleMethodsRead(t *testing.T) {
|
||||||
// Size
|
// Size
|
||||||
assert.Equal(t, int64(16), fh.Size())
|
assert.Equal(t, int64(16), fh.Size())
|
||||||
|
|
||||||
|
// No opens yet
|
||||||
|
assert.Equal(t, 0, fh.file.rwOpens())
|
||||||
|
|
||||||
// Read 1
|
// Read 1
|
||||||
assert.Equal(t, "0", rwReadString(t, fh, 1))
|
assert.Equal(t, "0", rwReadString(t, fh, 1))
|
||||||
|
|
||||||
|
// Open after the read
|
||||||
|
assert.Equal(t, 1, fh.file.rwOpens())
|
||||||
|
|
||||||
// Read remainder
|
// Read remainder
|
||||||
assert.Equal(t, "123456789abcdef", rwReadString(t, fh, 256))
|
assert.Equal(t, "123456789abcdef", rwReadString(t, fh, 256))
|
||||||
|
|
||||||
|
@ -101,6 +107,9 @@ func TestRWFileHandleMethodsRead(t *testing.T) {
|
||||||
assert.Equal(t, nil, fh.Close())
|
assert.Equal(t, nil, fh.Close())
|
||||||
assert.True(t, fh.closed)
|
assert.True(t, fh.closed)
|
||||||
|
|
||||||
|
// No opens again
|
||||||
|
assert.Equal(t, 0, fh.file.rwOpens())
|
||||||
|
|
||||||
// Close again
|
// Close again
|
||||||
assert.Equal(t, ECLOSED, fh.Close())
|
assert.Equal(t, ECLOSED, fh.Close())
|
||||||
}
|
}
|
||||||
|
@ -266,6 +275,10 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
|
||||||
vfs, fh := rwHandleCreateWriteOnly(t, r)
|
vfs, fh := rwHandleCreateWriteOnly(t, r)
|
||||||
defer cleanup(t, r, vfs)
|
defer cleanup(t, r, vfs)
|
||||||
|
|
||||||
|
// 1 opens since we opened with O_CREATE and the file didn't
|
||||||
|
// exist in the cache
|
||||||
|
assert.Equal(t, 1, fh.file.rwOpens())
|
||||||
|
|
||||||
// String
|
// String
|
||||||
assert.Equal(t, "file1 (rw)", fh.String())
|
assert.Equal(t, "file1 (rw)", fh.String())
|
||||||
assert.Equal(t, "<nil *RWFileHandle>", (*RWFileHandle)(nil).String())
|
assert.Equal(t, "<nil *RWFileHandle>", (*RWFileHandle)(nil).String())
|
||||||
|
@ -293,6 +306,9 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 5, n)
|
assert.Equal(t, 5, n)
|
||||||
|
|
||||||
|
// Open after the write
|
||||||
|
assert.Equal(t, 1, fh.file.rwOpens())
|
||||||
|
|
||||||
// Offset #2
|
// Offset #2
|
||||||
assert.Equal(t, int64(5), offset())
|
assert.Equal(t, int64(5), offset())
|
||||||
assert.Equal(t, int64(5), node.Size())
|
assert.Equal(t, int64(5), node.Size())
|
||||||
|
@ -323,6 +339,9 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
|
||||||
// Close
|
// Close
|
||||||
assert.NoError(t, fh.Close())
|
assert.NoError(t, fh.Close())
|
||||||
|
|
||||||
|
// No opens again
|
||||||
|
assert.Equal(t, 0, fh.file.rwOpens())
|
||||||
|
|
||||||
// Check double close
|
// Check double close
|
||||||
err = fh.Close()
|
err = fh.Close()
|
||||||
assert.Equal(t, ECLOSED, err)
|
assert.Equal(t, ECLOSED, err)
|
||||||
|
|
Loading…
Reference in a new issue