Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go-fuse
Commits
beb5f868
Commit
beb5f868
authored
Sep 26, 2011
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add update method MemUnionFs.
parent
05a51a96
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
127 additions
and
6 deletions
+127
-6
unionfs/memunionfs.go
unionfs/memunionfs.go
+54
-3
unionfs/memunionfs_test.go
unionfs/memunionfs_test.go
+73
-3
No files found.
unionfs/memunionfs.go
View file @
beb5f868
...
...
@@ -7,6 +7,7 @@ import (
"os"
"path/filepath"
"strings"
"sort"
"sync"
"time"
)
...
...
@@ -18,7 +19,7 @@ type MemUnionFs struct {
fuse
.
DefaultNodeFileSystem
backingStore
string
root
*
memNode
connector
*
fuse
.
FileSystemConnector
mutex
sync
.
RWMutex
cond
*
sync
.
Cond
nextFree
int
...
...
@@ -43,12 +44,16 @@ type memNode struct {
}
type
Result
struct
{
Info
*
os
.
FileInfo
*
os
.
FileInfo
Original
string
Backing
string
Link
string
}
func
(
me
*
MemUnionFs
)
OnMount
(
conn
*
fuse
.
FileSystemConnector
)
{
me
.
connector
=
conn
}
func
(
me
*
MemUnionFs
)
release
()
{
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
...
...
@@ -74,6 +79,52 @@ func (me *MemUnionFs) Clear() {
me
.
root
.
Clear
(
""
)
}
func
(
me
*
MemUnionFs
)
Update
(
results
map
[
string
]
*
Result
)
{
del
:=
[]
string
{}
add
:=
[]
string
{}
for
k
,
v
:=
range
results
{
if
v
.
FileInfo
!=
nil
{
add
=
append
(
add
,
k
)
}
else
{
del
=
append
(
del
,
k
)
}
}
sort
.
Strings
(
del
)
for
i
:=
len
(
del
)
-
1
;
i
>=
0
;
i
--
{
n
:=
del
[
i
]
dir
,
base
:=
filepath
.
Split
(
n
)
dir
=
strings
.
TrimRight
(
dir
,
"/"
)
dirNode
,
rest
:=
me
.
connector
.
Node
(
me
.
root
.
Inode
(),
dir
)
if
len
(
rest
)
>
0
{
continue
}
dirNode
.
RmChild
(
base
)
me
.
connector
.
EntryNotify
(
dirNode
,
base
)
}
me
.
mutex
.
Lock
()
defer
me
.
mutex
.
Unlock
()
sort
.
Strings
(
add
)
for
_
,
n
:=
range
add
{
node
,
rest
:=
me
.
connector
.
Node
(
me
.
root
.
Inode
(),
n
)
if
len
(
rest
)
>
0
{
me
.
connector
.
EntryNotify
(
node
,
rest
[
0
])
continue
}
me
.
connector
.
FileNotify
(
node
,
0
,
0
)
mn
:=
node
.
FsNode
()
.
(
*
memNode
)
mn
.
original
=
n
mn
.
changed
=
false
r
:=
results
[
n
]
mn
.
info
=
*
r
.
FileInfo
mn
.
link
=
r
.
Link
}
}
func
(
me
*
MemUnionFs
)
getFilename
()
string
{
id
:=
me
.
nextFree
me
.
nextFree
++
...
...
@@ -439,7 +490,7 @@ func (me *memNode) Reap(path string, results map[string]*Result) {
if
me
.
changed
{
info
:=
me
.
info
results
[
path
]
=
&
Result
{
Info
:
&
info
,
File
Info
:
&
info
,
Link
:
me
.
link
,
Backing
:
me
.
backing
,
Original
:
me
.
original
,
...
...
unionfs/memunionfs_test.go
View file @
beb5f868
...
...
@@ -32,7 +32,7 @@ func setupMemUfs(t *testing.T) (workdir string, ufs *MemUnionFs, cleanup func())
os
.
Mkdir
(
wd
+
"/ro"
,
0700
)
fuse
.
CheckSuccess
(
err
)
roFs
:=
NewCachingFileSystem
(
fuse
.
NewLoopbackFileSystem
(
wd
+
"/ro"
),
0.0
)
roFs
:=
fuse
.
NewLoopbackFileSystem
(
wd
+
"/ro"
)
memFs
:=
NewMemUnionFs
(
wd
+
"/backing"
,
roFs
)
// We configure timeouts are smaller, so we can check for
...
...
@@ -167,7 +167,7 @@ func TestMemUnionFsDelete(t *testing.T) {
}
r
:=
ufs
.
Reap
()
if
r
[
"file"
]
==
nil
||
r
[
"file"
]
.
Info
!=
nil
{
if
r
[
"file"
]
==
nil
||
r
[
"file"
]
.
File
Info
!=
nil
{
t
.
Errorf
(
"expect 1 deletion reap result: %v"
,
r
)
}
}
...
...
@@ -279,7 +279,7 @@ func TestMemUnionFsMkdirPromote(t *testing.T) {
CheckSuccess
(
err
)
r
:=
ufs
.
Reap
()
if
r
[
"subdir/subdir2/dir3"
]
==
nil
||
r
[
"subdir/subdir2/dir3"
]
.
Info
.
Mode
&
fuse
.
S_IFDIR
==
0
{
if
r
[
"subdir/subdir2/dir3"
]
==
nil
||
r
[
"subdir/subdir2/dir3"
]
.
File
Info
.
Mode
&
fuse
.
S_IFDIR
==
0
{
t
.
Errorf
(
"expect 1 file reap result: %v"
,
r
)
}
}
...
...
@@ -488,6 +488,76 @@ func TestMemUnionFsDoubleOpen(t *testing.T) {
}
}
func
TestMemUnionFsUpdate
(
t
*
testing
.
T
)
{
wd
,
ufs
,
clean
:=
setupMemUfs
(
t
)
defer
clean
()
err
:=
ioutil
.
WriteFile
(
wd
+
"/ro/file1"
,
[]
byte
(
"blablabla"
),
0644
)
CheckSuccess
(
err
)
_
,
err
=
os
.
Lstat
(
wd
+
"/mount/file1"
)
CheckSuccess
(
err
)
if
fi
,
_
:=
os
.
Lstat
(
wd
+
"/mount/file2"
);
fi
!=
nil
{
t
.
Fatal
(
"file2 should not exist"
,
fi
)
}
if
fi
,
_
:=
os
.
Lstat
(
wd
+
"/mount/symlink"
);
fi
!=
nil
{
t
.
Fatal
(
"symlink should not exist"
,
fi
)
}
err
=
os
.
Remove
(
wd
+
"/ro/file1"
)
CheckSuccess
(
err
)
err
=
ioutil
.
WriteFile
(
wd
+
"/ro/file2"
,
[]
byte
(
"foobar"
),
0644
)
CheckSuccess
(
err
)
err
=
os
.
Symlink
(
"target"
,
wd
+
"/ro/symlink"
)
CheckSuccess
(
err
)
// Still have cached attributes.
fi
,
err
:=
os
.
Lstat
(
wd
+
"/mount/file1"
)
CheckSuccess
(
err
)
if
fi
,
_
:=
os
.
Lstat
(
wd
+
"/mount/file2"
);
fi
!=
nil
{
t
.
Fatal
(
"file2 should not exist"
)
}
if
fi
,
_
:=
os
.
Lstat
(
wd
+
"/mount/symlink"
);
fi
!=
nil
{
t
.
Fatal
(
"symlink should not exist"
,
fi
)
}
roF2
,
err
:=
os
.
Lstat
(
wd
+
"/ro/file2"
)
CheckSuccess
(
err
)
roSymlinkFi
,
err
:=
os
.
Lstat
(
wd
+
"/ro/symlink"
)
CheckSuccess
(
err
)
updates
:=
map
[
string
]
*
Result
{
"file1"
:
&
Result
{
nil
,
""
,
""
,
""
,
},
"file2"
:
&
Result
{
roF2
,
""
,
""
,
""
,
},
"symlink"
:
&
Result
{
roSymlinkFi
,
""
,
""
,
"target"
,
},
}
ufs
.
Update
(
updates
)
// Cached attributes flushed.
if
fi
,
_
:=
os
.
Lstat
(
wd
+
"/mount/file1"
);
fi
!=
nil
{
t
.
Fatal
(
"file1 should have disappeared"
,
fi
)
}
fi
,
err
=
os
.
Lstat
(
wd
+
"/mount/file2"
)
CheckSuccess
(
err
)
if
roF2
.
Mtime_ns
!=
fi
.
Mtime_ns
{
t
.
Fatalf
(
"file2 attribute mismatch: got %v want %v"
,
fi
,
roF2
)
}
val
,
err
:=
os
.
Readlink
(
wd
+
"/mount/symlink"
)
CheckSuccess
(
err
)
if
val
!=
"target"
{
t
.
Error
(
"symlink value got %q want %v"
,
val
,
"target"
)
}
}
func
TestMemUnionFsFdLeak
(
t
*
testing
.
T
)
{
beforeEntries
,
err
:=
ioutil
.
ReadDir
(
"/proc/self/fd"
)
CheckSuccess
(
err
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment