package postgres import ( "mapserver/coords" "mapserver/db" "mapserver/settings" "mapserver/types" "math" "github.com/sirupsen/logrus" ) const ( SETTING_LAST_LAYER = "last_layer" SETTING_LAST_X_BLOCK = "last_x_block" SETTING_LAST_Y_BLOCK = "last_y_block" ) func (a *PostgresAccessor) countBlocks(x1, y1, z1, x2, y2, z2 int) (int, error) { rows, err := a.db.Query(getBlockCountByInitialTileQuery, x1, y1, z1, x2, y2, z2, ) if err != nil { return 0, err } defer rows.Close() if rows.Next() { var count int err = rows.Scan(&count) if err != nil { return 0, err } return count, nil } return 0, nil } // x -> 0 ... 256 //zoom/mapblock-width //13 1 //12 2 //11 4 //10 8 //9 16 //Zoom 9: //10 mapblocks height * 16 * 16 == 2560 func (a *PostgresAccessor) FindNextInitialBlocks(s settings.Settings, layers []*types.Layer, limit int) (*db.InitialBlocksResult, error) { lastlayer := s.GetInt(SETTING_LAST_LAYER, 0) lastxblock := s.GetInt(SETTING_LAST_X_BLOCK, -129) lastyblock := s.GetInt(SETTING_LAST_Y_BLOCK, -128) if lastxblock >= 128 { lastxblock = -128 lastyblock++ } else { lastxblock++ } if lastyblock > 128 { //done var nextlayer = lastlayer for _, l := range layers { if l.Id > nextlayer { nextlayer = l.Id break } } s.SetInt(SETTING_LAST_LAYER, nextlayer) s.SetInt(SETTING_LAST_X_BLOCK, -129) s.SetInt(SETTING_LAST_Y_BLOCK, -128) result := &db.InitialBlocksResult{} result.HasMore = nextlayer != lastlayer return result, nil } tc := coords.NewTileCoords(lastxblock, lastyblock, 9, lastlayer) currentlayer := types.FindLayerById(layers, lastlayer) tcr := coords.GetMapBlockRangeFromTile(tc, 0) tcr.Pos1.Y = currentlayer.From tcr.Pos2.Y = currentlayer.To fields := logrus.Fields{ "layerId": lastlayer, "pos1": tcr.Pos1, "pos2": tcr.Pos2, "tile": tc, } log.WithFields(fields).Debug("Initial-Query") minX := int(math.Min(float64(tcr.Pos1.X), float64(tcr.Pos2.X))) maxX := int(math.Max(float64(tcr.Pos1.X), float64(tcr.Pos2.X))) minY := int(math.Min(float64(tcr.Pos1.Y), float64(tcr.Pos2.Y))) maxY := int(math.Max(float64(tcr.Pos1.Y), float64(tcr.Pos2.Y))) minZ := int(math.Min(float64(tcr.Pos1.Z), float64(tcr.Pos2.Z))) maxZ := int(math.Max(float64(tcr.Pos1.Z), float64(tcr.Pos2.Z))) if lastxblock <= -128 { //first x entry, check z stride stridecount := a.intQuery(` select count(*) from blocks where posz >= $1 and posz <= $2 and posy >= $3 and posy <= $4`, minZ, maxZ, minY, maxY, ) if stridecount == 0 { fields = logrus.Fields{ "minX": minX, "maxX": maxX, "minY": minY, "maxY": maxY, } log.WithFields(fields).Debug("Skipping stride") s.SetInt(SETTING_LAST_LAYER, lastlayer) s.SetInt(SETTING_LAST_X_BLOCK, -129) s.SetInt(SETTING_LAST_Y_BLOCK, lastyblock+1) result := &db.InitialBlocksResult{} result.Progress = float64(((lastyblock+128)*256)+(lastxblock+128)) / float64(256*256) result.HasMore = true return result, nil } } count, err := a.countBlocks(minX, minY, minZ, maxX, maxY, maxZ) if err != nil { return nil, err } blocks := make([]*db.Block, 0) var lastmtime int64 if count > 0 { rows, err := a.db.Query(getBlocksByInitialTileQuery, minX, minY, minZ, maxX, maxY, maxZ, ) if err != nil { return nil, err } defer rows.Close() for rows.Next() { var posx, posy, posz int var data []byte var mtime int64 err = rows.Scan(&posx, &posy, &posz, &data, &mtime) if err != nil { return nil, err } if mtime > lastmtime { lastmtime = mtime } mb := convertRows(posx, posy, posz, data, mtime) blocks = append(blocks, mb) } } s.SetInt(SETTING_LAST_LAYER, lastlayer) s.SetInt(SETTING_LAST_X_BLOCK, lastxblock) s.SetInt(SETTING_LAST_Y_BLOCK, lastyblock) result := &db.InitialBlocksResult{} result.LastMtime = lastmtime result.Progress = float64(((lastyblock+128)*256)+(lastxblock+128)) / float64(256*256) result.List = blocks result.HasMore = true return result, nil }