usergrid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From toddn...@apache.org
Subject [1/3] Initial import of 2.0 core persistence code.
Date Wed, 27 Nov 2013 22:24:42 GMT
Updated Branches:
  refs/heads/two-dot-o [created] ac634a1d0


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftest.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftest.java
new file mode 100644
index 0000000..7a71815
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftest.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest;
+
+import org.apache.usergrid.perftest.logging.Log;
+import org.slf4j.Logger;
+
+/**
+ * A performance test that does nothing.
+ */
+public class NoopPerftest implements Perftest {
+    @Log Logger log;
+
+
+    @Override
+    public int getCallCount() {
+        return 1000;
+    }
+
+
+    @Override
+    public int getThreadCount() {
+        return 10;
+    }
+
+
+    @Override
+    public int getDelayBetweenCalls() {
+        return 0;
+    }
+
+
+    @Override
+    public void call() {
+        log.info( "This performance test tests nothing" );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftestModule.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftestModule.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftestModule.java
new file mode 100644
index 0000000..1dbe087
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/NoopPerftestModule.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest;
+
+
+import com.google.inject.AbstractModule;
+
+
+/**
+ * A performance test module that does nothing.
+ */
+public class NoopPerftestModule extends AbstractModule {
+    @Override
+    protected void configure() {
+        bind( Perftest.class ).to( NoopPerftest.class );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/Perftest.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/Perftest.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/Perftest.java
new file mode 100644
index 0000000..14388e3
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/Perftest.java
@@ -0,0 +1,11 @@
+package org.apache.usergrid.perftest;
+
+/**
+ * A performance test that will be run.
+ */
+public interface Perftest {
+    int getCallCount();
+    int getThreadCount();
+    int getDelayBetweenCalls();
+    void call();
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestModule.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestModule.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestModule.java
new file mode 100644
index 0000000..9f8581b
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestModule.java
@@ -0,0 +1,47 @@
+/*
+ * Created by IntelliJ IDEA.
+ * User: akarasulu
+ * Date: 11/22/13
+ * Time: 11:44 PM
+ */
+package org.apache.usergrid.perftest;
+
+import org.apache.usergrid.perftest.logging.Slf4jTypeListener;
+import org.apache.usergrid.perftest.rest.*;
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import com.google.inject.matcher.Matchers;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import org.apache.usergrid.perfteststats.CallStats;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class PerftestModule extends ServletModule {
+    public static final String PACKAGES_KEY = "com.sun.jersey.config.property.packages";
+
+
+    protected void configureServlets() {
+        bindListener( Matchers.any(), new Slf4jTypeListener() );
+
+        // Hook Jersey into Guice Servlet
+        bind( GuiceContainer.class );
+
+        // Hook Jackson into Jersey as the POJO <-> JSON mapper
+        bind( JacksonJsonProvider.class ).asEagerSingleton();
+
+        bind( CallStats.class );
+        bind( PerftestRunner.class );
+        bind( TestModuleLoader.class );
+        bind( PerftestResetResource.class ).asEagerSingleton();
+        bind( PerftestStopResource.class ).asEagerSingleton();
+        bind( PerftestStartResource.class ).asEagerSingleton();
+        bind( PerftestStatsResource.class ).asEagerSingleton();
+        bind( PerftestStatusResource.class ).asEagerSingleton();
+
+        Map<String, String> params = new HashMap<String, String>();
+        params.put( PACKAGES_KEY, getClass().getPackage().toString() );
+        serve("/*").with( GuiceContainer.class, params );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestRunner.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestRunner.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestRunner.java
new file mode 100644
index 0000000..a8bd831
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestRunner.java
@@ -0,0 +1,197 @@
+package org.apache.usergrid.perftest;
+
+
+import com.netflix.blitz4j.LoggingConfiguration;
+import org.apache.usergrid.perftest.logging.Log;
+import org.apache.usergrid.perftest.rest.CallStatsSnapshot;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.netflix.config.DynamicLongProperty;
+import com.netflix.config.DynamicPropertyFactory;
+import org.apache.usergrid.perfteststats.CallStats;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+
+/**
+ * Invokes a Perftest based on a CallSpec.
+ */
+@Singleton
+public class PerftestRunner {
+    @Log
+    Logger log;
+
+
+    private final TestModuleLoader loader;
+    private final Injector injector;
+    private final Object lock = new Object();
+    private DynamicLongProperty sleepToStop = DynamicPropertyFactory.getInstance().getLongProperty( "sleep.to.stop", 100 );
+    private CallStats stats;
+    private List<Thread> threads = new ArrayList<Thread>();
+    private boolean stopSignal = false;
+    private boolean running = false;
+    private boolean needsReset = false;
+    private long startTime;
+    private long stopTime;
+
+
+    @Inject
+    public PerftestRunner( Injector injector, TestModuleLoader loader )
+    {
+        this.loader = loader;
+        this.injector = injector;
+        setup();
+    }
+
+
+    public void setup() {
+        synchronized ( lock ) {
+            this.threads.clear();
+            this.stopSignal = false;
+            this.running = false;
+            this.startTime = 0;
+            this.stopTime = 0;
+
+            this.stats = injector.getInstance( CallStats.class );
+            final Perftest test = loader.getChildInjector().getInstance(Perftest.class);
+
+            final long delay = test.getDelayBetweenCalls();
+            threads = new ArrayList<Thread>( test.getThreadCount() );
+            for ( int ii = 0; ii < test.getThreadCount(); ii++ ) {
+                threads.add( new Thread( new Runnable() {
+                    @Override
+                    public void run() {
+                        while( ( ! stopSignal ) && ( stats.getCallCount() < test.getCallCount() ) ) {
+                            long startTime = System.nanoTime();
+                            test.call();
+                            long endTime = System.nanoTime();
+                            stats.callOccurred( test, startTime, endTime, TimeUnit.NANOSECONDS );
+
+                            if ( delay > 0 )
+                            {
+                                try {
+                                    Thread.sleep( delay );
+                                } catch ( InterruptedException e ) {
+                                    log.error( "Thread was interrupted.", e );
+                                }
+                            }
+
+                            synchronized ( lock ) {
+                                lock.notifyAll();
+                            }
+                        }
+                    }
+                }) );
+            }
+
+            this.needsReset = false;
+        }
+    }
+
+
+    public CallStatsSnapshot getCallStatsSnapshot() {
+        return stats.getStatsSnapshot( isRunning(), getStartTime(), getStopTime() );
+    }
+
+
+    public boolean isRunning() {
+        synchronized ( lock ) {
+            return running;
+        }
+    }
+
+
+    public boolean needsReset() {
+        synchronized ( lock )
+        {
+            return needsReset;
+        }
+    }
+
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+
+    public long getStopTime() {
+        return stopTime;
+    }
+
+
+    public void start() {
+        synchronized ( lock ) {
+            stopSignal = false;
+            startTime = System.nanoTime();
+            running = true;
+            for ( Thread t : threads ) {
+                t.start();
+            }
+        }
+
+        // launch a coordinator thread to detect when all others are done
+        new Thread( new Runnable() {
+            @Override
+            public void run() {
+                while ( threadsRunning() )
+                {
+                    synchronized ( lock )
+                    {
+                        try {
+                            lock.wait( sleepToStop.get() );
+                            log.info( "woke up running = {}", PerftestRunner.this.running );
+                            lock.notifyAll();
+                        } catch (InterruptedException e) {
+                            log.error( "Thread interrupted while sleeping", e );
+                        }
+                    }
+                }
+
+                log.info( "COORDINATOR THREAD: all threads have died." );
+                PerftestRunner.this.running = false;
+                PerftestRunner.this.needsReset = true;
+                stopTime = System.nanoTime();
+            }
+        } ).start();
+    }
+
+
+    private boolean threadsRunning()
+    {
+        boolean anyAlive = false;
+
+        try {
+            Thread.sleep( sleepToStop.get() );
+        }
+        catch ( InterruptedException e ) {
+            log.error( "Thread was interrupted.", e );
+        }
+
+        for ( Thread t : threads )
+        {
+            anyAlive |= t.isAlive();
+        }
+
+        return anyAlive;
+    }
+
+
+    public void stop() {
+        synchronized ( lock ) {
+            stopSignal = true;
+            boolean anyAlive = false;
+
+            do {
+                anyAlive |= threadsRunning();
+            } while( anyAlive );
+
+            running = false;
+            stopTime = System.nanoTime();
+            needsReset = true;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestServletConfig.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestServletConfig.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestServletConfig.java
new file mode 100644
index 0000000..7f664a9
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/PerftestServletConfig.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.servlet.GuiceServletContextListener;
+import com.netflix.blitz4j.LoggingConfiguration;
+
+import javax.servlet.ServletContextEvent;
+
+/**
+ * ...
+ */
+public class PerftestServletConfig extends GuiceServletContextListener {
+    @Override
+    protected Injector getInjector() {
+        return Guice.createInjector( new PerftestModule() );
+    }
+
+
+    @Override
+    public void contextInitialized( ServletContextEvent servletContextEvent ) {
+        LoggingConfiguration.getInstance().configure();
+        super.contextInitialized( servletContextEvent );
+    }
+
+    @Override
+    public void contextDestroyed( ServletContextEvent servletContextEvent ) {
+        LoggingConfiguration.getInstance().stop();
+        super.contextDestroyed( servletContextEvent );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/TestModuleLoader.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/TestModuleLoader.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/TestModuleLoader.java
new file mode 100644
index 0000000..45c7ebd
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/TestModuleLoader.java
@@ -0,0 +1,95 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest;
+
+
+import com.google.inject.*;
+import com.netflix.config.DynamicPropertyFactory;
+import com.netflix.config.DynamicStringProperty;
+
+
+/**
+ * Dynamically loads the Guice Module responsible for creating the Perftest.
+ */
+@Singleton
+public class TestModuleLoader implements Runnable {
+    public static final String MOCK_TEST_MODULE = "org.apache.usergrid.perftest.NoopPerftestModule";
+
+    private final Injector injector;
+    private Injector childInjector;
+    private DynamicStringProperty testModuleFqcn;
+    private Module testModule;
+
+
+    @Inject
+    public TestModuleLoader( Injector injector )
+    {
+        this.injector = injector;
+        testModuleFqcn = DynamicPropertyFactory.getInstance().getStringProperty( "test.module.fqcn", MOCK_TEST_MODULE );
+
+        if ( testModuleFqcn.get().equals( MOCK_TEST_MODULE ) ) {
+            testModule = new NoopPerftestModule();
+        }
+        else {
+            testModule = loadTestModule();
+        }
+
+        childInjector = injector.createChildInjector( testModule );
+        testModuleFqcn.addCallback( this );
+    }
+
+
+    public Module loadTestModule() {
+        // This is a crappy mechanism now - we need to use OSGi for this
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+
+        try {
+            Class clazz = cl.loadClass( testModuleFqcn.get() );
+            return ( Module ) clazz.newInstance();
+        } catch ( ClassNotFoundException e ) {
+            e.printStackTrace();
+        } catch ( InstantiationException e ) {
+            e.printStackTrace();
+        } catch ( IllegalAccessException e ) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+
+    public Module getTestModule()
+    {
+        return testModule;
+    }
+
+
+    public Injector getChildInjector()
+    {
+        return childInjector;
+    }
+
+
+    @Override
+    public void run() {
+        testModule = loadTestModule();
+        childInjector = injector.createChildInjector( testModule );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Log.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Log.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Log.java
new file mode 100644
index 0000000..32ddfee
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Log.java
@@ -0,0 +1,19 @@
+package org.apache.usergrid.perftest.logging;
+
+import javax.inject.Scope;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation to use to inject a SLF4J Logger backed by Log4j.
+ */
+@Scope
+@Documented
+@Retention( RUNTIME )
+@Target( FIELD )
+public @interface Log {
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jMembersInjector.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jMembersInjector.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jMembersInjector.java
new file mode 100644
index 0000000..7ccbe7f
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jMembersInjector.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.logging;
+
+
+import com.google.inject.MembersInjector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+
+public class Slf4jMembersInjector<T> implements MembersInjector<T> {
+    private final Field field;
+    private final Logger logger;
+
+    public Slf4jMembersInjector(Field field) {
+        this.field = field;
+        this.logger = LoggerFactory.getLogger(field.getDeclaringClass());
+        field.setAccessible(true);
+    }
+
+    public void injectMembers(T t) {
+        try {
+            field.set(t, logger);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jTypeListener.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jTypeListener.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jTypeListener.java
new file mode 100644
index 0000000..7c43bd9
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/logging/Slf4jTypeListener.java
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.logging;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.TypeEncounter;
+import com.google.inject.spi.TypeListener;
+import org.slf4j.Logger;
+
+import java.lang.reflect.Field;
+
+/**
+ * ...
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class Slf4jTypeListener implements TypeListener {
+    public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) {
+        for (Field field : typeLiteral.getRawType().getDeclaredFields()) {
+            if (field.getType() == Logger.class
+                    && field.isAnnotationPresent(Log.class)) {
+                typeEncounter.register(new Slf4jMembersInjector<T>(field));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/CallStatsSnapshot.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/CallStatsSnapshot.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/CallStatsSnapshot.java
new file mode 100644
index 0000000..f1fdd78
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/CallStatsSnapshot.java
@@ -0,0 +1,91 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.rest;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * ...
+ */
+public class CallStatsSnapshot {
+    private final int callCount;
+    private final long maxTime;
+    private final long minTime;
+    private final long meanTime;
+    private final boolean running;
+    private final long startTime;
+    private final long stopTime;
+
+
+    public CallStatsSnapshot( int callCount, long maxTime, long minTime, long meanTime,
+                              boolean running, long startTime, long stopTime ) {
+        this.callCount = callCount;
+        this.maxTime = maxTime;
+        this.minTime = minTime;
+        this.meanTime = meanTime;
+        this.running = running;
+        this.startTime = startTime;
+        this.stopTime = stopTime;
+    }
+
+
+    @JsonProperty
+    public int getCallCount() {
+        return callCount;
+    }
+
+
+    @JsonProperty
+    public long getMaxTime() {
+        return maxTime;
+    }
+
+
+    @JsonProperty
+    public long getMinTime() {
+        return minTime;
+    }
+
+
+    @JsonProperty
+    public long getMeanTime() {
+        return meanTime;
+    }
+
+
+    @JsonProperty
+    public boolean isRunning() {
+        return running;
+    }
+
+
+    @JsonProperty
+    public long getStartTime()
+    {
+        return startTime;
+    }
+
+
+    @JsonProperty
+    public long getStopTime()
+    {
+        return stopTime;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestResetResource.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestResetResource.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestResetResource.java
new file mode 100644
index 0000000..402945b
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestResetResource.java
@@ -0,0 +1,64 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.rest;
+
+import org.apache.usergrid.perftest.PerftestRunner;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * ...
+ */
+@Singleton
+@Produces( MediaType.APPLICATION_JSON )
+@Path( "/perftest/reset" )
+public class PerftestResetResource {
+    private final PerftestRunner runner;
+
+
+    @Inject
+    public PerftestResetResource( PerftestRunner runner )
+    {
+        this.runner = runner;
+    }
+
+
+    @POST
+    public String reset()
+    {
+        if ( runner.isRunning() )
+        {
+            return "{ \"result\":\"still running stop before resetting\" }";
+        }
+
+        if ( runner.needsReset() )
+        {
+            runner.setup();
+            return "{ \"result\":\"reset complete\" }";
+        }
+
+        return "{ \"result\":\"reset not required\" }";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStartResource.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStartResource.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStartResource.java
new file mode 100644
index 0000000..0fb5705
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStartResource.java
@@ -0,0 +1,64 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.rest;
+
+import org.apache.usergrid.perftest.PerftestRunner;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * ...
+ */
+@Singleton
+@Produces( MediaType.APPLICATION_JSON )
+@Path( "/perftest/start" )
+public class PerftestStartResource {
+    private final PerftestRunner runner;
+
+
+    @Inject
+    public PerftestStartResource( PerftestRunner runner )
+    {
+        this.runner = runner;
+    }
+
+
+    @POST
+    public String start()
+    {
+        if ( runner.isRunning() )
+        {
+            return "{ \"result\":\"already running\" }";
+        }
+
+        if ( runner.needsReset() )
+        {
+            return "{ \"result\":\"reset needed - but save the last run data first!\" }";
+        }
+
+        runner.start();
+        return "{ \"result\":\"successfully started\" }";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatsResource.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatsResource.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatsResource.java
new file mode 100644
index 0000000..93c2f20
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatsResource.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.rest;
+
+import org.apache.usergrid.perftest.PerftestRunner;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * ...
+ */
+@Singleton
+@Produces( MediaType.APPLICATION_JSON )
+@Path( "/perftest/perfteststats" )
+public class PerftestStatsResource {
+    private final PerftestRunner runner;
+
+
+    @Inject
+    public PerftestStatsResource( PerftestRunner runner )
+    {
+        this.runner = runner;
+    }
+
+
+    @GET
+    public CallStatsSnapshot getCallStatsSnapshot()
+    {
+        return runner.getCallStatsSnapshot();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatusResource.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatusResource.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatusResource.java
new file mode 100644
index 0000000..b146661
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStatusResource.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.rest;
+
+import org.apache.usergrid.perftest.PerftestRunner;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * ...
+ */
+@Singleton
+@Produces( MediaType.APPLICATION_JSON )
+@Path( "/perftest/status" )
+public class PerftestStatusResource {
+    private final PerftestRunner runner;
+
+
+    @Inject
+    public PerftestStatusResource( PerftestRunner runner ) {
+        this.runner = runner;
+    }
+
+
+    @GET
+    public String status()
+    {
+        if ( runner.isRunning() )
+        {
+            return "{ \"status\":\"running\" }";
+        }
+
+        if ( runner.needsReset() )
+        {
+            return "{ \"status\":\"needs reset\" }";
+        }
+
+        return "{ \"status\":\"not running\" }";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStopResource.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStopResource.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStopResource.java
new file mode 100644
index 0000000..36d3590
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perftest/rest/PerftestStopResource.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perftest.rest;
+
+import org.apache.usergrid.perftest.PerftestRunner;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * ...
+ */
+@Singleton
+@Produces( MediaType.APPLICATION_JSON )
+@Path( "/perftest/stop" )
+public class PerftestStopResource {
+    private final PerftestRunner runner;
+
+
+    @Inject
+    public PerftestStopResource( PerftestRunner runner )
+    {
+        this.runner = runner;
+    }
+
+
+    @POST
+    public String stop()
+    {
+        if ( runner.isRunning() )
+        {
+            runner.stop();
+            return "{ \"result\":\"stopped\" }";
+        }
+
+        return "{ \"result\":\"already stopped\" }";
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perfteststats/CallStats.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perfteststats/CallStats.java b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perfteststats/CallStats.java
new file mode 100644
index 0000000..e0a09a0
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/java/org/apache/usergrid/perfteststats/CallStats.java
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.usergrid.perfteststats;
+
+
+import org.apache.usergrid.perftest.Perftest;
+import org.apache.usergrid.perftest.logging.Log;
+import org.apache.usergrid.perftest.rest.CallStatsSnapshot;
+import org.slf4j.Logger;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+/**
+ * Atomically stores and updates call statistics on tests.
+ */
+public class CallStats {
+    @Log Logger log;
+
+    private final AtomicInteger callCount = new AtomicInteger();
+    private final Object lock = new Object();
+    private final TimeUnit units = TimeUnit.NANOSECONDS;
+
+    private long maxTime = Long.MIN_VALUE;
+    private long minTime = Long.MAX_VALUE;
+    private long meanTime = 0;
+    private long totalTime = 0;
+
+
+    public int getCallCount() {
+        synchronized ( lock ) {
+            return callCount.get();
+        }
+    }
+
+
+    public CallStatsSnapshot getStatsSnapshot( boolean isRunning, long startTime, long stopTime ) {
+        synchronized ( lock )
+        {
+            return new CallStatsSnapshot( callCount.get(), maxTime, minTime, meanTime, isRunning, startTime, stopTime );
+        }
+    }
+
+
+    public int callOccurred( Perftest test, long startTime, long endTime, TimeUnit units )
+    {
+        synchronized ( lock )
+        {
+            if ( callCount.get() >  test.getCallCount() - 1 )
+            {
+                return callCount.get();
+            }
+
+            if ( this.units.equals( units ) ) {
+                long time = endTime - startTime;
+
+                totalTime += time;
+                maxTime = Math.max( maxTime, time );
+                minTime = Math.min( minTime, time );
+                int numCalls = callCount.incrementAndGet();
+                StringBuilder sb = new StringBuilder();
+                sb.append( numCalls ).append( " " ).append( startTime ).append( " " ).append( endTime );
+                log.debug(sb.toString());
+                meanTime = totalTime / numCalls;
+                return numCalls;
+            }
+            else {
+                throw new RuntimeException( "Time unit corrections have not been implemented." );
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/resources/config.properties
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/resources/config.properties b/stack/corepersistence/perftest/src/main/resources/config.properties
new file mode 100644
index 0000000..f411991
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/resources/config.properties
@@ -0,0 +1,22 @@
+default.call.iterations=10000
+default.thread.count=10
+default.configuration.override=simpledb
+
+archaius.deployment.environment=test
+archaius.deployment.region=us-east-1c
+archaius.deployment.datacenter=Virginia
+archaius.deployment.applicationId=corepersistence-perftests
+
+archaius.dynamicPropertyFactory.registerConfigWithJMX=true
+
+#com.netflix.config.dynamo.tableName=archaiusProperties
+#com.netflix.config.dynamo.keyAttributeName=key
+#com.netflix.config.dynamo.valueAttributeName=value
+#com.netflix.config.dynamo.contextKeyAttributeName=contextKey
+#com.netflix.config.dynamo.contextValueAttributeName=contextValue
+
+# Application Settings
+
+test.module.fqcn=org.apache.usergrid.perftest.NoopPerftestModule
+leep.to.stop=100
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/resources/log4j.properties b/stack/corepersistence/perftest/src/main/resources/log4j.properties
new file mode 100644
index 0000000..a114a72
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/resources/log4j.properties
@@ -0,0 +1,20 @@
+log4j.rootLogger=OFF
+log4j.rootCategory=OFF
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p %c{3}.%M(%L)<%t>- %m%n
+
+log4j.appender.results=org.apache.log4j.FileAppender
+log4j.appender.results.File=./results.log
+log4j.appender.results.layout=com.netflix.logging.log4jAdapter.NFPatternLayout
+log4j.appender.results.Append=true
+log4j.appender.results.layout.ConversionPattern=%m%n
+log4j.appender.results.Threshold=DEBUG
+
+log4j.logger.asyncAppenders=OFF,results,stdout
+batcher.com.netflix.logging.AsyncAppender.results.waitTimeinMillis=20000
+
+log4j.logger.org.apache.usergrid.perftest=INFO,stdout
+log4j.logger.org.apache.usergrid.perfteststats=DEBUG,results
+

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/perftest/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/perftest/src/main/webapp/WEB-INF/web.xml b/stack/corepersistence/perftest/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..310e6a3
--- /dev/null
+++ b/stack/corepersistence/perftest/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+  <display-name>Guice Servlet</display-name>
+
+  <session-config>
+    <session-timeout>30</session-timeout>
+  </session-config>
+ 
+  <listener>
+    <listener-class>
+      org.apache.usergrid.perftest.PerftestServletConfig
+    </listener-class>
+  </listener>
+
+  <filter>
+    <filter-name>Guice Filter</filter-name>
+    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
+  </filter>
+
+  <filter-mapping>
+    <filter-name>Guice Filter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+</web-app>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/pom.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/pom.xml b/stack/corepersistence/pom.xml
new file mode 100644
index 0000000..f09e9b0
--- /dev/null
+++ b/stack/corepersistence/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.usergrid</groupId>
+  <artifactId>persistence</artifactId>
+  <packaging>pom</packaging>
+  <version>1.0-SNAPSHOT</version>
+
+  <description>Prorotype for refactoring persistence of usergrid</description>
+
+  <properties >
+    <astynax.version>1.56.44</astynax.version>
+  </properties>
+
+  <modules>
+    <module>model</module>
+    <module>collection</module>
+    <module>index</module>
+    <module>testutils</module>
+    <!-- Removed perfest until the jackson/guice is sorted
+    <module>perftest</module> -->
+
+  </modules>
+
+
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/testutils/pom.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/testutils/pom.xml b/stack/corepersistence/testutils/pom.xml
new file mode 100644
index 0000000..f863cf5
--- /dev/null
+++ b/stack/corepersistence/testutils/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>persistence</artifactId>
+    <groupId>org.apache.usergrid</groupId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>testutils</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+    </dependency>
+
+    <!-- snappy for cassandra -->
+    <dependency>
+      <groupId>org.xerial.snappy</groupId>
+      <artifactId>snappy-java</artifactId>
+      <version>1.1.0.1</version>
+    </dependency>
+
+    <!-- cassandra runtime -->
+    <dependency>
+        <groupId>org.apache.cassandra</groupId>
+        <artifactId>cassandra-all</artifactId>
+        <version>1.2.11</version>
+    </dependency>
+
+
+    <dependency>
+      <groupId>com.netflix.astyanax</groupId>
+      <artifactId>astyanax-cassandra</artifactId>
+      <version>${astynax.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/AvailablePortFinder.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/AvailablePortFinder.java b/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/AvailablePortFinder.java
new file mode 100644
index 0000000..e2da676
--- /dev/null
+++ b/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/AvailablePortFinder.java
@@ -0,0 +1,187 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.usergrid.persistence.test;
+
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.TreeSet;
+
+
+/**
+ * Finds currently available server ports.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ * @see <a href="http://www.iana.org/assignments/port-numbers">IANA.org</a>
+ */
+public class AvailablePortFinder {
+    /** The minimum number of server port number. */
+    public static final int MIN_PORT_NUMBER = 1;
+
+    /** The maximum number of server port number. */
+    public static final int MAX_PORT_NUMBER = 49151;
+
+
+    /** Creates a new instance. */
+    private AvailablePortFinder() {
+        // Do nothing
+    }
+
+
+    /**
+     * Returns the {@link java.util.Set} of currently available port numbers ({@link Integer}).  This method is identical to
+     * <code>getAvailablePorts(MIN_PORT_NUMBER, MAX_PORT_NUMBER)</code>.
+     * <p/>
+     * WARNING: this can take a very long time.
+     */
+    public static Set<Integer> getAvailablePorts() {
+        return getAvailablePorts( MIN_PORT_NUMBER, MAX_PORT_NUMBER );
+    }
+
+
+    /**
+     * Gets an available port, selected by the system.
+     *
+     * @throws java.util.NoSuchElementException if there are no ports available
+     */
+    public static int getNextAvailable() {
+        ServerSocket serverSocket = null;
+
+        try {
+            // Here, we simply return an available port found by the system
+            serverSocket = new ServerSocket( 0 );
+            int port = serverSocket.getLocalPort();
+
+            // Don't forget to close the socket...
+            serverSocket.close();
+
+            return port;
+        }
+        catch ( IOException ioe ) {
+            throw new NoSuchElementException( ioe.getMessage() );
+        }
+    }
+
+
+    /**
+     * Gets the next available port starting at a port.
+     *
+     * @param fromPort the port to scan for availability
+     *
+     * @throws java.util.NoSuchElementException if there are no ports available
+     */
+    public static int getNextAvailable( int fromPort ) {
+        if ( fromPort < MIN_PORT_NUMBER || fromPort > MAX_PORT_NUMBER ) {
+            throw new IllegalArgumentException( "Invalid start port: " + fromPort );
+        }
+
+        for ( int i = fromPort; i <= MAX_PORT_NUMBER; i++ ) {
+            if ( available( i ) ) {
+                return i;
+            }
+        }
+
+        throw new NoSuchElementException( "Could not find an available port " + "above " + fromPort );
+    }
+
+
+    /**
+     * Checks to see if a specific port is available.
+     *
+     * @param port the port to check for availability
+     */
+    public static boolean available( int port ) {
+        if ( port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER ) {
+            throw new IllegalArgumentException( "Invalid start port: " + port );
+        }
+
+        ServerSocket ss = null;
+        DatagramSocket ds = null;
+
+        try {
+            ss = new ServerSocket( port );
+            ss.setReuseAddress( true );
+            ds = new DatagramSocket( port );
+            ds.setReuseAddress( true );
+            return true;
+        }
+        catch ( IOException e ) {
+            // Do nothing
+        }
+        finally {
+            if ( ds != null ) {
+                ds.close();
+            }
+
+            if ( ss != null ) {
+                try {
+                    ss.close();
+                }
+                catch ( IOException e ) {
+                    /* should not be thrown */
+                }
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Returns the {@link java.util.Set} of currently avaliable port numbers ({@link Integer}) between the specified port range.
+     *
+     * @throws IllegalArgumentException if port range is not between {@link #MIN_PORT_NUMBER} and {@link
+     * #MAX_PORT_NUMBER} or <code>fromPort</code> if greater than <code>toPort</code>.
+     */
+    public static Set<Integer> getAvailablePorts( int fromPort, int toPort ) {
+        if ( fromPort < MIN_PORT_NUMBER || toPort > MAX_PORT_NUMBER || fromPort > toPort ) {
+            throw new IllegalArgumentException( "Invalid port range: " + fromPort + " ~ " + toPort );
+        }
+
+        Set<Integer> result = new TreeSet<Integer>();
+
+        for ( int i = fromPort; i <= toPort; i++ ) {
+            ServerSocket s = null;
+
+            try {
+                s = new ServerSocket( i );
+                result.add( new Integer( i ) );
+            }
+            catch ( IOException e ) {
+                // Do nothing
+            }
+            finally {
+                if ( s != null ) {
+                    try {
+                        s.close();
+                    }
+                    catch ( IOException e ) {
+                        /* should not be thrown */
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/CassandraRule.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/CassandraRule.java b/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/CassandraRule.java
new file mode 100644
index 0000000..989c00c
--- /dev/null
+++ b/stack/corepersistence/testutils/src/main/java/org/apache/usergrid/persistence/test/CassandraRule.java
@@ -0,0 +1,86 @@
+package org.apache.usergrid.persistence.test;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.rules.ExternalResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.cassandra.io.util.FileUtils;
+
+import com.google.common.io.Files;
+import com.netflix.astyanax.test.EmbeddedCassandra;
+
+
+/**
+ * TODO, not sure if this is a hack,
+ *
+ * @author tnine
+ */
+public class CassandraRule extends ExternalResource {
+
+    private static final Logger logger = LoggerFactory.getLogger( CassandraRule.class );
+
+    public static final int THRIFT_PORT = AvailablePortFinder.getNextAvailable();
+
+    public static final int GOSSIP_PORT = AvailablePortFinder.getNextAvailable();
+
+
+    private static final Object mutex = new Object();
+
+    private static EmbeddedCassandra cass;
+
+    private static boolean started = false;
+
+    @Override
+    protected void before() throws Throwable {
+
+        if ( started ) {
+            return;
+        }
+
+        synchronized ( mutex ) {
+
+            //we're late to the party, bail
+            if ( started ) {
+                return;
+            }
+
+
+            File dataDir = Files.createTempDir();
+            dataDir.deleteOnExit();
+
+
+
+            //cleanup before we run, shouldn't be necessary, but had the directory exist during JVM kill
+            if(dataDir.exists()){
+                FileUtils.deleteRecursive(dataDir);
+            }
+
+            try {
+                logger.info( "Starting cassandra" );
+
+                cass = new EmbeddedCassandra( dataDir, "Usergrid", THRIFT_PORT, GOSSIP_PORT );
+                cass.start();
+
+                logger.info( "Cassandra started" );
+
+                started = true;
+            }
+            catch ( IOException e ) {
+                throw new RuntimeException( "Unable to start cassandra", e );
+            }
+        }
+    }
+
+
+    @Override
+    protected void after() {
+
+        //TODO TN.  this should only really happen when we shut down
+//        cass.stop();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/testutils/src/main/resources/log4j-server.properties
----------------------------------------------------------------------
diff --git a/stack/corepersistence/testutils/src/main/resources/log4j-server.properties b/stack/corepersistence/testutils/src/main/resources/log4j-server.properties
new file mode 100644
index 0000000..cf22bca
--- /dev/null
+++ b/stack/corepersistence/testutils/src/main/resources/log4j-server.properties
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# for production, you should probably set pattern to %c instead of %l.  
+# (%l is slower.)
+
+# output messages into a rolling log file as well as stdout
+log4j.rootLogger=INFO,stdout
+
+# stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
+
+
+# Application logging options
+#log4j.logger.org.apache.cassandra=DEBUG
+#log4j.logger.org.apache.cassandra.db=DEBUG
+#log4j.logger.org.apache.cassandra.service.StorageProxy=DEBUG
+
+# Adding this to avoid thrift logging disconnect errors.
+log4j.logger.org.apache.thrift.server.TNonblockingServer=ERROR

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/ac634a1d/stack/corepersistence/testutils/src/main/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/stack/corepersistence/testutils/src/main/resources/log4j.xml b/stack/corepersistence/testutils/src/main/resources/log4j.xml
new file mode 100644
index 0000000..2db8103
--- /dev/null
+++ b/stack/corepersistence/testutils/src/main/resources/log4j.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+    <appender class="org.apache.log4j.ConsoleAppender" name="stdout">
+        <layout class="org.apache.log4j.PatternLayout">
+            <param value="%d %p (%t) [%c] - %m%n" name="ConversionPattern"/>
+        </layout>
+    </appender>
+    <logger name="org.apache">
+        <level value="info"/>
+    </logger>
+    <root>
+        <level value="debug"/>
+        <appender-ref ref="stdout"/>
+    </root>
+</log4j:configuration>


Mime
View raw message