Package org.geowebcache.storage

Source Code of org.geowebcache.storage.TileRangeIteratorTest$TileRangeIteratorConsumer

package org.geowebcache.storage;

import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import junit.framework.TestCase;

import org.geowebcache.grid.BoundingBox;
import org.geowebcache.grid.GridSet;
import org.geowebcache.grid.GridSetBroker;
import org.geowebcache.grid.GridSetFactory;
import org.geowebcache.grid.GridSubset;
import org.geowebcache.grid.GridSubsetFactory;
import org.geowebcache.grid.SRS;
import org.geowebcache.mime.MimeType;
import org.springframework.util.StopWatch;

public class TileRangeIteratorTest extends TestCase {

    private MimeType mimeType;

    private String parameters;

    private GridSet gridSet;

    private GridSubset gridSubSet;

    private long[][] gridCoverages;

    /**
     * If non null, {@link #traverseTileRangeIter(int, long[][], int, int, int[])} will create a
     * {@link DiscontinuousTileRange} instead of a simple {@link TileRange}
     */
    private RasterMask rasterMask;

    @Override
    public void setUp() throws Exception {
        mimeType = MimeType.createFromFormat("image/png");
        parameters = null;
        gridSet = new GridSetBroker(true, false).WORLD_EPSG3857;
        BoundingBox extent = new BoundingBox(0, 0, 100, 100);
        boolean alignTopLeft = false;
        int levels = 12;
        Double metersPerUnit = Double.valueOf(1);
        double pixelSize = 1;
        int tileWidth = 100;
        int tileHeight = 100;
        boolean yCoordinateFirst = false;

        gridSet = GridSetFactory.createGridSet("TestGridSet", SRS.getSRS(100000), extent,
                alignTopLeft, levels, metersPerUnit, pixelSize, tileWidth, tileHeight,
                yCoordinateFirst);
        gridSubSet = GridSubsetFactory.createGridSubSet(gridSet);
        gridCoverages = gridSubSet.getCoverages();
    }

    /**
     *
     */
    public void testTraverseIndividualZoomLevelsNoMetaTiling() throws Exception {
        int zoomStart = gridSubSet.getZoomStart();
        int zoomStop = gridSubSet.getZoomStop();
        int[] metaTilingFactors = { 1, 1 };

        for (int zLevel = zoomStart; zLevel <= zoomStop; zLevel++) {
            long tilesProcessed = traverseTileRangeIter(1, gridCoverages, zLevel, zLevel,
                    metaTilingFactors);
            long expected = countMetaTiles(gridCoverages, zLevel, zLevel, metaTilingFactors);
            assertEquals("Expected tile count mismatch at zoom level " + zLevel, expected,
                    tilesProcessed);
        }
    }

    /**
     *
     */
    public void testTraverseIndividualZoomLevelsNoMetaTilingMultiThreading() throws Exception {
        int zoomStart = gridSubSet.getZoomStart();
        int zoomStop = gridSubSet.getZoomStop();
        int[] metaTilingFactors = { 1, 1 };

        final int nThreads = 64;
        StopWatch sw = new StopWatch();
        sw.start();
        //for (int zLevel = zoomStart; zLevel <= zoomStop; zLevel++) {
            long tilesProcessed = traverseTileRangeIter(nThreads, gridCoverages, zoomStart, zoomStop,
                    metaTilingFactors);
            long expected = countMetaTiles(gridCoverages, zoomStart, zoomStop, metaTilingFactors);
            assertEquals("Expected tile count mismatch at zoom level " + zoomStart, expected,
                    tilesProcessed);
        //}
        sw.stop();
        System.err.println(nThreads + " threads finished in " + sw.getTotalTimeMillis() + " to count " + expected);
    }

    /**
     *
     */
    public void testTraverseIndividualZoomLevelsMetaTiling() throws Exception {
        int zoomStart = gridSubSet.getZoomStart();
        int zoomStop = gridSubSet.getZoomStop();
        int[] metaTilingFactors = { 3, 3 };

        for (int zLevel = zoomStart; zLevel <= zoomStop; zLevel++) {
            long tilesProcessed = traverseTileRangeIter(1, gridCoverages, zLevel, zLevel,
                    metaTilingFactors);
            long expected = countMetaTiles(gridCoverages, zLevel, zLevel, metaTilingFactors);
            assertEquals("Expected tile count mismatch at zoom level " + zLevel, expected,
                    tilesProcessed);
        }
    }

    /**
     *
     */
    public void testWholeRangeMultiThreaded() throws Exception {
        int zoomStart = gridSubSet.getZoomStart();
        int zoomStop = gridSubSet.getZoomStop();
        int[] metaTilingFactors = { 1, 1 };

        int nThreads = 32;
        long tilesProcessed = traverseTileRangeIter(nThreads, gridCoverages, zoomStart, zoomStop,
                metaTilingFactors);
        long expected = countMetaTiles(gridCoverages, zoomStart, zoomStop, metaTilingFactors);
        assertEquals(expected, tilesProcessed);
    }

