From d6ceac0a532f03c44a76d62385dfb985df31be43 Mon Sep 17 00:00:00 2001 From: Nathan Osman Date: Sun, 24 Apr 2016 00:32:32 -0700 Subject: [PATCH] Added some initial code. --- entry.go | 35 +++++++++++++++++++++++++++++++++++ storage.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 entry.go create mode 100644 storage.go diff --git a/entry.go b/entry.go new file mode 100644 index 0000000..d0a88a0 --- /dev/null +++ b/entry.go @@ -0,0 +1,35 @@ +package main + +import ( + "encoding/json" + "os" +) + +// Entry represents a file in storage. +type Entry struct { + URL string `json:"url"` + ContentLength int64 `json:"content_length"` + ContentType string `json:"content_type"` +} + +// LoadEntry loads an entry from disk. +func LoadEntry(filename string) (*Entry, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + e := &Entry{} + if err = json.NewDecoder(f).Decode(e); err != nil { + return nil, err + } + return e, nil +} + +// Save writes the entry to disk. +func (e *Entry) Save(filename string) error { + f, err := os.Create(filename) + if err != nil { + return err + } + return json.NewEncoder(f).Encode(e) +} diff --git a/storage.go b/storage.go new file mode 100644 index 0000000..4e74936 --- /dev/null +++ b/storage.go @@ -0,0 +1,39 @@ +package main + +import ( + "crypto/md5" + "fmt" + "io" + "os" + "path" + "sync" +) + +// Storage provides read and write access to items in the cache. In order to +// avoid race conditions, adding and testing for entries in the cache are +// protected by a mutex. +type Storage struct { + Directory string + mutex sync.Mutex +} + +// GetReader returns an io.Reader for the specified URL. If the file does not +// exist, both a writer (for downloading the file) and a reader are created. +func (s *Storage) GetReader(url string) (io.Reader, error) { + var ( + hash = string(md5.Sum([]byte(url))) + jsonFilename = path.Join(s.Directory, fmt.Sprintf("%s.json", hash)) + dataFilename = path.Join(s.Directory, fmt.Sprintf("%s.data", hash)) + ) + s.mutex.Lock() + defer s.mutex.Unlock() + i, err := os.Stat(jsonFilename) + if err != nil { + if os.IsNotExist(err) { + NewWriter(url, jsonFilename, dataFilename) + } else { + return nil, err + } + } + return NewReader(url, jsonFilename, dataFilename) +}