text:
package com.netflix.hystrix;

import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
import com.netflix.hystrix.AbstractTestHystrixCommand.CacheEnabled;
import com.netflix.hystrix.AbstractTestHystrixCommand.ExecutionResult;
import com.netflix.hystrix.AbstractTestHystrixCommand.FallbackResult;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
import org.junit.Test;
import rx.Observable;
import rx.Scheduler;
import rx.Subscriber;
import rx.functions.Action1;
import rx.functions.Func0;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.junit.Assert.*;

/**
 * Place to share code and tests between {@link HystrixCommandTest} and {@link HystrixObservableCommandTest}.
 * @param <C>
 */
public abstract class CommonHystrixCommandTests<C extends AbstractTestHystrixCommand<Integer>> {

    /**
     * Run the command in multiple modes and check that the hook assertions hold in each and that the command succeeds
     * @param ctor {@link AbstractTestHystrixCommand} constructor
     * @param assertion sequence of assertions to check after the command has completed
     */
    abstract void assertHooksOnSuccess(Func0<C> ctor, Action1<C> assertion);

    /**
     * Run the command in multiple modes and check that the hook assertions hold in each and that the command fails
     * @param ctor {@link AbstractTestHystrixCommand} constructor
     * @param assertion sequence of assertions to check after the command has completed
     */
    abstract void assertHooksOnFailure(Func0<C> ctor, Action1<C> assertion);

    /**
     * Run the command in multiple modes and check that the hook assertions hold in each and that the command fails
     * @param ctor {@link AbstractTestHystrixCommand} constructor
     * @param assertion sequence of assertions to check after the command has completed
     */
    abstract void assertHooksOnFailure(Func0<C> ctor, Action1<C> assertion, boolean failFast);

    /**
     * Run the command in multiple modes and check that the hook assertions hold in each and that the command fails as soon as possible
     * @param ctor {@link AbstractTestHystrixCommand} constructor
     * @param assertion sequence of assertions to check after the command has completed
     */
    protected void assertHooksOnFailFast(Func0<C> ctor, Action1<C> assertion) {
        assertHooksOnFailure(ctor, assertion, true);
    }