    /**
     *
     */
    public void testWholeRangeMultiThreadedMetaTiling() throws Exception {
        int zoomStart = gridSubSet.getZoomStart();
        int zoomStop = gridSubSet.getZoomStop();
        int[] metaTilingFactors = { 3, 3 };

        int nThreads = 32;
        long tilesProcessed = traverseTileRangeIter(nThreads, gridCoverages, zoomStart, zoomStop,
                metaTilingFactors);
        long expected = countMetaTiles(gridCoverages, zoomStart, zoomStop, metaTilingFactors);
        assertEquals(expected, tilesProcessed);
    }

    /**
     *
     */
    public void testDiscontinuousTileRange() throws Exception {
        rasterMask = createMock(RasterMask.class);
        expect(rasterMask.getGridCoverages()).andReturn(gridCoverages);
        // mock up RasterMask to return TRUE only for tiles 0,0,0 and 1,1,1
        expect(rasterMask.lookup(eq(0L), eq(0L), eq(0))).andReturn(Boolean.TRUE);
        expect(rasterMask.lookup(eq(0L), eq(0L), eq(1))).andReturn(Boolean.FALSE);
        expect(rasterMask.lookup(eq(1L), eq(0L), eq(1))).andReturn(Boolean.FALSE);
        expect(rasterMask.lookup(eq(0L), eq(1L), eq(1))).andReturn(Boolean.FALSE);
        expect(rasterMask.lookup(eq(1L), eq(1L), eq(1))).andReturn(Boolean.TRUE);
        replay(rasterMask);

        final int zoomStart = 0;
        final int zoomStop = 1;
        final int[] metaTilingFactors = { 1, 1 };

        final int nThreads = 1;
        long tilesProcessed = traverseTileRangeIter(nThreads, gridCoverages, zoomStart, zoomStop,
                metaTilingFactors);
        final long expected = 2;
        assertEquals(expected, tilesProcessed);
        verify(rasterMask);
    }

    /**
     * @return
     */
    private long traverseTileRangeIter(final int nThreads, final long[][] coveredGridLevels,
            final int zoomStart, final int zoomStop, final int[] metaTilingFactors)
            throws Exception {

        final ExecutorService executorService = Executors.newFixedThreadPool(nThreads);

        final TileRange tileRange;
        if (rasterMask == null) {
            tileRange = new TileRange("layer", "gridset", zoomStart, zoomStop, coveredGridLevels,
                    mimeType, parameters);
        } else {
            tileRange = new DiscontinuousTileRange("layer", "gridset", zoomStart, zoomStop,
                    rasterMask, mimeType, parameters);
        }

        final TileRangeIterator tri = new TileRangeIterator(tileRange, metaTilingFactors);

        Collection<Callable<Long>> tasks = new ArrayList<Callable<Long>>(nThreads);
        for (int taskN = 0; taskN < nThreads; taskN++) {
            tasks.add(new TileRangeIteratorConsumer(tri));
        }
        List<Future<Long>> values = executorService.invokeAll(tasks);
        executorService.shutdown();
        try {
            executorService.awaitTermination(120, TimeUnit.SECONDS);
        } catch (InterruptedException ie) {
            fail("Executor service timeout: " + ie.getMessage());
        }

        long totalProcessed = sumValues(values);
        return totalProcessed;
    }

    private long sumValues(List<Future<Long>> values) throws InterruptedException,
            ExecutionException {
        long total = 0;
        for (Future<Long> value : values) {
            long countedByTask = value.get().longValue();
            total += countedByTask;
        }
        return total;
    }

    /**
     * Simple Callable that traverses a {@link TileRangeIterator} and returns the number of grid
     * locations processed
     */
    private static final class TileRangeIteratorConsumer implements Callable<Long> {
        private final TileRangeIterator tri;

        private TileRangeIteratorConsumer(TileRangeIterator tri) {
            this.tri = tri;
        }

        public Long call() throws Exception {
            long nprocessed = 0;
            long[] gridLoc = new long[3];
            while (null != (gridLoc = tri.nextMetaGridLocation(gridLoc))) {
                ++nprocessed;
            }
            return Long.valueOf(nprocessed);
        }
    }

    private long countMetaTiles(long[][] coveredGridLevels, int startZoom, int stopZoom,
            int[] metaTilingFactors) {
        long count = 0;

        final int metaX = metaTilingFactors[0];
        final int metaY = metaTilingFactors[1];

        for (int i = startZoom; i <= stopZoom; i++) {
            long[] gridBounds = coveredGridLevels[i];
            long boundsMinX = gridBounds[0];
            long boundsMaxX = gridBounds[2];
            long boundsMinY = gridBounds[1];
            long boundsMaxY = gridBounds[3];

            long tilesX = 1 + boundsMaxX - boundsMinX;
            long tilesY = 1 + boundsMaxY - boundsMinY;

            long metaTilesX = (long) Math.ceil(tilesX / (double) metaX);
            long metaTilesY = (long) Math.ceil(tilesY / (double) metaY);

            long thisLevelMetaTiles = metaTilesX * metaTilesY;

            count += thisLevelMetaTiles;
        }

        return count;
    }

}
TOP

Related Classes of org.geowebcache.storage.TileRangeIteratorTest$TileRangeIteratorConsumer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.