]> Sergey Matveev's repositories - btrtrc.git/blob - fs/file_handle.go
Fixes for wasm
[btrtrc.git] / fs / file_handle.go
1 package torrentfs
2
3 import (
4         "context"
5         "io"
6
7         "bazil.org/fuse"
8         "bazil.org/fuse/fs"
9         "github.com/anacrolix/missinggo/v2"
10         "github.com/anacrolix/torrent"
11 )
12
13 type fileHandle struct {
14         fn fileNode
15         r  torrent.Reader
16 }
17
18 var _ interface {
19         fs.HandleReader
20         fs.HandleReleaser
21 } = fileHandle{}
22
23 func (me fileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
24         torrentfsReadRequests.Add(1)
25         if req.Dir {
26                 panic("read on directory")
27         }
28         r := me.r
29         pos, err := r.Seek(req.Offset, io.SeekStart)
30         if err != nil {
31                 panic(err)
32         }
33         if pos != req.Offset {
34                 panic("seek failed")
35         }
36         resp.Data = resp.Data[:req.Size]
37         readDone := make(chan struct{})
38         ctx, cancel := context.WithCancel(ctx)
39         var readErr error
40         go func() {
41                 defer close(readDone)
42                 me.fn.FS.mu.Lock()
43                 me.fn.FS.blockedReads++
44                 me.fn.FS.event.Broadcast()
45                 me.fn.FS.mu.Unlock()
46                 var n int
47                 r := missinggo.ContextedReader{r, ctx}
48                 //log.Printf("reading %v bytes at %v", len(resp.Data), req.Offset)
49                 if true {
50                         // A user reported on that on freebsd 12.2, the system requires that reads are
51                         // completely filled. Their system only asks for 64KiB at a time. I've seen systems that
52                         // can demand up to 16MiB at a time, so this gets tricky. For now, I'll restore the old
53                         // behaviour from before 2a7352a, which nobody reported problems with.
54                         n, readErr = io.ReadFull(r, resp.Data)
55                 } else {
56                         n, readErr = r.Read(resp.Data)
57                         if readErr == io.EOF {
58                                 readErr = nil
59                         }
60                 }
61                 resp.Data = resp.Data[:n]
62         }()
63         defer func() {
64                 <-readDone
65                 me.fn.FS.mu.Lock()
66                 me.fn.FS.blockedReads--
67                 me.fn.FS.event.Broadcast()
68                 me.fn.FS.mu.Unlock()
69         }()
70         defer cancel()
71
72         select {
73         case <-readDone:
74                 return readErr
75         case <-me.fn.FS.destroyed:
76                 return fuse.EIO
77         case <-ctx.Done():
78                 return fuse.EINTR
79         }
80 }
81
82 func (me fileHandle) Release(context.Context, *fuse.ReleaseRequest) error {
83         return me.r.Close()
84 }