    /**
     * Run the command via {@link com.netflix.hystrix.HystrixCommand#observe()}, immediately block and then assert
     * @param command command to run
     * @param assertion assertions to check
     * @param isSuccess should the command succeed?
     */
    protected void assertBlockingObserve(C command, Action1<C> assertion, boolean isSuccess) {
        System.out.println("Running command.observe(), immediately blocking and then running assertions...");
        if (isSuccess) {
            try {
                command.observe().toList().toBlocking().single();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        } else {
            try {
                command.observe().toList().toBlocking().single();
                fail("Expected a command failure!");
            } catch (Exception ex) {
                System.out.println("Received expected ex : " + ex);
                ex.printStackTrace();
            }
        }

        assertion.call(command);
    }

    /**
     * Run the command via {@link com.netflix.hystrix.HystrixCommand#observe()}, let the {@link rx.Observable} terminal
     * states unblock a {@link java.util.concurrent.CountDownLatch} and then assert
     * @param command command to run
     * @param assertion assertions to check
     * @param isSuccess should the command succeed?
     */
    protected void assertNonBlockingObserve(C command, Action1<C> assertion, boolean isSuccess) {
        System.out.println("Running command.observe(), awaiting terminal state of Observable, then running assertions...");
        final CountDownLatch latch = new CountDownLatch(1);

        Observable<Integer> o = command.observe();

        o.subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                latch.countDown();
            }

            @Override
            public void onError(Throwable e) {
                latch.countDown();
            }

            @Override
            public void onNext(Integer i) {
                //do nothing
            }
        });

        try {
            latch.await(3, TimeUnit.SECONDS);
            assertion.call(command);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (isSuccess) {
            try {
                o.toList().toBlocking().single();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        } else {
            try {
                o.toList().toBlocking().single();
                fail("Expected a command failure!");
            } catch (Exception ex) {
                System.out.println("Received expected ex : " + ex);
                ex.printStackTrace();
            }
        }
    }

    protected void assertSaneHystrixRequestLog(final int numCommands) {
        HystrixRequestLog currentRequestLog = HystrixRequestLog.getCurrentRequest();

        try {
            assertEquals(numCommands, currentRequestLog.getAllExecutedCommands().size());
            assertFalse(currentRequestLog.getExecutedCommandsAsString().contains("Executed"));
            assertTrue(currentRequestLog.getAllExecutedCommands().iterator().next().getExecutionEvents().size() >= 1);
            //Most commands should have 1 execution event, but fallbacks / responses from cache can cause more than 1.  They should never have 0
        } catch (Throwable ex) {
            System.out.println("Problematic Request log : " + currentRequestLog.getExecutedCommandsAsString() + " , expected : " + numCommands);
            throw new RuntimeException(ex);
        }
    }

    protected void assertCommandExecutionEvents(HystrixInvokableInfo<?> command, HystrixEventType... expectedEventTypes) {
        boolean emitExpected = false;
        int expectedEmitCount = 0;

        boolean fallbackEmitExpected = false;
        int expectedFallbackEmitCount = 0;

        List<HystrixEventType> condensedEmitExpectedEventTypes = new ArrayList<HystrixEventType>();

        for (HystrixEventType expectedEventType: expectedEventTypes) {
            if (expectedEventType.equals(HystrixEventType.EMIT)) {
                if (!emitExpected) {
                    //first EMIT encountered, add it to condensedEmitExpectedEventTypes
                    condensedEmitExpectedEventTypes.add(HystrixEventType.EMIT);
                }
                emitExpected = true;
                expectedEmitCount++;
            } else if (expectedEventType.equals(HystrixEventType.FALLBACK_EMIT)) {
                if (!fallbackEmitExpected) {
                    //first FALLBACK_EMIT encountered, add it to condensedEmitExpectedEventTypes
                    condensedEmitExpectedEventTypes.add(HystrixEventType.FALLBACK_EMIT);
                }
                fallbackEmitExpected = true;
                expectedFallbackEmitCount++;
            } else {
                condensedEmitExpectedEventTypes.add(expectedEventType);
            }
        }
        List<HystrixEventType> actualEventTypes = command.getExecutionEvents();
        assertEquals(expectedEmitCount, command.getNumberEmissions());
        assertEquals(expectedFallbackEmitCount, command.getNumberFallbackEmissions());
        assertEquals(condensedEmitExpectedEventTypes, actualEventTypes);
    }

    /**
     * Threadpool with 1 thread, queue of size 1
     */
    protected static class SingleThreadedPoolWithQueue implements HystrixThreadPool {

        final LinkedBlockingQueue<Runnable> queue;
        final ThreadPoolExecutor pool;
        private final int rejectionQueueSizeThreshold;

        public SingleThreadedPoolWithQueue(int queueSize) {
            this(queueSize, 100);
        }

        public SingleThreadedPoolWithQueue(int queueSize, int rejectionQueueSizeThreshold) {
            queue = new LinkedBlockingQueue<Runnable>(queueSize);
            pool = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, queue);
            this.rejectionQueueSizeThreshold = rejectionQueueSizeThreshold;
        }

        @Override
        public ThreadPoolExecutor getExecutor() {
            return pool;
        }

        @Override
        public Scheduler getScheduler() {
            return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this);
        }

        @Override
        public Scheduler getScheduler(Func0<Boolean> shouldInterruptThread) {
            return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this, shouldInterruptThread);
        }

        @Override
        public void markThreadExecution() {
            // not used for this test
        }

        @Override
        public void markThreadCompletion() {
            // not used for this test
        }

        @Override
        public void markThreadRejection() {
            // not used for this test
        }

        @Override
        public boolean isQueueSpaceAvailable() {
            return queue.size() < rejectionQueueSizeThreshold;
        }

    }

    /**
     * Threadpool with 1 thread, queue of size 1
     */
    protected static class SingleThreadedPoolWithNoQueue implements HystrixThreadPool {

        final SynchronousQueue<Runnable> queue;
        final ThreadPoolExecutor pool;

        public SingleThreadedPoolWithNoQueue() {
            queue = new SynchronousQueue<Runnable>();
            pool = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, queue);
        }

        @Override
        public ThreadPoolExecutor getExecutor() {
            return pool;
        }

        @Override
        public Scheduler getScheduler() {
            return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this);
        }

        @Override
        public Scheduler getScheduler(Func0<Boolean> shouldInterruptThread) {
            return new HystrixContextScheduler(HystrixPlugins.getInstance().getConcurrencyStrategy(), this, shouldInterruptThread);
        }

        @Override
        public void markThreadExecution() {
            // not used for this test
        }

        @Override
        public void markThreadCompletion() {
            // not used for this test
        }

        @Override
        public void markThreadRejection() {
            // not used for this test
        }

        @Override
        public boolean isQueueSpaceAvailable() {
            return true; //let the thread pool reject
        }

    }

    /**
     ********************* SEMAPHORE-ISOLATED Execution Hook Tests ***********************************
     */

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : NO
     * Execution Result: SUCCESS
     */
    @Test
    public void testExecutionHookSemaphoreSuccess() {
        assertHooksOnSuccess(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, FallbackResult.SUCCESS);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(1, 0, 1));
                        assertTrue(hook.executionEventsMatch(1, 0, 1));
                        assertTrue(hook.fallbackEventsMatch(0, 0, 0));
                        assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionEmit - !onRunSuccess - !onComplete - onEmit - onExecutionSuccess - onSuccess - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : NO
     * Execution Result: synchronous HystrixBadRequestException
     */
    @Test
    public void testExecutionHookSemaphoreBadRequestException() {
        assertHooksOnFailure(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.BAD_REQUEST, FallbackResult.SUCCESS);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(0, 1, 0));
                        assertTrue(hook.executionEventsMatch(0, 1, 0));
                        assertTrue(hook.fallbackEventsMatch(0, 0, 0));
                        assertEquals(HystrixBadRequestException.class, hook.getCommandException().getClass());
                        assertEquals(HystrixBadRequestException.class, hook.getExecutionException().getClass());
                        assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onError - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : NO
     * Execution Result: synchronous HystrixRuntimeException
     * Fallback: UnsupportedOperationException
     */
    @Test
    public void testExecutionHookSemaphoreExceptionNoFallback() {
        assertHooksOnFailure(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.FAILURE, FallbackResult.UNIMPLEMENTED);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(0, 1, 0));
                        assertTrue(hook.executionEventsMatch(0, 1, 0));
                        assertTrue(hook.fallbackEventsMatch(0, 0, 0));
                        assertEquals(RuntimeException.class, hook.getCommandException().getClass());
                        assertEquals(RuntimeException.class, hook.getExecutionException().getClass());
                        assertNull(hook.getFallbackException());
                        assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onError - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : NO
     * Execution Result: synchronous HystrixRuntimeException
     * Fallback: SUCCESS
     */
    @Test
    public void testExecutionHookSemaphoreExceptionSuccessfulFallback() {
        assertHooksOnSuccess(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.FAILURE, FallbackResult.SUCCESS);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(1, 0, 1));
                        assertTrue(hook.executionEventsMatch(0, 1, 0));
                        assertTrue(hook.fallbackEventsMatch(1, 0, 1));
                        assertEquals(RuntimeException.class, hook.getExecutionException().getClass());
                        assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onFallbackStart - onFallbackEmit - !onFallbackSuccess - !onComplete - onEmit - onFallbackSuccess - onSuccess - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : NO
     * Execution Result: synchronous HystrixRuntimeException
     * Fallback: synchronous HystrixRuntimeException
     */
    @Test
    public void testExecutionHookSemaphoreExceptionUnsuccessfulFallback() {
        assertHooksOnFailure(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.FAILURE, FallbackResult.FAILURE);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(0, 1, 0));
                        assertTrue(hook.executionEventsMatch(0, 1, 0));
                        assertTrue(hook.fallbackEventsMatch(0, 1, 0));
                        assertEquals(RuntimeException.class, hook.getCommandException().getClass());
                        assertEquals(RuntimeException.class, hook.getExecutionException().getClass());
                        assertEquals(RuntimeException.class, hook.getFallbackException().getClass());
                        assertEquals("onStart - !onRunStart - onExecutionStart - onExecutionError - !onRunError - onFallbackStart - onFallbackError - onError - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : YES
     * Fallback: UnsupportedOperationException
     */
    @Test
    public void testExecutionHookSemaphoreRejectedNoFallback() {
        assertHooksOnFailFast(
                new Func0<C>() {
                    @Override
                    public C call() {
                        AbstractCommand.TryableSemaphore semaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(2));

                        final C cmd1 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.UNIMPLEMENTED, semaphore);
                        final C cmd2 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.UNIMPLEMENTED, semaphore);

                        //saturate the semaphore
                        new Thread() {
                            @Override
                            public void run() {
                                cmd1.observe();
                            }
                        }.start();
                        new Thread() {
                            @Override
                            public void run() {
                                cmd2.observe();
                            }
                        }.start();

                        try {
                            //give the saturating threads a chance to run before we run the command we want to get rejected
                            Thread.sleep(200);
                        } catch (InterruptedException ie) {
                            throw new RuntimeException(ie);
                        }

                        return getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.UNIMPLEMENTED, semaphore);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(0, 1, 0));
                        assertTrue(hook.executionEventsMatch(0, 0, 0));
                        assertTrue(hook.fallbackEventsMatch(0, 0, 0));
                        assertEquals(RuntimeException.class, hook.getCommandException().getClass());
                        assertNull(hook.getFallbackException());
                        assertEquals("onStart - onError - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : YES
     * Fallback: SUCCESS
     */
    @Test
    public void testExecutionHookSemaphoreRejectedSuccessfulFallback() {
        assertHooksOnSuccess(
                new Func0<C>() {
                    @Override
                    public C call() {
                        AbstractCommand.TryableSemaphore semaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(2));

                        final C cmd1 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 1500, FallbackResult.SUCCESS, semaphore);
                        final C cmd2 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 1500, FallbackResult.SUCCESS, semaphore);

                        //saturate the semaphore
                        new Thread() {
                            @Override
                            public void run() {
                                cmd1.observe();
                            }
                        }.start();
                        new Thread() {
                            @Override
                            public void run() {
                                cmd2.observe();
                            }
                        }.start();

                        try {
                            //give the saturating threads a chance to run before we run the command we want to get rejected
                            Thread.sleep(200);
                        } catch (InterruptedException ie) {
                            throw new RuntimeException(ie);
                        }

                        return getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.SUCCESS, semaphore);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(1, 0, 1));
                        assertTrue(hook.executionEventsMatch(0, 0, 0));
                        assertTrue(hook.fallbackEventsMatch(1, 0, 1));
                        assertEquals("onStart - onFallbackStart - onFallbackEmit - !onFallbackSuccess - !onComplete - onEmit - onFallbackSuccess - onSuccess - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : NO
     * Thread/semaphore: SEMAPHORE
     * Semaphore Permit reached? : YES
     * Fallback: synchronous HystrixRuntimeException
     */
    @Test
    public void testExecutionHookSemaphoreRejectedUnsuccessfulFallback() {
        assertHooksOnFailFast(
                new Func0<C>() {
                    @Override
                    public C call() {
                        AbstractCommand.TryableSemaphore semaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(2));

                        final C cmd1 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.FAILURE, semaphore);
                        final C cmd2 = getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.FAILURE, semaphore);

                        //saturate the semaphore
                        new Thread() {
                            @Override
                            public void run() {
                                cmd1.observe();
                            }
                        }.start();
                        new Thread() {
                            @Override
                            public void run() {
                                cmd2.observe();
                            }
                        }.start();

                        try {
                            //give the saturating threads a chance to run before we run the command we want to get rejected
                            Thread.sleep(200);
                        } catch (InterruptedException ie) {
                            throw new RuntimeException(ie);
                        }

                        return getLatentCommand(ExecutionIsolationStrategy.SEMAPHORE, ExecutionResult.SUCCESS, 500, FallbackResult.FAILURE, semaphore);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(0, 1, 0));
                        assertTrue(hook.executionEventsMatch(0, 0, 0));
                        assertTrue(hook.fallbackEventsMatch(0, 1, 0));
                        assertEquals(RuntimeException.class, hook.getCommandException().getClass());
                        assertEquals(RuntimeException.class, hook.getFallbackException().getClass());
                        assertEquals("onStart - onFallbackStart - onFallbackError - onError - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : YES
     * Thread/semaphore: SEMAPHORE
     * Fallback: UnsupportedOperationException
     */
    @Test
    public void testExecutionHookSemaphoreShortCircuitNoFallback() {
        assertHooksOnFailFast(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCircuitOpenCommand(ExecutionIsolationStrategy.SEMAPHORE, FallbackResult.UNIMPLEMENTED);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(0, 1, 0));
                        assertTrue(hook.executionEventsMatch(0, 0, 0));
                        assertTrue(hook.fallbackEventsMatch(0, 0, 0));
                        assertEquals(RuntimeException.class, hook.getCommandException().getClass());
                        assertNull(hook.getFallbackException());
                        assertEquals("onStart - onError - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : YES
     * Thread/semaphore: SEMAPHORE
     * Fallback: SUCCESS
     */
    @Test
    public void testExecutionHookSemaphoreShortCircuitSuccessfulFallback() {
        assertHooksOnSuccess(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCircuitOpenCommand(ExecutionIsolationStrategy.SEMAPHORE, FallbackResult.SUCCESS);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(1, 0, 1));
                        assertTrue(hook.executionEventsMatch(0, 0, 0));
                        assertTrue(hook.fallbackEventsMatch(1, 0, 1));
                        assertEquals("onStart - onFallbackStart - onFallbackEmit - !onFallbackSuccess - !onComplete - onEmit - onFallbackSuccess - onSuccess - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     * Short-circuit? : YES
     * Thread/semaphore: SEMAPHORE
     * Fallback: synchronous HystrixRuntimeException
     */
    @Test
    public void testExecutionHookSemaphoreShortCircuitUnsuccessfulFallback() {
        assertHooksOnFailFast(
                new Func0<C>() {
                    @Override
                    public C call() {
                        return getCircuitOpenCommand(ExecutionIsolationStrategy.SEMAPHORE, FallbackResult.FAILURE);
                    }
                },
                new Action1<C>() {
                    @Override
                    public void call(C command) {
                        TestableExecutionHook hook = command.getBuilder().executionHook;
                        assertTrue(hook.commandEmissionsMatch(0, 1, 0));
                        assertTrue(hook.executionEventsMatch(0, 0, 0));
                        assertTrue(hook.fallbackEventsMatch(0, 1, 0));
                        assertEquals(RuntimeException.class, hook.getCommandException().getClass());
                        assertEquals(RuntimeException.class, hook.getFallbackException().getClass());
                        assertEquals("onStart - onFallbackStart - onFallbackError - onError - ", hook.executionSequence.toString());
                    }
                });
    }

    /**
     ********************* END SEMAPHORE-ISOLATED Execution Hook Tests ***********************************
     */

    /**
     * Abstract methods defining a way to instantiate each of the described commands.
     * {@link HystrixCommandTest} and {@link HystrixObservableCommandTest} should each provide concrete impls for
     * {@link HystrixCommand}s and {@link} HystrixObservableCommand}s, respectively.
     */

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult) {
        return getCommand(isolationStrategy, executionResult, FallbackResult.UNIMPLEMENTED);
    }

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency) {
        return getCommand(isolationStrategy, executionResult, executionLatency, FallbackResult.UNIMPLEMENTED);
    }

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, FallbackResult fallbackResult) {
        return getCommand(isolationStrategy, executionResult, 0, fallbackResult);
    }

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult) {
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, (executionLatency * 2) + 200, CacheEnabled.NO, "foo", 10, 10);
    }

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int timeout) {
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, timeout, CacheEnabled.NO, "foo", 10, 10);
    }

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, int fallbackSemaphoreCount) {
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphoreCount, fallbackSemaphoreCount, false);
    }

    C getCommand(HystrixCommandKey key, ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, int fallbackSemaphoreCount) {
        AbstractCommand.TryableSemaphoreActual executionSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(executionSemaphoreCount));
        AbstractCommand.TryableSemaphoreActual fallbackSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(fallbackSemaphoreCount));

        return getCommand(key, isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphore, fallbackSemaphore, false);
    }

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, int fallbackSemaphoreCount, boolean circuitBreakerDisabled) {
        AbstractCommand.TryableSemaphoreActual executionSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(executionSemaphoreCount));
        AbstractCommand.TryableSemaphoreActual fallbackSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(fallbackSemaphoreCount));
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphore, fallbackSemaphore, circuitBreakerDisabled);
    }

    C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, int executionSemaphoreCount, AbstractCommand.TryableSemaphore fallbackSemaphore, boolean circuitBreakerDisabled) {
        AbstractCommand.TryableSemaphoreActual executionSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(executionSemaphoreCount));
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, fallbackLatency, circuitBreaker, threadPool, timeout, cacheEnabled, value, executionSemaphore, fallbackSemaphore, circuitBreakerDisabled);
    }

    abstract C getCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, AbstractCommand.TryableSemaphore executionSemaphore, AbstractCommand.TryableSemaphore fallbackSemaphore, boolean circuitBreakerDisabled);

    abstract C getCommand(HystrixCommandKey commandKey, ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int fallbackLatency, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout, CacheEnabled cacheEnabled, Object value, AbstractCommand.TryableSemaphore executionSemaphore, AbstractCommand.TryableSemaphore fallbackSemaphore, boolean circuitBreakerDisabled);

    C getLatentCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, int timeout) {
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, timeout, CacheEnabled.NO, "foo", 10, 10);
    }

    C getLatentCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker, HystrixThreadPool threadPool, int timeout) {
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, circuitBreaker, threadPool, timeout, CacheEnabled.NO, "foo", 10, 10);
    }

    C getLatentCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult, int executionLatency, FallbackResult fallbackResult, AbstractCommand.TryableSemaphore executionSemaphore) {
        AbstractCommand.TryableSemaphoreActual fallbackSemaphore = new AbstractCommand.TryableSemaphoreActual(HystrixProperty.Factory.asProperty(10));
        return getCommand(isolationStrategy, executionResult, executionLatency, fallbackResult, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, (executionLatency * 2) + 200, CacheEnabled.NO, "foo", executionSemaphore, fallbackSemaphore, false);
    }

    C getCircuitOpenCommand(ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult) {
        HystrixCircuitBreakerTest.TestCircuitBreaker openCircuit = new HystrixCircuitBreakerTest.TestCircuitBreaker().setForceShortCircuit(true);
        return getCommand(isolationStrategy, ExecutionResult.SUCCESS, 0, fallbackResult, 0, openCircuit, null, 500, CacheEnabled.NO, "foo", 10, 10, false);
    }

    C getSharedCircuitBreakerCommand(HystrixCommandKey commandKey, ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult, HystrixCircuitBreakerTest.TestCircuitBreaker circuitBreaker) {
        return getCommand(commandKey, isolationStrategy, ExecutionResult.FAILURE, 0, fallbackResult, 0, circuitBreaker, null, 500, CacheEnabled.NO, "foo", 10, 10);
    }

    C getCircuitBreakerDisabledCommand(ExecutionIsolationStrategy isolationStrategy, ExecutionResult executionResult) {
        return getCommand(isolationStrategy, executionResult, 0, FallbackResult.UNIMPLEMENTED, 0, new HystrixCircuitBreakerTest.TestCircuitBreaker(), null, 500, CacheEnabled.NO, "foo", 10, 10, true);
    }

    C getRecoverableErrorCommand(ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult) {
        return getCommand(isolationStrategy, ExecutionResult.RECOVERABLE_ERROR, 0, fallbackResult);
    }

    C getUnrecoverableErrorCommand(ExecutionIsolationStrategy isolationStrategy, FallbackResult fallbackResult) {
        return getCommand(isolationStrategy, ExecutionResult.UNRECOVERABLE_ERROR, 0, fallbackResult);
    }
}


