go-hep.org/x/hep@v0.38.1/groot/riofs/plugin/http/rcache.go (about) 1 // Copyright ©2022 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package http 6 7 import ( 8 "io" 9 "os" 10 "sync" 11 12 "golang.org/x/sync/errgroup" 13 ) 14 15 type reader interface { 16 io.Reader 17 io.ReaderAt 18 io.Closer 19 } 20 21 type store interface { 22 io.Reader 23 io.ReaderAt 24 io.Writer 25 io.WriterAt 26 io.Closer 27 28 Name() string 29 } 30 31 type rcache struct { 32 r reader 33 o store 34 35 mu sync.RWMutex 36 sps spans 37 } 38 39 func rcacheOf(r reader) (*rcache, error) { 40 f, err := os.CreateTemp("", "riofs-remote-") 41 if err != nil { 42 return nil, err 43 } 44 45 return &rcache{r: r, o: f}, nil 46 } 47 48 func (r *rcache) Close() error { 49 e1 := r.r.Close() 50 e2 := r.o.Close() 51 _ = os.RemoveAll(r.o.Name()) 52 if e1 != nil { 53 return e1 54 } 55 return e2 56 } 57 58 func (r *rcache) Read(p []byte) (int, error) { 59 return r.r.Read(p) 60 } 61 62 func (r *rcache) ReadAt(p []byte, off int64) (int, error) { 63 sp := span{off: off, len: int64(len(p))} 64 oo := r.split(sp) 65 if len(oo) == 0 { 66 return r.o.ReadAt(p, off) 67 } 68 var ( 69 grp errgroup.Group 70 ii int64 71 ) 72 for i := range oo { 73 spa := oo[i] 74 beg := ii 75 end := ii + spa.len 76 ii = end 77 grp.Go(func() error { 78 return r.fetch(p[beg:end], spa) 79 }) 80 } 81 82 err := grp.Wait() 83 if err != nil { 84 return 0, err 85 } 86 87 return r.o.ReadAt(p, off) 88 } 89 90 func (r *rcache) split(sp span) []span { 91 r.mu.RLock() 92 defer r.mu.RUnlock() 93 94 return split(sp, r.sps) 95 } 96 97 func (r *rcache) fetch(p []byte, sp span) error { 98 _, err := r.r.ReadAt(p, sp.off) 99 if err != nil { 100 return err 101 } 102 _, err = r.o.WriteAt(p, sp.off) 103 if err != nil { 104 return err 105 } 106 r.mu.Lock() 107 defer r.mu.Unlock() 108 109 r.sps.add(sp) 110 return nil 111 }