Package com.foundationdb.server.test.it.qp

Source Code of com.foundationdb.server.test.it.qp.QueryTimeoutIT$DoNothingForever

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.server.test.it.qp;

import com.foundationdb.qp.operator.*;
import com.foundationdb.qp.row.Row;
import com.foundationdb.sql.Main;
import com.foundationdb.server.error.QueryCanceledException;
import com.foundationdb.server.error.QueryTimedOutException;
import com.foundationdb.server.explain.CompoundExplainer;
import com.foundationdb.server.explain.ExplainContext;
import org.junit.Ignore;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicBoolean;

import static com.foundationdb.qp.operator.API.cursor;
import java.util.Map;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class QueryTimeoutIT extends OperatorITBase
{
    @Override
    protected Map<String, String> startupConfigProperties() {
        return uniqueStartupConfigProperties(getClass());
    }

    @Override
    protected void setupPostCreateSchema()
    {
        super.setupPostCreateSchema();
        session().cancelCurrentQuery(false);
    }

    @Test
    public void noExitWithDefaultTimeout() throws InterruptedException
    {
        final Operator plan = new DoNothingForever();
        final Cursor cursor = cursor(plan, queryContext, queryBindings);
        final AtomicBoolean exited = new AtomicBoolean(false);
        Thread queryThread = new Thread(
            new Runnable()
            {
                @Override
                public void run()
                {
                    try {
                        while (true) {
                            cursor.next();
                        }
                    } catch (QueryCanceledException e) {
                        exited.set(true);
                    }
                }
            });
        queryThread.start();
        Thread.sleep(5 * 1000); // 5 sec
        session().cancelCurrentQuery(true);
        queryThread.join();
        assertTrue(exited.get());
    }

    @Test
    public void exitWithTimeout() throws InterruptedException
    {
        int timeoutMilli = 3000;
        configService().queryTimeoutMilli(timeoutMilli);
        final Operator plan = new DoNothingForever();
        final Cursor cursor = cursor(plan, queryContext, queryBindings);
        final AtomicBoolean exited = new AtomicBoolean(false);
        Thread queryThread = new Thread(
            new Runnable()
            {
                @Override
                public void run()
                {
                    try {
                        while (true) {
                            cursor.next();
                        }
                    } catch (QueryTimedOutException e) {
                        exited.set(true);
                    }
                }
            });
        long start = System.currentTimeMillis();
        queryThread.start();
        queryThread.join();
        long stop = System.currentTimeMillis();
        assertTrue(exited.get());
        long elapsedMilli = (stop - start);
        assertTrue("Time: " + timeoutMilli + " Not equal to " + elapsedMilli, closeEnough(timeoutMilli, elapsedMilli));
    }

    @Test
    @Ignore
    public void shortenedTimeout() throws InterruptedException
    {
        int INITIAL_TIMEOUT_MILLI = 10000000;
        int MODIFIED_TIMEOUT_MILLI = 5000;
        Main layerInfo = (Main) layerInfo();
        configService().queryTimeoutMilli(INITIAL_TIMEOUT_MILLI);
        final Operator plan = new DoNothingForever();
        final Cursor cursor = cursor(plan, queryContext, queryBindings);
        final AtomicBoolean exited = new AtomicBoolean(false);
        Thread queryThread = new Thread(
            new Runnable()
            {
                @Override
                public void run()
                {
                    try {
                        while (true) {
                            cursor.next();
                        }
                    } catch (QueryTimedOutException e) {
                        exited.set(true);
                    }
                }
            });
        long start = System.currentTimeMillis();
        queryThread.start();
        // Shorten timeout
        Thread.sleep(1000); // 1 sec
        configService().queryTimeoutMilli(MODIFIED_TIMEOUT_MILLI);
        queryThread.join();
        long stop = System.currentTimeMillis();
        assertTrue(exited.get());
        long elapsedMilli = (stop - start);
        assertTrue(closeEnough(MODIFIED_TIMEOUT_MILLI, elapsedMilli));
    }

    @Test
    @Ignore
    public void removedTimeout() throws InterruptedException
    {
        int INITIAL_TIMEOUT_MILLI = 5000;
        int MODIFIED_TIMEOUT_MILLI = -1; // No timeout
        Main layerInfo = (Main) layerInfo();
        configService().queryTimeoutMilli(INITIAL_TIMEOUT_MILLI);
        final Operator plan = new DoNothingForever();
        final Cursor cursor = cursor(plan, queryContext, queryBindings);
        final AtomicBoolean exited = new AtomicBoolean(false);
        Thread queryThread = new Thread(
            new Runnable()
            {
                @Override
                public void run()
                {
                    try {
                        while (true) {
                            cursor.next();
                        }
                    } catch (QueryCanceledException e) { // catches timeout too
                        exited.set(true);
                    }
                }
            });
        long start = System.currentTimeMillis();
        queryThread.start();
        // Remove timeout
        Thread.sleep(1000); // 1 sec
        configService().queryTimeoutMilli(MODIFIED_TIMEOUT_MILLI);
        Thread.sleep(INITIAL_TIMEOUT_MILLI);
        session().cancelCurrentQuery(true);
        queryThread.join();
        long stop = System.currentTimeMillis();
        assertTrue(exited.get());
        long elapsedMilli = (stop - start);
        long expectedMilli = INITIAL_TIMEOUT_MILLI + 1000;
        assertTrue(closeEnough(expectedMilli, elapsedMilli));
    }

    private boolean closeEnough(long expectedMilli, long actualMilli)
    {
        // A lower fudge factor is needed because the timeout starts from the time the QueryContext is created,
        // which is in the @Before method, slightly before the test's timer starts.
        return
            actualMilli <= expectedMilli * (1 + UPPER_FUDGE_FACTOR) &&
            actualMilli >= expectedMilli * (1 - LOWER_FUDGE_FACTOR);
    }
   
    private static final double UPPER_FUDGE_FACTOR = 1.0; // 100%
    private static final double LOWER_FUDGE_FACTOR = 0.2; // 20%

    private static class DoNothingForever extends Operator
    {
        // Operator interface

        @Override
        protected Cursor cursor(QueryContext context, QueryBindingsCursor bindingsCursor)
        {
            return new Execution(context, bindingsCursor);
        }

        @Override
        public CompoundExplainer getExplainer(ExplainContext context)
        {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        private class Execution extends LeafCursor
        {
            // Cursor interface

            @Override
            public Row next()
            {
                checkQueryCancelation();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    fail();
                }
                return null;
            }

            // Execution interface

            Execution(QueryContext context,QueryBindingsCursor bindingsCursor)
            {
                super(context, bindingsCursor);
            }
        }
    }
}
TOP

Related Classes of com.foundationdb.server.test.it.qp.QueryTimeoutIT$DoNothingForever

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.