text:
package org.apache.flex.compiler.internal.tree.mxml;

import org.apache.flex.compiler.internal.tree.as.NodeBase;
import org.apache.flex.compiler.mxml.IMXMLLanguageConstants;
import org.apache.flex.compiler.mxml.IMXMLTagData;
import org.apache.flex.compiler.mxml.IMXMLTextData;
import org.apache.flex.compiler.tree.ASTNodeID;
import org.apache.flex.compiler.tree.mxml.IMXMLPrivateNode;

/**
 * Implementation of the {@code IMXMLPrivateNode} interface.
 */
class MXMLPrivateNode extends MXMLNodeBase implements IMXMLPrivateNode
{
    /**
     * Constructor
     *
     * @param parent The parent node of this node, or null if there
     * is no parent.
     */
    MXMLPrivateNode(NodeBase parent)
    {
        super(parent);
    }

    @Override
    public ASTNodeID getNodeID()
    {
        return ASTNodeID.MXMLPrivateID;
    }

    @Override
    public String getName()
    {
        return IMXMLLanguageConstants.PRIVATE;
    }

    @Override
    protected void processChildTag(MXMLTreeBuilder builder, IMXMLTagData tag,
                                   IMXMLTagData childTag, MXMLNodeInfo info)
    {
        // Allow any child tag, but ignore it.
    }

