Fixed a couple of logic bugs.

This commit is contained in:
Nathan Osman 2016-04-30 22:32:35 -07:00
parent b233dd8e92
commit 8e53208882
2 changed files with 35 additions and 25 deletions

59
cache/livereader.go vendored
View File

@ -9,41 +9,29 @@ import (
// liveReader reads a file from disk, synchronizing reads with a downloader. // liveReader reads a file from disk, synchronizing reads with a downloader.
type liveReader struct { type liveReader struct {
downloader *downloader downloader *downloader
file *os.File dataFilename string
watcher *fsnotify.Watcher file *os.File
entry *Entry entry *Entry
done chan error done chan error
err error err error
eof bool eof bool
} }
// newLiveReader creates a reader from the provided downloader and data // newLiveReader creates a reader from the provided downloader and data
// file. fsnotify is used to watch for writes to the file to avoid using a // file. fsnotify is used to watch for writes to the file to avoid using a
// spinloop. Invoking this function assumes the existence of the data file. // spinloop. Invoking this function assumes the existence of the data file.
func newLiveReader(d *downloader, dataFilename string) (*liveReader, error) { func newLiveReader(d *downloader, dataFilename string) (*liveReader, error) {
f, err := os.Open(dataFilename)
if err != nil {
return nil, err
}
w, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
if err = w.Add(dataFilename); err != nil {
return nil, err
}
l := &liveReader{ l := &liveReader{
downloader: d, downloader: d,
file: f, dataFilename: dataFilename,
watcher: w, done: make(chan error),
done: make(chan error),
} }
go func() { go func() {
defer close(l.done) defer close(l.done)
l.done <- d.WaitForDone() l.done <- d.WaitForDone()
}() }()
return l, err return l, nil
} }
// Read attempts to read as much data as possible into the provided buffer. // Read attempts to read as much data as possible into the provided buffer.
@ -54,7 +42,25 @@ func (l *liveReader) Read(p []byte) (int, error) {
if l.err != nil { if l.err != nil {
return 0, l.err return 0, l.err
} }
if l.file == nil {
f, err := os.Open(l.dataFilename)
if err != nil {
l.err = err
return 0, l.err
}
l.file = f
}
bytesRead := 0 bytesRead := 0
watcher, err := fsnotify.NewWatcher()
if err != nil {
l.err = err
return 0, l.err
}
defer watcher.Close()
if err := watcher.Add(l.dataFilename); err != nil {
l.err = err
return 0, l.err
}
loop: loop:
for bytesRead < len(p) { for bytesRead < len(p) {
n, err := l.file.Read(p[bytesRead:]) n, err := l.file.Read(p[bytesRead:])
@ -66,7 +72,7 @@ loop:
} }
for { for {
select { select {
case e := <-l.watcher.Events: case e := <-watcher.Events:
if e.Op&fsnotify.Write != fsnotify.Write { if e.Op&fsnotify.Write != fsnotify.Write {
continue continue
} }
@ -83,7 +89,10 @@ loop:
// Close attempts to close the data file (if opened). // Close attempts to close the data file (if opened).
func (l *liveReader) Close() error { func (l *liveReader) Close() error {
return l.file.Close() if l.file != nil {
return l.file.Close()
}
return nil
} }
// GetEntry returns the Entry associated with the file, blocking until either // GetEntry returns the Entry associated with the file, blocking until either

View File

@ -56,6 +56,7 @@ func (s *Server) writeHeaders(w http.ResponseWriter, e *cache.Entry) {
func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if req.Method != "GET" { if req.Method != "GET" {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed) http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
} }
r, err := s.cache.GetReader(rewrite(req.RequestURI)) r, err := s.cache.GetReader(rewrite(req.RequestURI))
if err != nil { if err != nil {