From e732909773760e28a68e5293cefa5ef9d4ec2c6c Mon Sep 17 00:00:00 2001 From: Las Zenow Date: Thu, 22 Jan 2015 21:16:20 -0600 Subject: [PATCH] Use io.readerAt to open the books without loading everything in memory --- reader.go | 64 +++++++++++++++++++++++++++------------------- storage/storage.go | 8 +++++- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/reader.go b/reader.go index 0882a3c..8254180 100644 --- a/reader.go +++ b/reader.go @@ -3,16 +3,13 @@ package main import ( log "github.com/cihub/seelog" - "bytes" "io" - "io/ioutil" "net/http" "strconv" "strings" "git.gitorious.org/go-pkg/epubgo.git" "git.gitorious.org/trantor/trantor.git/database" - "git.gitorious.org/trantor/trantor.git/storage" "github.com/gorilla/mux" ) @@ -183,13 +180,24 @@ func openReadEpub(h handler) (*epubgo.Epub, database.Book) { if err != nil { return nil, book } - if !book.Active { if !h.sess.IsAdmin() { return nil, book } } - e, err := openBook(book.Id, h.store) + + f, err := h.store.Get(book.Id, EPUB_FILE) + if err != nil { + return nil, book + } + defer f.Close() + + info, err := f.Stat() + if err != nil { + return nil, book + } + + e, err := epubgo.Load(f, info.Size()) if err != nil { return nil, book } @@ -205,42 +213,46 @@ func contentHandler(h handler) { return } - book, err := h.db.GetBookId(id) + err := openEpubFile(h, id, file) if err != nil { notFound(h) return } +} + +func openEpubFile(h handler, id string, file string) error { + book, err := h.db.GetBookId(id) + if err != nil { + return err + } if !book.Active { if !h.sess.IsAdmin() { - notFound(h) - return + return err } } - e, err := openBook(book.Id, h.store) + + f, err := h.store.Get(id, EPUB_FILE) if err != nil { - notFound(h) - return + return err + } + defer f.Close() + + info, err := f.Stat() + if err != nil { + return err + } + + e, err := epubgo.Load(f, info.Size()) + if err != nil { + return err } defer e.Close() html, err := e.OpenFile(file) if err != nil { - notFound(h) - return + return err } defer html.Close() io.Copy(h.w, html) -} - -func openBook(id string, store *storage.Store) (*epubgo.Epub, error) { - f, err := store.Get(id, EPUB_FILE) - if err != nil { - return nil, err - } - defer f.Close() - - buff, err := ioutil.ReadAll(f) - reader := bytes.NewReader(buff) - - return epubgo.Load(reader, int64(len(buff))) + return nil } diff --git a/storage/storage.go b/storage/storage.go index b5f0ba0..531d39d 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -11,6 +11,12 @@ type Store struct { path string } +type File interface { + io.ReadCloser + io.ReaderAt + Stat() (fi os.FileInfo, err error) +} + func Init(path string) (*Store, error) { st := new(Store) st.path = path @@ -42,7 +48,7 @@ func (st *Store) Store(id string, file io.Reader, name string) (size int64, err return io.Copy(dest, file) } -func (st *Store) Get(id string, name string) (io.ReadCloser, error) { +func (st *Store) Get(id string, name string) (File, error) { path := idPath(st.path, id) return os.Open(p.Join(path, name)) }