    @Override
    protected void processChildNonWhitespaceUnit(MXMLTreeBuilder builder, IMXMLTagData tag,
                                                 IMXMLTextData text, MXMLNodeInfo info)
    {
        // Allow child text, but ignore it.
    }
}

redpajama_set_name: RedPajamaGithub


text:
enum GetFileListType
{
    GetFileListTypeAll,
    GetFileListTypeFileOnly,
    GetFileListTypeFolderOnly,
    GetFileListTypeImageOnly,
    GetFileListTypeVideoOnly,
    GetFileListTypeImageVideoOnly,
};

enum SortFileListType{
    SortFileListCreateDate,
    SortFileListModifyDate,
    SortFileListFileSize,
    SortFileListFileType,
    SortFileListFileName,
};

@interface FileLib : NSObject

+(NSURL*)getDocumentURL;
+(NSURL*)getDocumentURL:(NSString*) subFolder;
+(NSURL*)getDocumentURL:(NSString*) subFolder isDirectory:(BOOL)isDirectory;

+(NSString*)getDocumentPath;
+(NSString*)getDocumentPath: (NSString*) subFolder;
+(NSString*)getDocumentPath: (NSString*) subFolder autoCreateDir:(BOOL) autoCreateDir;

+(NSURL*)getLibraryURL;
+(NSURL*)getLibraryURL:(NSString*) subFolder;
+(NSURL*)getLibraryURL:(NSString*) subFolder isDirectory:(BOOL)isDirectory;

+(NSString*)getLibraryPath;
+(NSString*)getLibraryPath: (NSString*) subFolder;
+(NSString*)getLibraryPath: (NSString*) subFolder autoCreateDir:(BOOL) autoCreateDir;

+(NSString*)getTempPath;
+(NSString*)getTempPath: (NSString*) subFolder;
+(NSString*)getTempPath: (NSString*) subFolder autoCreateDir:(BOOL) autoCreateDir;

+(NSString*)getResourcePath;
+(NSString*)getResourcePath: (NSString*) subFolder;
+(NSURL*)getEmbedResourceURLWithFilename:(NSString*) filename;
+(NSString*)getEmbedResourcePathWithFilename:(NSString*) filename;

+(NSMutableArray*)getFileList:(NSString*) path searchString:(NSString*)searchString isFullPath:(BOOL)isFullPath isIncludeSubFolder:(BOOL)isIncludeSubFolder filterListType:(enum GetFileListType) filterListType;
+(NSMutableArray*)getFileList:(NSString*) path searchString:(NSString*)searchString isFullPath:(BOOL)isFullPath;
+(NSMutableArray*)getFileList:(NSString*) path fileType:(NSString*) fileType isFullPath:(BOOL)isFullPath;
+(NSMutableArray*)getFileList:(NSString*) path fileType:(NSString*) fileType;

+(BOOL)createDirectory:(NSString*) path;
+(BOOL)removeFileOrDirectory:(NSString*) path;

+(void)saveImage:(UIImage *)photo path:(NSString *)path;
+(void)saveImage:(UIImage *)photo path:(NSString *)path jpgCompressLevel:(CGFloat) jpgCompressLevel;

+(UIImagePickerController*)showPickerController: (id) container sourceType:(UIImagePickerControllerSourceType) sourceType;

+(BOOL)writeFile: (NSString*) filePath content:(NSString*) content;
+(BOOL)writeFileInDocument: (NSString*) fileName content:(NSString*) content;
+(NSString*)readFile: (NSString*) filePath;
+(NSString*)readFileInDocument:(NSString*) fileName;
+(NSString*)readEmbedResourceFileWithFilename:(NSString *)filename;

+(BOOL)moveFileFromPath:(NSString*) fromPath toPath:(NSString*) toPath;
+(BOOL)copyFileFromPath:(NSString*) fromPath toPath:(NSString*) toPath;

+(BOOL)copyFolderFromPath:(NSString*) fromPath toPath:(NSString*) toPath;
+(BOOL)moveFolderFromPath:(NSString*) fromPath toPath:(NSString*) toPath;

+(ReturnSet*)renameFolderFromPath:(NSString*) fromPath toPath:(NSString*) toPath mergeFolderData:(BOOL) mergeFolderData removeOldFolder:(BOOL)removeOldFolder;

+(BOOL)checkPathExisted:(NSString*) path;
+(BOOL)checkPathIsDirectory:(NSString*) path;

+(NSString*)getNewName:(NSString*)prefix suffix:(NSString*)suffix;
+(NSString*)getNewNameYMDHMSWithPrefix:(NSString*)prefix suffix:(NSString*)suffix;
+(double)getFileSizeWithPath:(NSString*) path;
+(double)getFolderSizeWithPath:(NSString*) path includeSubFolder:(BOOL)includeSubFolder;

+(NSString*)genAutoFilenameWithSourcefile:(NSString*)sourcefile destinationFolder:(NSString*)destinationFolder;

+(NSArray*)sortFileList:(NSArray*) files sortType:(enum SortFileListType) sortType isSortAscending:(BOOL)isSortAscending;

@end


text:
// Package grpcrand implements math/rand functions in a concurrent-safe way
// with a global random source, independent of math/rand's global source.
package grpcrand

import (
	"math/rand"
	"sync"
	"time"
)

var (
	r  = rand.New(rand.NewSource(time.Now().UnixNano()))
	mu sync.Mutex
)

// Int63n implements rand.Int63n on the grpcrand global source.
func Int63n(n int64) int64 {
	mu.Lock()
	res := r.Int63n(n)
	mu.Unlock()
	return res
}

// Intn implements rand.Intn on the grpcrand global source.
func Intn(n int) int {
	mu.Lock()
	res := r.Intn(n)
	mu.Unlock()
	return res
}

// Float64 implements rand.Float64 on the grpcrand global source.
func Float64() float64 {
	mu.Lock()
	res := r.Float64()
	mu.Unlock()
	return res
}


