func (i ImageSource) searchRootsInternal(filename string, visitPath, visitURL func(string) error) (err error) { if len(i.roots) == 0 && len(i.webroots) == 0 { logging.Debug("No roots") err = os.ErrNotExist return } // Search requested image from all roots by trial and error for _, root := range i.roots { // TODO: Fix escape vulnerability (sanitize filename from at least ".." etc) err = visitPath(filepath.Join(root, filename)) if err == nil { return } } for _, root := range i.webroots { logging.Debugf("Attempting to load %s", root+filename) err = visitURL(root + filename) if err == nil { return } } return }
// Takes the caching policy and the maximum size of the cache in bytes. func NewCache(policy Policy, mm uint64) *Cache { logging.Debugf("Cache create: mem:%v", mm) return &Cache{ maxMemory: mm, policy: policy, storer: make(MemoryStore), } }
func TestPingRoots(t *testing.T) { logging.Debugf("Testing PingRoots...") is := MakeImageSource() err := is.AddRoot("../") if err != nil { t.Fatal(err) } img := images.NewImage() defer img.Destroy() t0 := time.Now() err = is.searchRoots("testimages/loadimage/22.jpg", img) if err != nil { t.Fatal(err) } t1 := time.Now().Sub(t0) img = images.NewImage() defer img.Destroy() t0 = time.Now() err = is.pingRoots("testimages/loadimage/22.jpg", img) if err != nil { t.Fatal(err) } t2 := time.Now().Sub(t0) img = images.NewImage() defer img.Destroy() t0 = time.Now() err = is.searchRoots("testimages/loadimage/22.jpg", img) if err != nil { t.Fatal(err) } t3 := time.Now().Sub(t0) logging.Debugf("searchRoots #1: %v, pingRoots: %v, searchRoots #2: %v", t1, t2, t3) if t1 < t2 { t.Fatal(fmt.Sprintf("pingRoots is slower than searchRoots! pingRoots: %v, searchRoots: %v", t2, t1)) } if t3 < t2 { t.Fatal(fmt.Sprintf("pingRoots is slower than searchRoots! pingRoots: %v, searchRoots: %v", t2, t3)) } return }
// Gets an image blob of requested dimensions func (c *Cache) GetBlob(key string) (blob []byte, found bool) { b64 := stringToBase64(key) logging.Debugf("Cache get with key: %v", b64) c.RLock() blob, found = c.storer.Load(key) c.RUnlock() if found { logging.Debugf("Cache found: %v", b64) c.policy.Visit(key) } else { logging.Debugf("Cache not found: %v", b64) } return }
func (c *Cache) AddBlob(key string, blob []byte) { size := uint64(len(blob)) if size > c.maxMemory { return } logging.Debugf("Cache add: %v", stringToBase64(key)) // This is the only point where the cache is mutated. // While this runs the there can be no reads from the storer. c.Lock() defer c.Unlock() for c.currentMemory+size > c.maxMemory { c.deleteOne() } c.policy.Push(key) c.currentMemory += uint64(len(blob)) c.storer.Store(key, blob) }
func (c *Cache) deleteOne() { to_delete := c.policy.Pop() logging.Debugf("Cache delete: %v", stringToBase64(to_delete)) c.currentMemory -= c.storer.Delete(to_delete) }
func (r LiquidRescale) Apply(img images.Image) error { logging.Debugf("Liquid rescaling image to: %v, %v", r.Width, r.Height) // The third argument to LiquidRescaleImage is the maximum transversal step, or how many pixels a seam can move sideways. // The fourth is the rigidity, which makes seams less steep. Recommended if transversal step is greater than one. return img.LiquidRescaleImage(uint(r.Width), uint(r.Height), 1, 0) }
func (c Crop) Apply(img images.Image) error { logging.Debugf("Crop image to: %d, %d with offset: %d, %d", c.Width, c.Height, c.X, c.Y) return img.Crop(c.Width, c.Height, c.X, c.Y) }