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  }