text:
<!DOCTYPE html>

    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Plotting whitened data — MNE 0.16.1 documentation</title>
    <link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <link rel="stylesheet" href="../_static/gallery.css" type="text/css" />

    <link rel="shortcut icon" href="../_static/favicon.ico"/>
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />

    <link rel="stylesheet" href="../_static/style.css " type="text/css" />
    <link rel="stylesheet" href="../_static/font-awesome.css" type="text/css" />
    <link rel="stylesheet" href="../_static/flag-icon.css" type="text/css" />

  <link rel="canonical" href="https://mne.tools/stable/index.html" />

        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">

        </button>

        0.16.1

Install

Documentation

API

Examples

Contribute

  Site

  <button type="button" class="btn btn-primary navbar-btn dropdown-toggle" id="dropdownMenu1" data-toggle="dropdown">
    v0.16.1

  </button>

Development

v0.16 (stable)

v0.15

v0.14

v0.13

v0.12

v0.11

<form class="navbar-form navbar-right" action="../search.html" method="get">

  <input type="text" name="q" class="form-control" placeholder="Search" />

  <input type="hidden" name="check_keywords" value="yes" />
  <input type="hidden" name="area" value="default" />
</form>

Plotting whitened data

Raw data with whitening

Epochs with whitening

Evoked data with whitening

Evoked data with scaled whitening

Topographic plot with whitening

<form action="../search.html" method="get">

  <input type="text" name="q" class="form-control" placeholder="Search" />

  <input type="hidden" name="check_keywords" value="yes" />
  <input type="hidden" name="area" value="default" />
</form>

Note

Click here to download the full example code

Plotting whitened data¶

This tutorial demonstrates how to plot whitened evoked data.

Data are whitened for many processes, including dipole fitting, source
localization and some decoding algorithms. Viewing whitened data thus gives
a different perspective on the data that these algorithms operate on.

Let's start by loading some data and computing a signal (spatial) covariance
that we'll consider to be noise.

import mne
from mne.datasets import sample

Raw data with whitening¶

Note

In the mne.io.Raw.plot() with noise_cov supplied,
you can press they "w" key to turn whitening on and off.

data_path = sample.data_path()
raw_fname = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'
raw = mne.io.read_raw_fif(raw_fname, preload=True)

events = mne.find_events(raw, stim_channel='STI 014')
event_id = {'auditory/left': 1, 'auditory/right': 2, 'visual/left': 3,
            'visual/right': 4, 'smiley': 5, 'button': 32}
reject = dict(grad=4000e-13, mag=4e-12, eog=150e-6)
epochs = mne.Epochs(raw, events, event_id=event_id, reject=reject)

# baseline noise cov, not a lot of samples
noise_cov = mne.compute_covariance(epochs, tmax=0., method='shrunk',
                                   verbose='error')

# butterfly mode shows the differences most clearly
raw.plot(events=events, butterfly=True)
raw.plot(noise_cov=noise_cov, events=events, butterfly=True)

Epochs with whitening¶

epochs.plot()
epochs.plot(noise_cov=noise_cov)

Evoked data with whitening¶

evoked = epochs.average()
evoked.plot(time_unit='s')
evoked.plot(noise_cov=noise_cov, time_unit='s')

Evoked data with scaled whitening¶

The mne.Evoked.plot_white() function takes an additional step of
scaling the whitened plots to show how well the assumption of Gaussian
noise is satisfied by the data:

evoked.plot_white(noise_cov=noise_cov, time_unit='s')

Topographic plot with whitening¶

evoked.comment = 'All trials'
evoked.plot_topo(title='Evoked data')
evoked.plot_topo(noise_cov=noise_cov, title='Whitened evoked data')

Total running time of the script: ( 0 minutes  36.208 seconds)

Download Python source code: plot_whitened.py

Download Jupyter notebook: plot_whitened.ipynb

Gallery generated by Sphinx-Gallery

GitHub

·

Mailing list

·

Gitter

·

What's new

·

Cite MNE

Back to top

© Copyright 2012-2018, MNE Developers. Last updated on 2018-06-24.


text:
#pragma once
#include "Request.hpp"
#include "Response.hpp"
#include "Headers.hpp"
#include "Method.hpp"
#include "Time.hpp"
#include "net/Socket.hpp"
#include <ostream>
#include <sstream>

namespace http
{
    /**Writes the header text to the output stream.*/
    inline void write_headers(std::ostream &os, const Headers &headers)
    {
        for (auto &header : headers)
        {
            os << header.first << ": " << header.second << "\r\n";
        }
        os << "\r\n";
    }
    /**Writes the HTTP request first line and headers to the output stream.*/
    inline void write_request_header(std::ostream &os, const Request &request)
    {
        os << to_string(request.method) << " ";
        if (!request.raw_url.empty()) os << request.raw_url;
        else request.url.encode_request(os);
        os << " HTTP/1.1\r\n";
        write_headers(os, request.headers);
    }
    /**Writes the HTTP response first line and headers to the output stream.*/
    inline void write_response_header(std::ostream &os, const Response &response)
    {
        os << "HTTP/1.1 " << response.status.code << " " << response.status.msg << "\r\n";
        write_headers(os, response.headers);
    }
    /**Adds basic default headers to a request or response to be sent.
     * Currently this is just the "Date" header.
     */
    template<class T> void add_default_headers(T &message)
    {
        Headers &headers = message.headers;
        headers.set("Date", format_time(time(nullptr)));
    }

    /**Sends a HTTP client side request to the socket using Socket::send_all.*/
    inline void send_request(Socket *socket, Request &request)
    {
        if (!request.body.empty())
            request.headers.set("Content-Length", std::to_string(request.body.size()));
        std::stringstream ss;
        write_request_header(ss, request);
        auto ss_str = ss.str();
        socket->send_all(ss_str.data(), ss_str.size());
        if (!request.body.empty()) socket->send_all(request.body.data(), request.body.size());
    }

    /**Sends a HTTP server side response to the socket using Socket::send_all.*/
    inline void send_response(Socket *socket, const std::string &req_method, Response &response)
    {
        auto sc = response.status.code;
        //For certain response codes, there must not be a message body
        bool message_body_allowed = sc != 204 && sc != 205 && sc != 304;

       //For HEAD requests, Content-Length etc. should be determined, but the body must not be sent
        bool send_message_body = message_body_allowed && req_method != "HEAD";

        if (message_body_allowed)
        {
            //TODO: Support chunked streams in the future
            response.headers.set("Content-Length", std::to_string(response.body.size()));
        }
        else if (!response.body.empty())
        {
            throw std::runtime_error("HTTP forbids this response from having a body");
        }

        add_default_headers(response);
        std::stringstream ss;
        write_response_header(ss, response);
        auto ss_str = ss.str();
        socket->send_all(ss_str.data(), ss_str.size());

        if (send_message_body && !response.body.empty())
        {
            socket->send_all(response.body.data(), response.body.size());
        }
    }
}


text:
package org.zouzias.spark.lucenerdd.examples.linkage

import org.apache.lucene.index.Term
import org.apache.lucene.search.BooleanClause.Occur
import org.apache.lucene.search._
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, Row, SparkSession}
import org.zouzias.spark.lucenerdd.{LuceneRDD, _}
import org.zouzias.spark.lucenerdd.logging.Logging

/**
 * Record linkage example between amazon and itself blocked by manufacturer using
 * [[LuceneRDD.blockEntityLinkage]] method
 *
 * You can run this locally with ./spark-blocklinkage-amazon.sh
 */
object BlockEntityLinkageAmazon extends Logging {

