Skip to content

Commit e5816ba

Browse files
committed
less code, less bug
1 parent 5ed52af commit e5816ba

4 files changed

Lines changed: 44 additions & 76 deletions

File tree

bash/webdav/client.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"flag"
99
"fmt"
1010
"io"
11+
"io/fs"
1112
"net"
1213
"os"
1314
"path/filepath"
@@ -41,7 +42,7 @@ type Client struct {
4142
Ctx context.Context
4243
closed *multicast.Channel[any]
4344

44-
statsLocker *ttlcache.Cache[string, *StatWithLocker]
45+
statsCache *ttlcache.Cache[string, fs.FileInfo]
4546

4647
ServerAddr string
4748
}
@@ -54,8 +55,8 @@ func NewClient(conn net.Conn) *Client {
5455
),
5556
closed: multicast.New[any](),
5657

57-
statsLocker: ttlcache.New(
58-
ttlcache.WithTTL[string, *StatWithLocker](2 * time.Second),
58+
statsCache: ttlcache.New(
59+
ttlcache.WithTTL[string, fs.FileInfo](5 * time.Second),
5960
),
6061
}
6162
c.tasks.OnEviction(func(ctx context.Context, er ttlcache.EvictionReason, i *ttlcache.Item[string, chan net.Conn]) {
@@ -78,7 +79,7 @@ func (c *Client) Open(r *bufio.Reader, version string, id string) (err error) {
7879
To(c.initID(r))
7980
To(c.initPWD(r))
8081
go c.tasks.Start()
81-
go c.statsLocker.Start()
82+
go c.statsCache.Start()
8283

8384
span.SetAttributes(
8485
attribute.String("host", c.ID),
@@ -217,8 +218,8 @@ func (c *Client) Close() {
217218
c.tasks.DeleteAll()
218219
c.tasks.Stop()
219220

220-
c.statsLocker.DeleteAll()
221-
c.statsLocker.Stop()
221+
c.statsCache.DeleteAll()
222+
c.statsCache.Stop()
222223

223224
c.conn.Close()
224225
c.closed.Close()

bash/webdav/file.go

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,11 @@ func (f *File) Readdir(count int) (files []fs.FileInfo, err error) {
2222
defer span.End()
2323
defer err0.Record(&err, span)
2424

25-
list := To1(f.readdir(count))
26-
var wg sync.WaitGroup
27-
wg.Add(len(list))
28-
for _, stat := range list {
29-
go func(stat fs.FileInfo) {
30-
defer wg.Done()
31-
fname := filepath.Join(f.name, stat.Name())
32-
sl := f.c.StatLocker(fname)
33-
sl.locker.Lock()
34-
defer sl.locker.Unlock()
35-
sl.stat = stat
36-
}(stat)
25+
files = To1(f.readdir(count))
26+
for _, stat := range files {
27+
fname := filepath.Join(f.name, stat.Name())
28+
f.c.statsCache.Set(fname, stat, 0)
3729
}
38-
wg.Wait()
39-
files = list
4030
return
4131
}
4232

@@ -67,16 +57,14 @@ func (f *File) Stat() (finfo fs.FileInfo, err error) {
6757
return f.c.Stat(context.Background(), f.name)
6858
}
6959
func (f *File) _Stat() (finfo fs.FileInfo, err error) {
70-
f.locker.RLock()
71-
finfo = f.stat
72-
f.locker.RUnlock()
73-
if finfo != nil {
60+
f.statusInit.Do(func() {
61+
f.stat, err = f._GetStat()
62+
})
63+
if err != nil {
64+
f.statusInit = &sync.Once{}
7465
return
7566
}
76-
f.locker.Lock()
77-
defer f.locker.Unlock()
78-
finfo, err = f._GetStat()
79-
f.stat = finfo
67+
finfo = f.stat
8068
return
8169
}
8270
func (f *File) _GetStat() (finfo fs.FileInfo, err error) {

bash/webdav/file2.go

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,14 @@ type File struct {
2727
name string
2828
cursor int64
2929

30-
locker *sync.RWMutex
31-
stat fs.FileInfo
30+
statusInit *sync.Once
31+
stat fs.FileInfo
3232

33-
readerInit *sync.Once
34-
readerInitErr error
35-
reader net.Conn
33+
readerInit *sync.Once
34+
reader net.Conn
3635

37-
writerInit *sync.Once
38-
writerInitErr error
39-
writer net.Conn
36+
writerInit *sync.Once
37+
writer net.Conn
4038

4139
no uint64
4240
}
@@ -58,7 +56,7 @@ func OpenFile(c *Client, filename string) *File {
5856
c: c,
5957
name: filename,
6058

61-
locker: &sync.RWMutex{},
59+
statusInit: &sync.Once{},
6260
readerInit: &sync.Once{},
6361
writerInit: &sync.Once{},
6462
}
@@ -71,7 +69,7 @@ func (f *File) Close() error {
7169
f.reader.Close()
7270
}
7371
if f.writer != nil {
74-
defer f.c.statsLocker.Delete(f.name)
72+
defer f.c.statsCache.Delete(f.name)
7573
f.writer.Close()
7674
time.Sleep(200 * time.Millisecond) //等200ms, 让dd把末尾的输入内容写入到文件内
7775
}
@@ -88,19 +86,21 @@ func (f *File) Read(p []byte) (n int, err error) {
8886
err0.Record(&err, span)
8987
})
9088

91-
stat := To1(f.Stat())
89+
stat := To1(f._Stat())
9290
if stat.IsDir() {
9391
return 0, io.EOF
9492
}
9593
f.readerInit.Do(func() {
9694
cmd := fmt.Sprintf("dd if=%s skip=%d", shellescape.Quote(f.name), f.cursor)
9795
cmd = fmt.Sprintf("%s %s", cmd, "iflag=skip_bytes")
98-
f.reader, f.readerInitErr = f.c.Exec(cmd)
96+
f.reader, err = f.c.Exec(cmd)
9997
})
100-
if f.readerInitErr != nil {
101-
err = f.readerInitErr
98+
if err != nil {
99+
f.readerInit = &sync.Once{}
102100
return
103101
}
102+
f.reader.SetReadDeadline(time.Now().Add(5 * time.Second))
103+
defer f.reader.SetReadDeadline(time.Time{})
104104
n, err = f.reader.Read(p)
105105
f.cursor += int64(n)
106106
return
@@ -114,12 +114,14 @@ func (f *File) Write(p []byte) (n int, err error) {
114114
f.writerInit.Do(func() {
115115
cmd := fmt.Sprintf("dd of=%s seek=%d", shellescape.Quote(f.name), f.cursor)
116116
cmd = fmt.Sprintf("%s %s", cmd, "oflag=seek_bytes")
117-
f.writer, f.writerInitErr = f.c.Exec(cmd)
117+
f.writer, err = f.c.Exec(cmd)
118118
})
119-
if f.writerInitErr != nil {
120-
err = f.writerInitErr
119+
if err != nil {
120+
f.writerInit = &sync.Once{}
121121
return
122122
}
123+
f.writer.SetWriteDeadline(time.Now().Add(5 * time.Second))
124+
defer f.writer.SetWriteDeadline(time.Time{})
123125
n, err = f.writer.Write(p)
124126
f.cursor += int64(n)
125127
return
@@ -137,7 +139,7 @@ func (f *File) Seek(offset int64, whence int) (n int64, err error) {
137139
case io.SeekCurrent:
138140
f.cursor += offset
139141
case io.SeekEnd:
140-
stat := To1(f.Stat())
142+
stat := To1(f._Stat())
141143
f.cursor = stat.Size() + offset
142144
}
143145
n = f.cursor

bash/webdav/filesystem.go

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@ package webdav
33
import (
44
"context"
55
"fmt"
6-
"io/fs"
76
"os"
8-
"sync"
97

108
"github.com/alessio/shellescape"
11-
"github.com/jellydator/ttlcache/v3"
129
. "github.com/lainio/err2/try"
1310
"github.com/vscode-lcode/lcode/v2/util/err0"
1411
"golang.org/x/net/webdav"
@@ -38,7 +35,7 @@ func (c *Client) RemoveAll(ctx context.Context, name string) (err error) {
3835
defer span.End()
3936
defer err0.Record(&err, span)
4037

41-
defer c.statsLocker.DeleteAll()
38+
defer c.statsCache.DeleteAll()
4239

4340
cmd := fmt.Sprintf("rm -rf %s", shellescape.Quote(name))
4441
To(c.ExecNoreply(cmd))
@@ -49,8 +46,8 @@ func (c *Client) Rename(ctx context.Context, oldName, newName string) (err error
4946
defer span.End()
5047
defer err0.Record(&err, span)
5148

52-
defer c.statsLocker.Delete(oldName)
53-
defer c.statsLocker.Delete(newName)
49+
defer c.statsCache.Delete(oldName)
50+
defer c.statsCache.Delete(newName)
5451

5552
cmd := fmt.Sprintf("mv %s %s", shellescape.Quote(oldName), shellescape.Quote(newName))
5653
To(c.ExecNoreply(cmd))
@@ -62,37 +59,17 @@ func (c *Client) Stat(ctx context.Context, name string) (f os.FileInfo, err erro
6259
defer span.End()
6360
defer err0.Record(&err, span)
6461

65-
sl := c.StatLocker(name)
66-
sl.locker.RLock()
67-
f = sl.stat
68-
sl.locker.RUnlock()
69-
if f != nil {
62+
item := c.statsCache.Get(name)
63+
if item != nil {
64+
f = item.Value()
7065
return
7166
}
7267

73-
sl.locker.Lock()
74-
defer sl.locker.Unlock()
7568
f, err = OpenFile(c, name)._Stat()
7669
if err != nil {
7770
return
7871
}
79-
sl.stat = f
72+
c.statsCache.Set(name, f, 0)
8073

8174
return
8275
}
83-
84-
type StatWithLocker struct {
85-
locker *sync.RWMutex
86-
stat fs.FileInfo
87-
}
88-
89-
func (client *Client) StatLocker(name string) (sl *StatWithLocker) {
90-
item := client.statsLocker.Get(name)
91-
if item == nil {
92-
sl = &StatWithLocker{locker: &sync.RWMutex{}, stat: nil}
93-
client.statsLocker.Set(name, sl, ttlcache.DefaultTTL)
94-
} else {
95-
sl = item.Value()
96-
}
97-
return
98-
}

0 commit comments

Comments
 (0)