mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 13:18:53 +00:00
taildrop: implement asynchronous file deletion (#9844)
File resumption requires keeping partial files around for some time, but we must still eventually delete them if never resumed. Thus, we implement asynchronous file deletion, which could spawn a background goroutine to delete the files. We also use the same mechanism for deleting files on Windows, where a file can't be deleted if there is still an open file handle. We can enqueue those with the asynchronous file deleter as well. Updates tailscale/corp#14772 Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
@@ -646,6 +646,9 @@ func (b *LocalBackend) Shutdown() {
|
||||
if b.sockstatLogger != nil {
|
||||
b.sockstatLogger.Shutdown()
|
||||
}
|
||||
if b.peerAPIServer != nil {
|
||||
b.peerAPIServer.taildrop.Shutdown()
|
||||
}
|
||||
|
||||
b.unregisterNetMon()
|
||||
b.unregisterHealthWatch()
|
||||
@@ -3614,14 +3617,14 @@ func (b *LocalBackend) initPeerAPIListener() {
|
||||
|
||||
ps := &peerAPIServer{
|
||||
b: b,
|
||||
taildrop: &taildrop.Manager{
|
||||
taildrop: taildrop.ManagerOptions{
|
||||
Logf: b.logf,
|
||||
Clock: tstime.DefaultClock{b.clock},
|
||||
Clock: tstime.DefaultClock{Clock: b.clock},
|
||||
Dir: fileRoot,
|
||||
DirectFileMode: b.directFileRoot != "",
|
||||
AvoidFinalRename: !b.directFileDoFinalRename,
|
||||
SendFileNotify: b.sendFileNotify,
|
||||
},
|
||||
}.New(),
|
||||
}
|
||||
if dm, ok := b.sys.DNSManager.GetOK(); ok {
|
||||
ps.resolver = dm.Resolver()
|
||||
|
@@ -68,7 +68,7 @@ func bodyNotContains(sub string) check {
|
||||
|
||||
func fileHasSize(name string, size int) check {
|
||||
return func(t *testing.T, e *peerAPITestEnv) {
|
||||
root := e.ph.ps.taildrop.Dir
|
||||
root := e.ph.ps.taildrop.Dir()
|
||||
if root == "" {
|
||||
t.Errorf("no rootdir; can't check whether %q has size %v", name, size)
|
||||
return
|
||||
@@ -84,7 +84,7 @@ func fileHasSize(name string, size int) check {
|
||||
|
||||
func fileHasContents(name string, want string) check {
|
||||
return func(t *testing.T, e *peerAPITestEnv) {
|
||||
root := e.ph.ps.taildrop.Dir
|
||||
root := e.ph.ps.taildrop.Dir()
|
||||
if root == "" {
|
||||
t.Errorf("no rootdir; can't check contents of %q", name)
|
||||
return
|
||||
@@ -540,11 +540,11 @@ func TestHandlePeerAPI(t *testing.T) {
|
||||
if !tt.omitRoot {
|
||||
rootDir = t.TempDir()
|
||||
if e.ph.ps.taildrop == nil {
|
||||
e.ph.ps.taildrop = &taildrop.Manager{
|
||||
e.ph.ps.taildrop = taildrop.ManagerOptions{
|
||||
Logf: e.logBuf.Logf,
|
||||
}
|
||||
Dir: rootDir,
|
||||
}.New()
|
||||
}
|
||||
e.ph.ps.taildrop.Dir = rootDir
|
||||
}
|
||||
for _, req := range tt.reqs {
|
||||
e.rr = httptest.NewRecorder()
|
||||
@@ -583,10 +583,10 @@ func TestFileDeleteRace(t *testing.T) {
|
||||
capFileSharing: true,
|
||||
clock: &tstest.Clock{},
|
||||
},
|
||||
taildrop: &taildrop.Manager{
|
||||
taildrop: taildrop.ManagerOptions{
|
||||
Logf: t.Logf,
|
||||
Dir: dir,
|
||||
},
|
||||
}.New(),
|
||||
}
|
||||
ph := &peerAPIHandler{
|
||||
isSelf: true,
|
||||
|
Reference in New Issue
Block a user