  def main(args: Array[String]) {

    // initialise spark context
    val conf = new SparkConf().setAppName(LinkageGooglevsAmazon.getClass.getName)

    implicit val spark: SparkSession = SparkSession.builder.config(conf).getOrCreate()
    import spark.sqlContext.implicits._

    val start = System.currentTimeMillis()
    val amazonDF = spark.read.parquet("data/linkage-products1/linkage-products-amazon.parquet")
    logInfo(s"Loaded ${amazonDF.count} ACM records")

    val amazon = amazonDF.select("id", "title", "description", "manufacturer")

    // Custom linker
    val linker: Row => Query = { row => {

        val name = row.getString(row.fieldIndex("title"))
        val description = row.getString(row.fieldIndex("description"))
        val nameTokens = name.split(" ")
          .flatMap(_.replaceAll("[^a-zA-Z0-9]", " ").split(" "))
          .filter(_.length > 1)
          .distinct

        val descTerms = description.split(" ")
          .flatMap(_.replaceAll("[^a-zA-Z0-9]", " ").split(" "))
          .filter(_.length >= 2)
          .distinct

        val booleanQuery = new BooleanQuery.Builder()

        if (nameTokens.nonEmpty && descTerms.nonEmpty) {

          nameTokens.foreach{ name =>
            booleanQuery.add(new TermQuery(new Term("title", name.toLowerCase)),
              Occur.SHOULD)
          }

          descTerms.foreach{ name =>
            booleanQuery.add(new TermQuery(new Term("description", name.toLowerCase())),
              Occur.SHOULD)
          }

          booleanQuery.build()

        }
        else if (nameTokens.nonEmpty){
          nameTokens.foreach{ name =>
            booleanQuery.add(new TermQuery(new Term("title", name.toLowerCase())),
              Occur.SHOULD)
          }

          booleanQuery.build()
        }
        else {
          new MatchAllDocsQuery()
        }
      }
    }

    val blockingFields = Array("manufacturer")

    // Block entity linkage
    val linkedResults = LuceneRDD.blockEntityLinkage(amazon, amazon,
      linker, /* Link by title similarity */
      blockingFields, blockingFields)

    // Compute the performance of linkage (accuracy)
    val linkageResults: DataFrame = spark.createDataFrame(linkedResults
      .filter(_._2.nonEmpty)
      .map{ case (left, topDocs) =>
        (topDocs.head.get(topDocs.head.fieldIndex("id")),
          left.getString(left.fieldIndex("id"))
        )
      })
      .toDF("left_id", "right_id")
      .filter($"left_id".equalTo($"right_id"))

    val correctHits: Double = linkageResults.count()
    logInfo(s"Correct hits are $correctHits")
    val total: Double = amazonDF.count
    val accuracy = correctHits / total
    val end = System.currentTimeMillis()

    logInfo("=" * 40)
    logInfo(s"|| Elapsed time: ${(end - start) / 1000.0} seconds ||")
    logInfo("=" * 40)

    logInfo("*" * 40)
    logInfo(s"* Accuracy of deduplication is $accuracy *")
    logInfo("*" * 40)

    // terminate spark context
    spark.stop()
  }
}


text: assert.equal(++execution.index, 2);


text:
ROOT_DIR = ${CURDIR}
BUILD_DIR = ${CURDIR}/build
COMMON_DIR = ${CURDIR}/common
BOARDS_DIR = ${CURDIR}/boards

MODULES := $(COMMON_DIR) $(COMMON_DIR)/xt $(COMMON_DIR)/util $(COMMON_DIR)/ps2 $(COMMON_DIR)/keyevent $(COMMON_DIR)/keymap $(COMMON_DIR)/xt2ps2 $(COMMON_DIR)/console

VSEARCH_PATH = $(COMMON_DIR):$(BOARDS_DIR):$(COMMON_DIR)/util:$(COMMON_DIR)/xt:$(COMMON_DIR)/keyevent:$(COMMON_DIR)/ps2:$(COMMON_DIR)/keyevent:$(COMMON_DIR)/keymap:$(COMMON_DIR)/xt2ps2:$(COMMON_DIR)/console
VSEARCH_PATH += :$(BOARDS_DIR)/$(CURR_DIR)

export

ifeq ($(words $(MAKECMDGOALS)), 2)
	MK_TARGET = $(lastword $(MAKECMDGOALS))
endif

.PHONY: all
all: nano_mega328p pro_micro tiny85_revb

.PHONY: nano_mega328p pro_micro tiny85_revb

nano_mega328p pro_micro tiny85_revb: CURR_DIR = $@
nano_mega328p pro_micro tiny85_revb:
	make -f $(BOARDS_DIR)/$@/$@.mk

clean:
	rm -r build


text:
title: Datadog-Kyoto Tycoon Integration
integration_title: Kyoto Tycoon
kind: integration
doclevel: basic
---

Capture Kyoto Tycoon metrics in Datadog to:

* Visualize your database server performance
* Correlate the performance of Kyoto Tycoon with the rest of your applications


text:
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "target.h"
#include "gdbcore.h"
#include "gdbcmd.h"
#include "symfile.h"
#include "objfiles.h"
#include "regcache.h"
#include "value.h"
#include "osabi.h"
#include "regset.h"
#include "solib-svr4.h"
#include "microblaze-tdep.h"
#include "trad-frame.h"
#include "frame-unwind.h"
#include "tramp-frame.h"
#include "linux-tdep.h"

static int
microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
					   struct bp_target_info *bp_tgt)
{
  CORE_ADDR addr = bp_tgt->reqstd_address;
  const gdb_byte *bp;
  int val;
  int bplen;
  gdb_byte old_contents[BREAKPOINT_MAX];

  /* Determine appropriate breakpoint contents and size for this address.  */
  bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
  if (bp == NULL)
    error (_("Software breakpoints not implemented for this target."));

  val = target_read_memory (addr, old_contents, bplen);

  /* If our breakpoint is no longer at the address, this means that the
     program modified the code on us, so it is wrong to put back the
     old value.  */
  if (val == 0 && memcmp (bp, old_contents, bplen) == 0)
    val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen);

  return val;
}

static void
microblaze_linux_sigtramp_cache (struct frame_info *next_frame,
				 struct trad_frame_cache *this_cache,
				 CORE_ADDR func, LONGEST offset,
				 int bias)
{
  CORE_ADDR base;
  CORE_ADDR gpregs;
  int regnum;
  struct gdbarch *gdbarch = get_frame_arch (next_frame);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  base = frame_unwind_register_unsigned (next_frame, MICROBLAZE_SP_REGNUM);
  if (bias > 0 && get_frame_address_in_block (next_frame) != func)
    /* See below, some signal trampolines increment the stack as their
       first instruction, need to compensate for that.  */
    base -= bias;

  /* Find the address of the register buffer.  */
  gpregs = base + offset;

  /* Registers saved on stack.  */
  for (regnum = 0; regnum < MICROBLAZE_BTR_REGNUM; regnum++)
    trad_frame_set_reg_addr (this_cache, regnum,
			     gpregs + regnum * MICROBLAZE_REGISTER_SIZE);
  trad_frame_set_id (this_cache, frame_id_build (base, func));
}

static void
microblaze_linux_sighandler_cache_init (const struct tramp_frame *self,
					struct frame_info *next_frame,
					struct trad_frame_cache *this_cache,
					CORE_ADDR func)
{
  microblaze_linux_sigtramp_cache (next_frame, this_cache, func,
				   0 /* Offset to ucontext_t.  */
				   + 24 /* Offset to .reg.  */,
				   0);
}

static struct tramp_frame microblaze_linux_sighandler_tramp_frame =
{
  SIGTRAMP_FRAME,
  4,
  {
    { 0x31800077, -1 }, /* addik R12,R0,119.  */
    { 0xb9cc0008, -1 }, /* brki R14,8.  */
    { TRAMP_SENTINEL_INSN },
  },
  microblaze_linux_sighandler_cache_init
};

static void
microblaze_linux_init_abi (struct gdbarch_info info,
			   struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  linux_init_abi (info, gdbarch);

  set_gdbarch_memory_remove_breakpoint (gdbarch,
					microblaze_linux_memory_remove_breakpoint);

  /* Shared library handling.  */
  set_solib_svr4_fetch_link_map_offsets (gdbarch,
					 svr4_ilp32_fetch_link_map_offsets);

  /* Trampolines.  */
  tramp_frame_prepend_unwinder (gdbarch,
				&microblaze_linux_sighandler_tramp_frame);
}

