added back anchor and selfheal broken chunks
This commit is contained in:
parent
fd035148bb
commit
6122768619
8 changed files with 65 additions and 44 deletions
|
|
@ -98,8 +98,12 @@ func (f *File) Read(p []byte) (n int, err error) {
|
|||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
if err == crypto.ErrDecrypt {
|
||||
log.V(2).Info("rereading to cache file", "err", err)
|
||||
return f.readToCache(p)
|
||||
}
|
||||
if err != nil {
|
||||
if !IsIOErr(err) && err != crypto.ErrDecrypt {
|
||||
if !IsIOErr(err) {
|
||||
log.Error(err, "error reading cache file")
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,13 +129,13 @@ const (
|
|||
func FileSize(s int64) string {
|
||||
switch {
|
||||
case s >= TiB:
|
||||
return strconv.Itoa(int(s/TiB)) + " TiB"
|
||||
return strconv.FormatFloat(float64(s)/TiB, 'f', 2, 64) + " TiB"
|
||||
case s >= GiB:
|
||||
return strconv.Itoa(int(s/GiB)) + " GiB"
|
||||
return strconv.FormatFloat(float64(s)/GiB, 'f', 2, 64) + " GiB"
|
||||
case s >= MiB:
|
||||
return strconv.Itoa(int(s/MiB)) + " MiB"
|
||||
return strconv.FormatFloat(float64(s)/MiB, 'f', 2, 64) + " MiB"
|
||||
case s >= KiB:
|
||||
return strconv.Itoa(int(s/KiB)) + " KiB"
|
||||
return strconv.FormatFloat(float64(s)/KiB, 'f', 2, 64) + " KiB"
|
||||
}
|
||||
return strconv.Itoa(int(s)) + " B"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,6 +381,7 @@ func (md *Metadata) close() (err error) {
|
|||
md.cancel()
|
||||
if md.wc != nil {
|
||||
close(md.wc)
|
||||
<-md.done
|
||||
md.wc = nil
|
||||
}
|
||||
if md.f != nil {
|
||||
|
|
@ -449,30 +450,27 @@ type writeAt struct {
|
|||
|
||||
func (md *Metadata) resetChans() {
|
||||
md.wc = make(chan writeAt, 10)
|
||||
md.done = make(chan struct{})
|
||||
}
|
||||
|
||||
func (md *Metadata) writer() {
|
||||
md.resetChans()
|
||||
md.err.Store(nil)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-md.ctx.Done():
|
||||
return
|
||||
case wa := <-md.wc:
|
||||
atomic.StoreInt64(&md.Atime, now())
|
||||
n, err := md.f.WriteAt(wa.data, wa.pos)
|
||||
if err == nil {
|
||||
md.addChunk(wa.pos, n)
|
||||
md.fs.q.Add(n)
|
||||
} else {
|
||||
md.err.Store(&mdErr{err})
|
||||
}
|
||||
if wa.ret != nil {
|
||||
streamingPool.Put(wa.ret)
|
||||
}
|
||||
for wa := range md.wc {
|
||||
atomic.StoreInt64(&md.Atime, now())
|
||||
n, err := md.f.WriteAt(wa.data, wa.pos)
|
||||
if err == nil {
|
||||
md.addChunk(wa.pos, n)
|
||||
md.fs.q.Add(n)
|
||||
} else {
|
||||
md.err.Store(&mdErr{err})
|
||||
}
|
||||
if wa.ret != nil {
|
||||
streamingPool.Put(wa.ret)
|
||||
}
|
||||
}
|
||||
close(md.done)
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ func (cs *CacheServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
h.Del("Last-Modified")
|
||||
|
||||
paths, err := i.GetPaths(p, cs.fs, true)
|
||||
paths, pathAnchor, err := i.GetPaths(p, cs.fs, true)
|
||||
if err == io.EOF {
|
||||
w.WriteHeader(i.Status())
|
||||
return
|
||||
|
|
@ -94,7 +94,7 @@ func (cs *CacheServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
h.Set(csp, indexCSP)
|
||||
|
||||
w.WriteHeader(i.Status())
|
||||
err = cache.Execute(w, data{Paths: paths})
|
||||
err = cache.Execute(w, data{Paths: paths, PathAnchor: pathAnchor})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -47,8 +47,9 @@ type dirContents struct {
|
|||
}
|
||||
|
||||
type dir struct {
|
||||
Name template.HTML
|
||||
URI template.HTML
|
||||
Name template.HTML
|
||||
URI template.HTML
|
||||
Anchor string
|
||||
}
|
||||
|
||||
type dirs []dir
|
||||
|
|
@ -96,7 +97,19 @@ func (r *responseInterceptor) Status() int {
|
|||
return r.status
|
||||
}
|
||||
|
||||
func (r *responseInterceptor) GetPaths(path string, filesystem *fs.FS, relative bool) (dc dirContents, err error) {
|
||||
func xmldecode(s string) string {
|
||||
s = strings.ReplaceAll(s, "&", "&")
|
||||
s = strings.ReplaceAll(s, "'", "'")
|
||||
return s
|
||||
}
|
||||
|
||||
func urlencode(s string) string {
|
||||
s = strings.ReplaceAll(s, "[", "%5B")
|
||||
s = strings.ReplaceAll(s, "]", "%5D")
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *responseInterceptor) GetPaths(path string, filesystem *fs.FS, relative bool) (dc dirContents, pa string, err error) {
|
||||
buf := r.buf.Bytes()
|
||||
buf = bytes.ReplaceAll(buf, []byte{'&'}, []byte("&"))
|
||||
err = xml.Unmarshal(buf, &dc)
|
||||
|
|
@ -105,19 +118,20 @@ func (r *responseInterceptor) GetPaths(path string, filesystem *fs.FS, relative
|
|||
}
|
||||
dc.Base = path
|
||||
path = strings.TrimSuffix(path, "/")
|
||||
pa = "#" + anchor(path)
|
||||
for _, p := range dc.AllPaths {
|
||||
p = strings.ReplaceAll(p, "&", "&")
|
||||
p = strings.ReplaceAll(p, "'", "'")
|
||||
p = xmldecode(p)
|
||||
name := template.HTML(p)
|
||||
full := path + "/" + p
|
||||
uri := template.HTML(full)
|
||||
uri := template.HTML(urlencode(full))
|
||||
if relative {
|
||||
uri = template.HTML(p)
|
||||
uri = template.HTML(urlencode(p))
|
||||
}
|
||||
if p[len(p)-1] == '/' {
|
||||
dc.Dirs = append(dc.Dirs, dir{
|
||||
Name: name,
|
||||
URI: uri,
|
||||
Name: name,
|
||||
URI: uri,
|
||||
Anchor: pathAnchor(p),
|
||||
})
|
||||
} else {
|
||||
dc.Files = append(dc.Files, file{
|
||||
|
|
@ -139,7 +153,7 @@ func getPreloads(path string, filesystem *fs.FS) (dc dirContents) {
|
|||
for _, p := range filesystem.Preloads() {
|
||||
dc.Files = append(dc.Files, file{
|
||||
Name: template.HTML(p.Name),
|
||||
URI: template.HTML(p.Name),
|
||||
URI: template.HTML(urlencode(p.Name)),
|
||||
Size: fs.FileSize(p.Size),
|
||||
Rate: p.Rate(),
|
||||
Status: p.Status,
|
||||
|
|
@ -151,6 +165,10 @@ func getPreloads(path string, filesystem *fs.FS) (dc dirContents) {
|
|||
return
|
||||
}
|
||||
|
||||
func pathAnchor(s string) string {
|
||||
return anchor(strings.TrimSuffix(s, "/"))
|
||||
}
|
||||
|
||||
func anchor(s string) string {
|
||||
if i := strings.LastIndex(s, "/"); i > 0 && i+1 < len(s) {
|
||||
s = s[i+1:]
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ const (
|
|||
)
|
||||
|
||||
type data struct {
|
||||
QuotaCur float64
|
||||
QuotaMax float64
|
||||
Paths dirContents
|
||||
QuotaCur float64
|
||||
QuotaMax float64
|
||||
Paths dirContents
|
||||
PathAnchor string
|
||||
}
|
||||
|
||||
type FileServer struct {
|
||||
|
|
@ -136,7 +137,7 @@ func (fs *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
h.Del("Last-Modified")
|
||||
|
||||
paths, err := i.GetPaths(p, fs.fs, false)
|
||||
paths, pathAnchor, err := i.GetPaths(p, fs.fs, false)
|
||||
if err == io.EOF {
|
||||
w.WriteHeader(i.Status())
|
||||
return
|
||||
|
|
@ -148,7 +149,7 @@ func (fs *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
h.Set(csp, indexCSP)
|
||||
|
||||
w.WriteHeader(i.Status())
|
||||
err = index.Execute(w, data{Paths: paths})
|
||||
err = index.Execute(w, data{Paths: paths, PathAnchor: pathAnchor})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
<a href="/?o=preloads">[Preloads]</a></pre>
|
||||
<table>
|
||||
<tr class="listitem">
|
||||
<td class="listpath up"><a href="../">../</a></td>
|
||||
<td class="listpath up"><a href="../{{.PathAnchor}}">../</a></td>
|
||||
<td class="listoptions">[dir]</td>
|
||||
</tr>
|
||||
<tr class="spacer"><td colspan="2"></td></tr>
|
||||
{{range $s := .Paths.Dirs -}}
|
||||
<tr class="listitem">
|
||||
<td class="listpath"><a href="{{$s.URI}}">{{$s.Name}}</a></td>
|
||||
<td class="listpath"><a id="{{$s.Anchor}}" href="{{$s.URI}}">{{$s.Name}}</a></td>
|
||||
<td class="listoptions">[dir]</td>
|
||||
</tr>
|
||||
<tr class="spacer"><td colspan="2"></td></tr>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue