コード例 #1
0
ファイル: groupcacheDemo.go プロジェクト: fengzai/snippet
func main() {
	var err error
	p = groupcache.NewHTTPPool("http://127.0.0.1:50000")
	// update p's list
	p.Set("http://127.0.0.1:50001", "http://127.0.0.1:50002")

	// create a new group by name and set a function for get a value by key
	// if you g.Get KEY at first time, it will store the value use sink, run the function
	// if you g.Get KEY not at first time, actually it NOT entry the function
	// does not support update a key's value
	g = groupcache.NewGroup("dns", 64<<20, groupcache.GetterFunc(
		func(ctx groupcache.Context, key string, dest groupcache.Sink) (err error) {
			if ctx == nil {
				ctx = "f**k"
			}
			log.Println(key, ctx)
			err = dest.SetString(ctx.(string))
			return
		}))

	// let it listen
	go http.ListenAndServe("127.0.0.1:50000", nil)

	// get a key's value into data

	time.Sleep(2 * time.Second)
	var data []byte
	var key = "key"
	err = g.Get("aa", key, groupcache.AllocatingByteSliceSink(&data))
	if err != nil {
		log.Println("get error:", err)
	}
	log.Println(string(data))

	time.Sleep(2 * time.Second)
	key = "key1"
	err = g.Get("bb", key, groupcache.AllocatingByteSliceSink(&data))
	if err != nil {
		log.Println("get error:", err)
	}
	log.Println(string(data))

	time.Sleep(2 * time.Second)
	key = "key"
	err = g.Get("cc", key, groupcache.AllocatingByteSliceSink(&data))
	if err != nil {
		log.Println("get error:", err)
	}
	log.Println(string(data))
}
コード例 #2
0
ファイル: handler.go プロジェクト: foresmac/vip
func handleImageRequest(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(http.StatusMethodNotAllowed)
	}

	w.Header().Set("Cache-Control", "public, max-age=31536000")

	// Client is checking for a cached URI, assume it is valid
	// and return a 304
	if r.Header.Get("If-Modified-Since") != "" {
		w.WriteHeader(http.StatusNotModified)
		return
	}

	gc := fetch.RequestContext(r)

	var data []byte
	err := cache.Get(gc, gc.CacheKey(), groupcache.AllocatingByteSliceSink(&data))
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}

	w.Header().Set("Content-Type", http.DetectContentType(data))
	http.ServeContent(w, r, gc.ImageId, time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), bytes.NewReader(data))
}
コード例 #3
0
ファイル: groupcache.go プロジェクト: dylanpoe/golang.org
func main() {
	// STARTINIT OMIT
	me := "http://10.0.0.1"
	peers := groupcache.NewHTTPPool(me)

	// Whenever peers change:
	peers.Set("http://10.0.0.1", "http://10.0.0.2", "http://10.0.0.3")
	// ENDINIT OMIT

	// STARTGROUP OMIT
	var thumbNails = groupcache.NewGroup("thumbnail", 64<<20, groupcache.GetterFunc(
		func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
			fileName := key
			dest.SetBytes(generateThumbnail(fileName))
			return nil
		}))
	// ENDGROUP OMIT

	var ctx groupcache.Context
	var w http.ResponseWriter
	var r *http.Request

	// STARTUSE OMIT
	var data []byte
	err := thumbNails.Get(ctx, "big-file.jpg",
		groupcache.AllocatingByteSliceSink(&data))
	// ...
	_ = err               // OMIT
	var modTime time.Time // OMIT
	http.ServeContent(w, r, "big-file-thumb.jpg", modTime, bytes.NewReader(data))
	// ENDUSE OMIT
}
コード例 #4
0
func main() {
	me := ":" + os.Args[1]
	peers := groupcache.NewHTTPPool("http://localhost" + me)
	peers.Set("http://localhost:8081", "http://localhost:8082",
		"http://localhost:8083")
	helloworld := groupcache.NewGroup("helloworld",
		1024*1024*10, groupcache.GetterFunc(
			func(ctx groupcache.Context,
				key string,
				dest groupcache.Sink) error {
				log.Println(me)
				dest.SetString(me + "->" + key)
				return nil
			}))
	fmt.Println("GroupName: ", helloworld.Name())
	http.HandleFunc("/xbox/", func(w http.ResponseWriter, r *http.Request) {
		parts := strings.SplitN(r.URL.Path[len("/xbox/"):], "/", 1)
		for _, x := range parts {
			fmt.Println("get: ", x)
		}
		if len(parts) != 1 {
			http.Error(w, "Bad Request", http.StatusBadRequest)
			return
		}
		var data []byte
		helloworld.Get(nil, parts[0], groupcache.AllocatingByteSliceSink(&data))
		w.Write(data)
		log.Println("Gets: ", helloworld.Stats.Gets.String())
		log.Println("Load: ", helloworld.Stats.Loads.String())
		log.Println("LocalLoad: ", helloworld.Stats.LocalLoads.String())
		log.Println("PeerError: ", helloworld.Stats.PeerErrors.String())
		log.Println("PeerLoad: ", helloworld.Stats.PeerLoads.String())
	})
	http.ListenAndServe(me, nil)
}
コード例 #5
0
func main() {
	// STARTINIT OMIT
	me := "http://127.0.0.1:11211"
	peers := groupcache.NewHTTPPool(me)

	// Whenever peers change:
	peers.Set("http://127.0.0.1:11211")
	// ENDINIT OMIT

	// STARTGROUP OMIT
	var thumbNails = groupcache.NewGroup("thumbnail", 64<<20, groupcache.GetterFunc(
		func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
			dest.SetBytes(generateThumbnail(key))
			return nil
		}))
	// ENDGROUP OMIT

	var ctx groupcache.Context

	// STARTUSE OMIT
	var data []byte
	thumbNails.Get(ctx, "big-file.jpg", groupcache.AllocatingByteSliceSink(&data))

	fmt.Println(string(data))
}
コード例 #6
0
func resultFromCache(siteURL string) ([]Icon, error) {
	if iconCache == nil {
		return FetchIcons(siteURL)
	}

	// Let results expire after a day
	now := time.Now()
	key := fmt.Sprintf("%d-%02d-%02d-%s", now.Year(), now.Month(), now.Day(), siteURL)
	var data []byte
	err := iconCache.Get(siteURL, key, groupcache.AllocatingByteSliceSink(&data))
	if err != nil {
		logger.Println("ERR:", err)
		return FetchIcons(siteURL)
	}

	res := &result{}
	err = json.Unmarshal(data, res)
	if err != nil {
		panic(err)
	}

	if res.Error != "" {
		return res.Icons, errors.New(res.Error)
	}
	return res.Icons, nil
}
コード例 #7
0
ファイル: handler.go プロジェクト: applepi-icpc/ggfetch
func (g *GGFetchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	method := r.URL.Path[1:]
	key := r.URL.RawQuery
	log.Println("METHOD", method, "KEY", key)
	hi, ok := g.methods[method]
	if !ok {
		http.NotFound(w, r)
		return
	}

	buf := make([]byte, 0)
	if err := hi.Group.Get(nil, key, groupcache.AllocatingByteSliceSink(&buf)); err != nil {
		log.Println("ERROR", err, "METHOD", method, "KEY", key)
		var statusCode int
		switch err {
		case image.ErrFormat, io.ErrUnexpectedEOF:
			statusCode = http.StatusBadRequest
		default:
			statusCode = http.StatusInternalServerError
		}
		http.Error(w, err.Error(), statusCode)
		return
	}
	if err := hi.Fetcher.WriteResponse(w, buf); err != nil {
		log.Println("ERROR", err, "METHOD", method, "KEY", key)
	}
}
コード例 #8
0
func (c *DimensionsCache) Get(url *url.URL) (d Dimensions, err error) {
	var data []byte
	c.group.Get(nil, url.String(), groupcache.AllocatingByteSliceSink(&data))

	d = Dimensions{}
	err = binary.Read(bytes.NewReader(data), binary.BigEndian, &d)
	return d, err
}
コード例 #9
0
func (s *Frontend) Get(args *api.Load, reply *api.ValueResult) error {
	var data []byte
	fmt.Printf("cli asked for %s from groupcache\n", args.Key)
	err := s.cacheGroup.Get(nil, args.Key,
		groupcache.AllocatingByteSliceSink(&data))

	reply.Value = string(data)
	return err
}
コード例 #10
0
func (this *GroupCacheKvStorage) Get(key interface{}) (interface{}, error) {
	var data []byte
	this.CacheGroup.Get(nil, key.(string), groupcache.AllocatingByteSliceSink(&data))
	object, err := bytesToInterface(data, this.T)
	if err != nil {
		return nil, err
	}
	return object, nil
}
コード例 #11
0
ファイル: hotpotato.go プロジェクト: ryanbressler/HotPotatoFS
func (f File) ReadAll(intr fs.Intr) ([]byte, fuse.Error) {
	var contents []byte
	err := filecache.Get(nil, f.Path, groupcache.AllocatingByteSliceSink(&contents))
	if err != nil {
		log.Print(err)
		return nil, fuse.ENOENT
	}
	return contents, nil
}
コード例 #12
0
func TestGetterErrorContextType(t *testing.T) {
	var data []byte
	dest := groupcache.AllocatingByteSliceSink(&data)
	gt := &Getter{
		Server: &imageserver.StaticServer{
			Image: testdata.Medium,
		},
	}
	err := gt.Get("invalid", "foo", dest)
	if err == nil {
		t.Fatal("no error")
	}
}
コード例 #13
0
func TestGetterErrorContextType(t *testing.T) {
	var data []byte
	dest := groupcache.AllocatingByteSliceSink(&data)
	gt := &Getter{
		Server: imageserver.ServerFunc(func(params imageserver.Params) (*imageserver.Image, error) {
			return testdata.Medium, nil
		}),
	}
	err := gt.Get("invalid", "foo", dest)
	if err == nil {
		t.Fatal("no error")
	}
}
コード例 #14
0
ファイル: gc1.go プロジェクト: samuelyao314/mygo
func console() {
	scanner := bufio.NewScanner(os.Stdin)
	quit := false

	for !quit {
		fmt.Print("gc> ")

		if !scanner.Scan() {
			break
		}

		line := scanner.Text()
		parts := strings.Split(line, " ")
		cmd := parts[0]
		args := parts[1:]

		switch cmd {
		case "peers":
			pool.Set(args...)
		case "stats":
			stats := dns.CacheStats(groupcache.MainCache)
			fmt.Println("Bytes:    ", stats.Bytes)
			fmt.Println("Items:    ", stats.Items)
			fmt.Println("Gets:     ", stats.Gets)
			fmt.Println("Hits:     ", stats.Hits)
			fmt.Println("Evictions:", stats.Evictions)
		case "get":
			var data []byte
			err := dns.Get(nil, args[0],
				groupcache.AllocatingByteSliceSink(&data))

			if err != nil {
				fmt.Println("get error:", err)
				continue
			}

			fmt.Print(args[0], ":")
			io.Copy(os.Stdout, bytes.NewReader(data))
			fmt.Println()
		case "quit":
			quit = true
		default:
			fmt.Println("unrecognized command:", cmd, args)
		}

	}

	if err := scanner.Err(); err != nil {
		fmt.Println("reading stdin:", err)
	}
}
コード例 #15
0
ファイル: main.go プロジェクト: pombredanne/CodeSnippet
// handler handles all incoming requests for a definition.
func handler(w http.ResponseWriter, r *http.Request) {
	log.Println("received request:", r.Method, r.URL.Path)
	word := strings.Trim(path.Base(r.URL.Path), "/")

	// Get the definition from groupcache and write it out.
	var data []byte
	err := dict.Get(nil, word, groupcache.AllocatingByteSliceSink(&data))
	if err != nil {
		log.Println("retreiving definition for", word, "-", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	io.Copy(w, bytes.NewReader(data))
}
コード例 #16
0
func TestGetterErrorSink(t *testing.T) {
	ctx := &Context{
		Params: imageserver.Params{},
	}
	dest := groupcache.AllocatingByteSliceSink(nil)
	gt := &Getter{
		Server: &imageserver.StaticServer{
			Image: testdata.Medium,
		},
	}
	err := gt.Get(ctx, "foo", dest)
	if err == nil {
		t.Fatal("no error")
	}
}
コード例 #17
0
func TestGetterErrorSink(t *testing.T) {
	ctx := &Context{
		Params: imageserver.Params{},
	}
	dest := groupcache.AllocatingByteSliceSink(nil)
	gt := &Getter{
		Server: imageserver.ServerFunc(func(params imageserver.Params) (*imageserver.Image, error) {
			return testdata.Medium, nil
		}),
	}
	err := gt.Get(ctx, "foo", dest)
	if err == nil {
		t.Fatal("no error")
	}
}
コード例 #18
0
func TestGetterErrorServer(t *testing.T) {
	ctx := &Context{
		Params: imageserver.Params{},
	}
	var data []byte
	dest := groupcache.AllocatingByteSliceSink(&data)
	gt := &Getter{
		Server: imageserver.ServerFunc(func(params imageserver.Params) (*imageserver.Image, error) {
			return nil, fmt.Errorf("error")
		}),
	}
	err := gt.Get(ctx, "foo", dest)
	if err == nil {
		t.Fatal("no error")
	}
}
コード例 #19
0
ファイル: gcgrpcpool.go プロジェクト: charithe/gcgrpcpool
func (gp *GRPCPool) Retrieve(ctx context.Context, req *gcgrpc.RetrieveRequest) (*gcgrpc.RetrieveResponse, error) {
	group := groupcache.GetGroup(req.Group)
	if group == nil {
		log.Warnf("Unable to find group [%s]", req.Group)
		return nil, fmt.Errorf("Unable to find group [%s]", req.Group)
	}
	group.Stats.ServerRequests.Add(1)
	var value []byte
	err := group.Get(ctx, req.Key, groupcache.AllocatingByteSliceSink(&value))
	if err != nil {
		log.WithError(err).Warnf("Failed to retrieve [%s]", req)
		return nil, fmt.Errorf("Failed to retrieve [%s]: %v", req, err)
	}

	return &gcgrpc.RetrieveResponse{Value: value}, nil
}
コード例 #20
0
func TestGetterErrorServer(t *testing.T) {
	ctx := &Context{
		Params: imageserver.Params{},
	}
	var data []byte
	dest := groupcache.AllocatingByteSliceSink(&data)
	gt := &Getter{
		Server: &imageserver.StaticServer{
			Error: fmt.Errorf("error"),
		},
	}
	err := gt.Get(ctx, "foo", dest)
	if err == nil {
		t.Fatal("no error")
	}
}
コード例 #21
0
ファイル: main.go プロジェクト: gnanderson/imagio
func main() {
	dumpcfg := flag.Bool("dumpcfg", false, "Dump config.")

	flag.Usage = func() {
		fmt.Fprintf(os.Stdout, "Usage: %s [OPTIONS]\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.Parse()

	if *dumpcfg {
		config.Get().DumpCfg()
		os.Exit(0)
	}

	initCacheGroup()

	log.Printf("Service listen on %v\n", config.Get().Listen())

	http.HandleFunc("/",
		func(w http.ResponseWriter, r *http.Request) {
			var data []byte
			var ctx groupcache.Context

			cacheGroup.Get(ctx, r.URL.String(), groupcache.AllocatingByteSliceSink(&data))

			http.ServeContent(w, r, r.URL.String(), time.Now(), bytes.NewReader(data))
		},
	)

	http.HandleFunc("/nocache",
		func(w http.ResponseWriter, r *http.Request) {
			var result []byte
			result = imgproc.Do(Construct(new(query.Options), r.URL).(*query.Options))
			w.Write(result)
		},
	)

	http.HandleFunc("/stat",
		func(w http.ResponseWriter, r *http.Request) {
			// awesome stat. not implemented yet.
		},
	)

	log.Fatal(http.ListenAndServe(config.Get().Listen(), nil))
}
コード例 #22
0
ファイル: views.go プロジェクト: thraxil/reticulum
func ServeImageHandler(w http.ResponseWriter, r *http.Request, ctx Context) {
	ri, handled := parsePathServeImage(w, r, ctx)
	if handled {
		return
	}

	var data []byte
	err := ctx.Cluster.Imagecache.Get(nil, ri.String(),
		groupcache.AllocatingByteSliceSink(&data))
	if err == nil {
		w = setCacheHeaders(w, ri.Extension)
		w.Write(data)
		return
	}

	if ctx.serveDirect(ri, w) {
		return
	}

	if !ctx.haveImageFullsizeLocally(ri) {
		ctx.serveFromCluster(ri, w)
		return
	}

	// we do have the full-size, but not the scaled one
	// so resize it, cache it, and serve it.
	if !ctx.locallyWriteable() {
		// but first, make sure we are writeable. If not,
		// we need to let another node in the cluster handle it.
		ctx.serveScaledFromCluster(ri, w)
		return
	}

	result := ctx.makeResizeJob(ri)
	if !result.Success {
		http.Error(w, "could not resize image", 500)
		return
	}
	if result.Magick {
		// imagemagick did the resize, so we just spit out
		// the sized file
		ctx.serveMagick(ri, w)
		return
	}
	ctx.serveScaledByExtension(ri, w, *result.OutputImage)
}
コード例 #23
0
ファイル: groupcache.go プロジェクト: cautio/imageserver
// Get implements Server.
func (srv *Server) Get(params imageserver.Params) (*imageserver.Image, error) {
	ctx := &Context{
		Params: params,
	}
	key := srv.KeyGenerator.GetKey(params)
	var data []byte
	dest := groupcache.AllocatingByteSliceSink(&data)
	err := srv.Group.Get(ctx, key, dest)
	if err != nil {
		return nil, err
	}
	im := new(imageserver.Image)
	err = im.UnmarshalBinaryNoCopy(data)
	if err != nil {
		return nil, err
	}
	return im, nil
}
コード例 #24
0
func TestGetterErrorImageMarshal(t *testing.T) {
	ctx := &Context{
		Params: imageserver.Params{},
	}
	var data []byte
	dest := groupcache.AllocatingByteSliceSink(&data)
	gt := &Getter{
		Server: &imageserver.StaticServer{
			Image: &imageserver.Image{
				Format: strings.Repeat("a", imageserver.ImageFormatMaxLen+1),
			},
		},
	}
	err := gt.Get(ctx, "foo", dest)
	if err == nil {
		t.Fatal("no error")
	}
}
コード例 #25
0
ファイル: groupcachetest.go プロジェクト: uileyar/helloworld
func main() {

	flag.Set("logtostderr", "true")
	flag.Parse()

	me := ":8080"
	peers := groupcache.NewHTTPPool("http://localhost" + me)
	peers.Set("http://localhost:8081", "http://localhost:8082", "http://localhost:8083")

	helloworld := groupcache.NewGroup("helloworld", 1024*1024*1024*16, groupcache.GetterFunc(
		func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
			glog.Infof("%v, key = %v", me, key)
			dest.SetString(key)
			return nil
		}))

	glog.Infof("GroupName: %v", helloworld.Name())
	http.HandleFunc("/xbox/",
		func(w http.ResponseWriter, r *http.Request) {
			parts := strings.SplitN(r.URL.Path[len("/xbox/"):], "/", 1)
			glog.Infof("parts: %v", parts)
			if len(parts) != 1 {
				http.Error(w, "Bad Request", http.StatusBadRequest)
				return
			}

			var data []byte
			helloworld.Get(nil, parts[0], groupcache.AllocatingByteSliceSink(&data))
			w.Write(data)

			glog.Infof("data: %s", data)
			glog.Infof("Stats: %#v", helloworld.Stats)
			//glog.Infof("Gets: %v", helloworld.Stats.Gets.String())
			//glog.Infof("Load: %v", helloworld.Stats.Loads.String())
			//glog.Infof("LocalLoad: %v", helloworld.Stats.LocalLoads.String())
			//glog.Infof("PeerError: %v", helloworld.Stats.PeerErrors.String())
			//glog.Infof("PeerLoad: %v", helloworld.Stats.PeerLoads.String())
		})

	http.ListenAndServe(me, nil)
}
コード例 #26
0
ファイル: groupcache.go プロジェクト: tartavull/dvid
// only need to override the Get function of the wrapped KeyValueDB.
func (g groupcacheStore) Get(ctx Context, k TKey) ([]byte, error) {
	gctx := GroupcacheCtx{
		Context:    ctx,
		KeyValueDB: g.KeyValueDB,
	}
	// we only provide this server for data contexts that have InstanceID().
	ip, ok := ctx.(instanceProvider)
	if !ok {
		dvid.Criticalf("groupcache Get passed a non-data context %v, falling back on normal kv store Get\n", ctx)
		return g.KeyValueDB.Get(ctx, k)
	}

	// the groupcache key has an instance identifier in first 4 bytes.
	instanceBytes := make([]byte, 4)
	binary.LittleEndian.PutUint32(instanceBytes, uint32(ip.InstanceID()))
	gkey := string(instanceBytes) + string(k)

	// Try to get data from groupcache, which if fails, will call the original KeyValueDB in passed Context.
	var data []byte
	err := g.cache.Get(groupcache.Context(gctx), gkey, groupcache.AllocatingByteSliceSink(&data))
	return data, err
}
コード例 #27
0
ファイル: main.go プロジェクト: bountylabs/etcd_groupcache
func main() {

	if !flag.Parsed() {
		flag.Parse()
	}

	// 	etcd := os.Getenv("ETCD_ADDR")
	ip := os.Getenv("PUBLIC_HOSTIP")
	pport := os.Getenv("PUBLIC_PORT")

	cache := etcd_groupcache.New(fmt.Sprintf("http://%s:%s", ip, pport), nil, nil)
	peers := []string{fmt.Sprintf("http://%s:8080", ip), fmt.Sprintf("http://%s:8081", ip)}
	log.Infoln(peers)
	cache.Set(peers...)
	http.Handle("/_groupcache/", cache)

	var stringcache = groupcache.NewGroup("SlowDBCache", 64<<20, groupcache.GetterFunc(
		func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
			log.Infoln(pport)
			dest.SetString(key + "heyo")
			return nil
		}))

	go func() {
		var data []byte
		key := "some key"
		err := stringcache.Get(nil, key, groupcache.AllocatingByteSliceSink(&data))
		if err != nil {
			log.Errorln(err)
		}
		log.Infoln(string(data))
	}()

	log.Infoln("Groupcache Listening 8080")
	if err := http.ListenAndServe(":"+*port, nil); err != nil {
		panic(err)
	}
}
コード例 #28
0
func TestGetter(t *testing.T) {
	ctx := &Context{
		Params: imageserver.Params{},
	}
	var data []byte
	dest := groupcache.AllocatingByteSliceSink(&data)
	gt := &Getter{
		Server: &imageserver.StaticServer{
			Image: testdata.Medium,
		},
	}
	err := gt.Get(ctx, "foo", dest)
	if err != nil {
		t.Fatal(err)
	}
	im := new(imageserver.Image)
	err = im.UnmarshalBinary(data)
	if err != nil {
		t.Fatal(err)
	}
	if !imageserver.ImageEqual(im, testdata.Medium) {
		t.Fatal("not equal")
	}
}
コード例 #29
0
ファイル: tile_generation.go プロジェクト: d4l3k/campus
func (s *Server) generateTile(req *MapTileRequest) ([]byte, error) {
	url := fmt.Sprintf("static/api/tiles/%d_%d_%d_%s.png", req.Z, req.X, req.Y, req.Floor)
	if _, err := os.Stat(url); err == nil {
		if *debug {
			log.Printf("file exists, but not serving due to debug; %s", url)
		} else {
			return ioutil.ReadFile(url)
		}
	}
	point := tileToPoint(req.X, req.Y, req.Z)
	pointBottom := tileToPoint(req.X+1, req.Y+1, req.Z)
	log.Printf("Map tile req %+v %+v %+v", req, point, pointBottom)
	coords := &models.Coords{
		North: point.Lat(),
		South: pointBottom.Lat(),
		West:  point.Lng(),
		East:  pointBottom.Lng(),
	}
	buildings := s.OverlappingBuildings(coords)

	if len(buildings) == 0 {
		return blankTile, nil
	}

	m := image.NewNRGBA(image.Rect(0, 0, TileSize, TileSize))
	for _, building := range buildings {
		for _, floor := range building.Floors {
			if floor.Name != req.Floor {
				continue
			}
			bfz := &BuildingFloorZoom{building.Name, floor.Name, req.Z}
			buf, err := json.Marshal(bfz)
			if err != nil {
				return nil, err
			}
			var resp []byte
			if err := s.zoomedFloorCache.Get(coords, string(buf), groupcache.AllocatingByteSliceSink(&resp)); err != nil {
				return nil, err
			}
			resizedImg, _, err := image.Decode(bytes.NewBuffer(resp))
			if err != nil {
				return nil, err
			}
			rect := resizedImg.Bounds()
			x := float64(rect.Dx()) - float64(rect.Dx())/(floor.Coords.East-floor.Coords.West)*(floor.Coords.East-coords.East) - TileSize
			y := float64(rect.Dy()) / (floor.Coords.North - floor.Coords.South) * (floor.Coords.North - coords.North)
			sp := image.Pt(int(x), int(y))
			draw.Draw(m, image.Rect(0, 0, TileSize, TileSize), resizedImg, sp, draw.Over)
		}
	}

	var buf bytes.Buffer
	if err := png.Encode(&buf, m); err != nil {
		return nil, err
	}
	bytes := buf.Bytes()
	if err := ioutil.WriteFile(url, bytes, 0755); err != nil {
		return nil, err
	}
	return bytes, nil
}