/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_microblaze_linux_tdep;

void
_initialize_microblaze_linux_tdep (void)
{
  gdbarch_register_osabi (bfd_arch_microblaze, 0, GDB_OSABI_LINUX,
			  microblaze_linux_init_abi);
}


text:
var fs = require('fs');
// use path module
var path = require('path');

// function to list the contents of a directory according to a certain file extension
module.exports = function(dir_name, file_type, callback) {
        // use the built-in readdir function
        // demonstrates how callbacks truly work
        fs.readdir(dir_name, function(err, filenameList) {
                // throw an error to the user inputted callback function
                if (err) {
                        // still have access to callback because of closures
                        return callback(err, null);
                } else {
                        // only add files whose extension matches desired file type to the array
                        var filtered_list = [];
                        filenameList.forEach(function(file) {
                                if (path.extname(file).slice(1) == file_type) {
                                        filtered_list.push(file);
                                }});
                        callback(null, filtered_list);

                }
        });

}


text:
package com.jeecms.cms.manager.assist;

import java.util.Date;

import com.jeecms.cms.entity.assist.CmsSiteAccessPages;
import com.jeecms.common.page.Pagination;

/**
 * @author Tom
 */
public interface CmsSiteAccessPagesMng {

	public CmsSiteAccessPages save(CmsSiteAccessPages access);

	public CmsSiteAccessPages update(CmsSiteAccessPages access);

	public CmsSiteAccessPages findAccessPage(String sessionId, Integer pageIndex);

	public Pagination findPages(Integer siteId,Integer orderBy,Integer pageNo,Integer pageSize);

	public void clearByDate(Date date);
}


text:
@ECHO OFF

goto endOfComments

rem * Licensed to Apereo under one or more contributor license
rem * agreements. See the NOTICE file distributed with this work
rem * for additional information regarding copyright ownership.
rem * Apereo licenses this file to you under the Apache License,
rem * Version 2.0 (the "License"); you may not use this file
rem * except in compliance with the License.  You may obtain a
rem * copy of the License at the following location:
rem *
rem *   http://www.apache.org/licenses/LICENSE-2.0
rem *
rem * Unless required by applicable law or agreed to in writing,
rem * software distributed under the License is distributed on an
rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
rem * KIND, either express or implied.  See the License for the
rem * specific language governing permissions and limitations
rem * under the License.
rem */

rem
rem *** SSP Insert Student Users into SSP Training Script MSSQL Version ***
rem
rem This script adds a student that is able to login into SSP-Platform
rem  for SSP Training by using sed to substitute variables in the sql
rem  file with command line arguments of real values. This is then automatically
rem  executed for database 'ssp' using the psql command.
rem
rem Params: 1st arg string username for the new Student Login
rem	  2nd arg string password for the new Student Login (sha or md5 portalPassword format)
rem	  3rd arg string firstname for the new Student Login
rem	  4th arg string lastname for the new Student Login
rem
rem	  5th OPTIONAL arg number=1 to tell script to output to file
rem	 	instead of the db. File is set to
rem           ../mssql/sspTrainingDataCompiled(TODAY'S DATE).sql
rem
rem Note: Requires MSSQL 2008 or higher (SQL Script Dependency)
rem

:endOfComments

set "SQLFILEDIR=%~dp0..\..\dataScripts\mssql"
set "SETSTUDENTUSERSSQLFILE=sspTrainingAddUsers.sql"
set FILEDATESTAMP=%date:~4,2%-%date:~7,2%-%date:~10,4%
set "OUTPUTFILE=%~dp0..\..\..\mssql\sspTrainingDataCompiled%FILEDATESTAMP%.sql"

if exist "%SQLFILEDIR%\%SETSTUDENTUSERSSQLFILE%" (
    if "%6" == "" (
       if NOT "%5" == "" (
	       sqlcmd  -d ssp -i %SQLFILEDIR%\%SETSTUDENTUSERSSQLFILE% -v USERNAME="%1" USERPASSWORD="%2==" USERFIRSTNAME="%3" USERLASTNAME="%4" USERUUID="%5" USERROLE="STUDENT" USER_IS_MAP_TEMPLATE_ADMIN="0"

          exit /b %errorlevel%

       ) else (
          echo Not enough input arguments in script: sspTrainingSetStudentUsers.bat!
	  exit /b 1
       )

    rem Print To File Option
    ) else if "%7" == "" (
       if "%6" == "1" (

          sqlcmd  -d ssp -i %SQLFILEDIR%\%SETSTUDENTUSERSSQLFILE% -v USERNAME="%1" USERPASSWORD="%2==" USERFIRSTNAME="%3" USERLASTNAME="%4" USERUUID="%5" USERROLE="STUDENT" USER_IS_MAP_TEMPLATE_ADMIN="0" -e >> %OUTPUTFILE%

            exit /b %errorlevel%

        ) else (
           echo Improper sixth argument! Expected: 1  Recieved: %6
           exit /b 1
        )
    rem End Print To File Option

   ) else (
	echo Improper number of input arguments in script: sspTrainingSetStudentUsers.bat!
	exit /b 1
   )

) else (
   echo Script file: %SQLFILEDIR%\%SETSTUDENTUSERSSQLFILE% Not Found!
   exit /b 1
)

rem END OF SCRIPT


text:
<?php

namespace Sonata\AdminBundle\Form\Type\Filter;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * Class ChoiceType.
 *
 * @author  Thomas Rabaix <thomas.rabaix@sonata-project.org>
 */
class ChoiceType extends AbstractType
{
    const TYPE_CONTAINS = 1;

    const TYPE_NOT_CONTAINS = 2;

    const TYPE_EQUAL = 3;

    /**
     * @var TranslatorInterface
     */
    protected $translator;

    /**
     * @param TranslatorInterface $translator
     */
    public function __construct(TranslatorInterface $translator)
    {
        $this->translator = $translator;
    }

    /**
     * {@inheritdoc}
     *
     * @todo Remove when dropping Symfony <2.8 support
     */
    public function getName()
    {
        return $this->getBlockPrefix();
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'sonata_type_filter_choice';
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $choices = array(
            self::TYPE_CONTAINS     => $this->translator->trans('label_type_contains', array(), 'SonataAdminBundle'),
            self::TYPE_NOT_CONTAINS => $this->translator->trans('label_type_not_contains', array(), 'SonataAdminBundle'),
            self::TYPE_EQUAL        => $this->translator->trans('label_type_equals', array(), 'SonataAdminBundle'),
        );

        $operatorChoices = $options['operator_type'] !== 'hidden' ? array('choices' => $choices) : array();

        $builder
            ->add('type', $options['operator_type'], array_merge(array('required' => false), $options['operator_options'], $operatorChoices))
            ->add('value', $options['field_type'], array_merge(array('required' => false), $options['field_options']))
        ;
    }

    /**
     * {@inheritdoc}
     *
     * @todo Remove it when bumping requirements to SF 2.7+
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $this->configureOptions($resolver);
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'field_type'       => 'choice',
            'field_options'    => array(),
            'operator_type'    => 'choice',
            'operator_options' => array(),
        ));
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ArcGIS.Core.Data;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;

namespace CustomIdentify
{
    /// <summary>
    /// Implementation of custom pop-up tool.
    /// </summary>
    class CustomIdentify : MapTool
    {
        /// <summary>
        /// Define the tool as a sketch tool that draws a rectangle in screen space on the view.
        /// </summary>
        public CustomIdentify()
        {
            IsSketchTool = true;
            SketchType = SketchGeometryType.Rectangle;
            SketchOutputMode = SketchOutputMode.Screen;
        }
        /// <summary>
        /// Called when a sketch is completed.
        /// </summary>
        protected override async Task<bool> OnSketchCompleteAsync(Geometry geometry)
        {
            var popupContent = await QueuedTask.Run(() =>
            {
                var popupContents = new List<PopupContent>();
                var mapView = MapView.Active;
                if (mapView != null) {
                    //Get the features that intersect the sketch geometry.
                    var features = mapView.GetFeatures(geometry);
                    if (features.Count > 0) {
                        foreach (var kvp in features) {
                            var bfl = kvp.Key;
                            var oids = kvp.Value;
                            foreach (var objectID in oids) {
                                popupContents.Add(new DynamicPopupContent(bfl, objectID));
                            }
                        }
                    }
                }
                return popupContents;
            });

            MapView.Active.ShowCustomPopup(popupContent);
            return true;
        }

        //private static Dictionary<string, FeatureClass> _layersInMapFeatureClassMap = new Dictionary<string, FeatureClass>();

        //public static Dictionary<string, FeatureClass> LayersInMapFeatureClassMap = new Dictionary<string, FeatureClass>();

        //private Task<Geodatabase> GetGDBFromLyrAsync(BasicFeatureLayer lyr)
        //{
        //    return QueuedTask.Run(() =>  lyr.GetTable().GetDatastore() as Geodatabase);
        //}
    }
}


text:
Hack: YAML front matter is require here to tell Jekyll to process this files as a template. If only there were a better way...
---

{% include embed-api-snippet.html %}
<link rel="import" href="../assets/html/polymer.html">

<polymer-element name="ga-component">
  <script>

    Polymer('ga-component', {

      attached: function() {
        var self = this;
        gapi.analytics.ready(function() {
          self.embedLoad();
          gapi.analytics.auth.on('success', function() {
            self.embedAuthorize();
          })
        });
      },

      embedLoad: function() {
        // Override in sub-element.
      },

      embedAuthorize: function() {
        // Override in sub-element.
      },

      getParentDashboard: function() {
        var parent = this.parentElement;
        while (parent.nodeName.toLowerCase() != 'ga-dashboard') {
          parent = parent.parentElement;
          if (parent.nodeName.toLowerCase() == 'body') {
            throw new Error(this.nodeName.toLowerCase() +
                ' must be a child of a ga-dashboard element');
          }
        }
        return parent;
      }
    });
  </script>
</polymer-element>


text:
namespace MigAz.Azure.UserControls
{
    partial class IPv4AddressBox
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.txtIpAddress = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            //
            // txtIpAddress
            //
            this.txtIpAddress.Location = new System.Drawing.Point(0, 0);
            this.txtIpAddress.MaxLength = 15;
            this.txtIpAddress.Name = "txtIpAddress";
            this.txtIpAddress.Size = new System.Drawing.Size(100, 20);
            this.txtIpAddress.TabIndex = 0;
            this.txtIpAddress.TextChanged += new System.EventHandler(this.txtIpAddress_TextChanged);
            this.txtIpAddress.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtIpAddress_KeyPress);
            //
            // IPv4AddressBox
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.txtIpAddress);
            this.Name = "IPv4AddressBox";
            this.Size = new System.Drawing.Size(100, 20);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.TextBox txtIpAddress;
    }
}


text:
import {TestBed, async} from '@angular/core/testing';

import {AppComponent} from './app.component';
import {AppModule} from "./app.module";
import {APP_BASE_HREF} from "@angular/common";

describe('AppComponent', () => {
    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [AppModule],
            providers: [{provide: APP_BASE_HREF, useValue: '/'}]
        }).compileComponents();
    }));

    it('should create the app', async(() => {
        const fixture = TestBed.createComponent(AppComponent);
        const app = fixture.debugElement.componentInstance;
        expect(app).toBeTruthy();
    }));

    xit(`should have as title 'Jigsaw'`, async(() => {
        const fixture = TestBed.createComponent(AppComponent);
        const app = fixture.debugElement.componentInstance;
        expect(app.title).toEqual('Jigsaw');
    }));

    xit('should render title in a a tag', async(() => {
        const fixture = TestBed.createComponent(AppComponent);
        fixture.detectChanges();
        const compiled = fixture.debugElement.nativeElement;
        expect(compiled.querySelector('header h4 a').textContent).toContain('Jigsaw');
    }));
});


text:
package lcw

import (
	"strings"

	"github.com/pkg/errors"
)

// Scache wraps LoadingCache with partitions (sub-system), and scopes.
// Simplified interface with just 4 funcs - Get, Flush, Stats and Close
type Scache struct {
	lc LoadingCache
}

// NewScache creates Scache on top of LoadingCache
func NewScache(lc LoadingCache) *Scache {
	return &Scache{lc: lc}
}

// Get retrieves a key from underlying backend
func (m *Scache) Get(key Key, fn func() ([]byte, error)) (data []byte, err error) {
	keyStr := key.String()
	val, err := m.lc.Get(keyStr, func() (value interface{}, e error) {
		return fn()
	})
	return val.([]byte), err
}

// Stat delegates the call to the underlying cache backend
func (m *Scache) Stat() CacheStat {
	return m.lc.Stat()
}

// Close calls Close function of the underlying cache
func (m *Scache) Close() error {
	return m.lc.Close()
}

// Flush clears cache and calls postFlushFn async
func (m *Scache) Flush(req FlusherRequest) {
	if len(req.scopes) == 0 {
		m.lc.Purge()
		return
	}

	// check if fullKey has matching scopes
	inScope := func(fullKey string) bool {
		key, err := parseKey(fullKey)
		if err != nil {
			return false
		}
		for _, s := range req.scopes {
			for _, ks := range key.scopes {
				if ks == s {
					return true
				}
			}
		}
		return false
	}

	for _, k := range m.lc.Keys() {
		if inScope(k) {
			m.lc.Delete(k) // Keys() returns copy of cache's key, safe to remove directly
		}
	}
}

// Key for scoped cache. Created foe given partition (can be empty) and set with ID and Scopes.
// example: k := NewKey("sys1").ID(postID).Scopes("last_posts", customer_id)
type Key struct {
	id        string   // the primary part of the key, i.e. usual cache's key
	partition string   // optional id for a subsystem or cache partition
	scopes    []string // list of scopes to use in invalidation
}

// NewKey makes base key for given partition. Partition can be omitted.
func NewKey(partition ...string) Key {
	if len(partition) == 0 {
		return Key{partition: ""}
	}
	return Key{partition: partition[0]}
}

// ID sets key id
func (k Key) ID(id string) Key {
	k.id = id
	return k
}

// Scopes of the key
func (k Key) Scopes(scopes ...string) Key {
	k.scopes = scopes
	return k
}

// String makes full string key from primary key, partition and scopes
// key string made as <partition>@@<id>@@<scope1>$$<scope2>....
func (k Key) String() string {
	bld := strings.Builder{}
	_, _ = bld.WriteString(k.partition)
	_, _ = bld.WriteString("@@")
	_, _ = bld.WriteString(k.id)
	_, _ = bld.WriteString("@@")
	_, _ = bld.WriteString(strings.Join(k.scopes, "$$"))
	return bld.String()
}

// parseKey gets compound key string created by Key func and split it to the actual key, partition and scopes
// key string made as <partition>@@<id>@@<scope1>$$<scope2>....
func parseKey(keyStr string) (Key, error) {
	elems := strings.Split(keyStr, "@@")
	if len(elems) != 3 {
		return Key{}, errors.Errorf("can't parse cache key %s, invalid number of segments %d", keyStr, len(elems))
	}

	scopes := strings.Split(elems[2], "$$")
	if len(scopes) == 1 && scopes[0] == "" {
		scopes = []string{}
	}
	key := Key{
		partition: elems[0],
		id:        elems[1],
		scopes:    scopes,
	}

	return key, nil
}

// FlusherRequest used as input for cache.Flush
type FlusherRequest struct {
	partition string
	scopes    []string
}

// Flusher makes new FlusherRequest with empty scopes
func Flusher(partition string) FlusherRequest {
	res := FlusherRequest{partition: partition}
	return res
}

// Scopes adds scopes to FlusherRequest
func (f FlusherRequest) Scopes(scopes ...string) FlusherRequest {
	f.scopes = scopes
	return f
}